1/* 2 * Sierra VMD video decoder 3 * Copyright (C) 2004 the ffmpeg project 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Sierra VMD video decoder 25 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru) 26 * for more information on the Sierra VMD format, visit: 27 * http://www.pcisys.net/~melanson/codecs/ 28 * 29 * The video decoder outputs PAL8 colorspace data. The decoder expects 30 * a 0x330-byte VMD file header to be transmitted via extradata during 31 * codec initialization. Each encoded frame that is sent to this decoder 32 * is expected to be prepended with the appropriate 16-byte frame 33 * information record from the VMD file. 34 */ 35 36#include <string.h> 37 38#include "libavutil/common.h" 39#include "libavutil/intreadwrite.h" 40 41#include "avcodec.h" 42#include "internal.h" 43#include "bytestream.h" 44 45#define VMD_HEADER_SIZE 0x330 46#define PALETTE_COUNT 256 47 48typedef struct VmdVideoContext { 49 50 AVCodecContext *avctx; 51 AVFrame *prev_frame; 52 53 const unsigned char *buf; 54 int size; 55 56 unsigned char palette[PALETTE_COUNT * 4]; 57 unsigned char *unpack_buffer; 58 int unpack_buffer_size; 59 60 int x_off, y_off; 61} VmdVideoContext; 62 63#define QUEUE_SIZE 0x1000 64#define QUEUE_MASK 0x0FFF 65 66static int lz_unpack(const unsigned char *src, int src_len, 67 unsigned char *dest, int dest_len) 68{ 69 unsigned char *d; 70 unsigned char *d_end; 71 unsigned char queue[QUEUE_SIZE]; 72 unsigned int qpos; 73 unsigned int dataleft; 74 unsigned int chainofs; 75 unsigned int chainlen; 76 unsigned int speclen; 77 unsigned char tag; 78 unsigned int i, j; 79 GetByteContext gb; 80 81 bytestream2_init(&gb, src, src_len); 82 d = dest; 83 d_end = d + dest_len; 84 dataleft = bytestream2_get_le32(&gb); 85 memset(queue, 0x20, QUEUE_SIZE); 86 if (bytestream2_get_bytes_left(&gb) < 4) 87 return AVERROR_INVALIDDATA; 88 if (bytestream2_peek_le32(&gb) == 0x56781234) { 89 bytestream2_skipu(&gb, 4); 90 qpos = 0x111; 91 speclen = 0xF + 3; 92 } else { 93 qpos = 0xFEE; 94 speclen = 100; /* no speclen */ 95 } 96 97 while (dataleft > 0 && bytestream2_get_bytes_left(&gb) > 0) { 98 tag = bytestream2_get_byteu(&gb); 99 if ((tag == 0xFF) && (dataleft > 8)) { 100 if (d_end - d < 8 || bytestream2_get_bytes_left(&gb) < 8) 101 return AVERROR_INVALIDDATA; 102 for (i = 0; i < 8; i++) { 103 queue[qpos++] = *d++ = bytestream2_get_byteu(&gb); 104 qpos &= QUEUE_MASK; 105 } 106 dataleft -= 8; 107 } else { 108 for (i = 0; i < 8; i++) { 109 if (dataleft == 0) 110 break; 111 if (tag & 0x01) { 112 if (d_end - d < 1 || bytestream2_get_bytes_left(&gb) < 1) 113 return AVERROR_INVALIDDATA; 114 queue[qpos++] = *d++ = bytestream2_get_byteu(&gb); 115 qpos &= QUEUE_MASK; 116 dataleft--; 117 } else { 118 chainofs = bytestream2_get_byte(&gb); 119 chainofs |= ((bytestream2_peek_byte(&gb) & 0xF0) << 4); 120 chainlen = (bytestream2_get_byte(&gb) & 0x0F) + 3; 121 if (chainlen == speclen) { 122 chainlen = bytestream2_get_byte(&gb) + 0xF + 3; 123 } 124 if (d_end - d < chainlen) 125 return AVERROR_INVALIDDATA; 126 for (j = 0; j < chainlen; j++) { 127 *d = queue[chainofs++ & QUEUE_MASK]; 128 queue[qpos++] = *d++; 129 qpos &= QUEUE_MASK; 130 } 131 dataleft -= chainlen; 132 } 133 tag >>= 1; 134 } 135 } 136 } 137 return d - dest; 138} 139static int rle_unpack(const unsigned char *src, unsigned char *dest, 140 int src_count, int src_size, int dest_len) 141{ 142 unsigned char *pd; 143 int i, l, used = 0; 144 unsigned char *dest_end = dest + dest_len; 145 GetByteContext gb; 146 uint16_t run_val; 147 148 bytestream2_init(&gb, src, src_size); 149 pd = dest; 150 if (src_count & 1) { 151 if (bytestream2_get_bytes_left(&gb) < 1) 152 return 0; 153 *pd++ = bytestream2_get_byteu(&gb); 154 used++; 155 } 156 157 do { 158 if (bytestream2_get_bytes_left(&gb) < 1) 159 break; 160 l = bytestream2_get_byteu(&gb); 161 if (l & 0x80) { 162 l = (l & 0x7F) * 2; 163 if (dest_end - pd < l || bytestream2_get_bytes_left(&gb) < l) 164 return bytestream2_tell(&gb); 165 bytestream2_get_bufferu(&gb, pd, l); 166 pd += l; 167 } else { 168 if (dest_end - pd < 2*l || bytestream2_get_bytes_left(&gb) < 2) 169 return bytestream2_tell(&gb); 170 run_val = bytestream2_get_ne16(&gb); 171 for (i = 0; i < l; i++) { 172 AV_WN16(pd, run_val); 173 pd += 2; 174 } 175 l *= 2; 176 } 177 used += l; 178 } while (used < src_count); 179 180 return bytestream2_tell(&gb); 181} 182 183static int vmd_decode(VmdVideoContext *s, AVFrame *frame) 184{ 185 int i; 186 unsigned int *palette32; 187 unsigned char r, g, b; 188 189 GetByteContext gb; 190 191 unsigned char meth; 192 unsigned char *dp; /* pointer to current frame */ 193 unsigned char *pp; /* pointer to previous frame */ 194 unsigned char len; 195 int ofs; 196 197 int frame_x, frame_y; 198 int frame_width, frame_height; 199 200 frame_x = AV_RL16(&s->buf[6]); 201 frame_y = AV_RL16(&s->buf[8]); 202 frame_width = AV_RL16(&s->buf[10]) - frame_x + 1; 203 frame_height = AV_RL16(&s->buf[12]) - frame_y + 1; 204 205 if ((frame_width == s->avctx->width && frame_height == s->avctx->height) && 206 (frame_x || frame_y)) { 207 208 s->x_off = frame_x; 209 s->y_off = frame_y; 210 } 211 frame_x -= s->x_off; 212 frame_y -= s->y_off; 213 214 if (frame_x < 0 || frame_width < 0 || 215 frame_x >= s->avctx->width || 216 frame_width > s->avctx->width || 217 frame_x + frame_width > s->avctx->width) { 218 av_log(s->avctx, AV_LOG_ERROR, 219 "Invalid horizontal range %d-%d\n", 220 frame_x, frame_width); 221 return AVERROR_INVALIDDATA; 222 } 223 if (frame_y < 0 || frame_height < 0 || 224 frame_y >= s->avctx->height || 225 frame_height > s->avctx->height || 226 frame_y + frame_height > s->avctx->height) { 227 av_log(s->avctx, AV_LOG_ERROR, 228 "Invalid vertical range %d-%d\n", 229 frame_x, frame_width); 230 return AVERROR_INVALIDDATA; 231 } 232 233 /* if only a certain region will be updated, copy the entire previous 234 * frame before the decode */ 235 if (s->prev_frame->data[0] && 236 (frame_x || frame_y || (frame_width != s->avctx->width) || 237 (frame_height != s->avctx->height))) { 238 239 memcpy(frame->data[0], s->prev_frame->data[0], 240 s->avctx->height * frame->linesize[0]); 241 } 242 243 /* check if there is a new palette */ 244 bytestream2_init(&gb, s->buf + 16, s->size - 16); 245 if (s->buf[15] & 0x02) { 246 bytestream2_skip(&gb, 2); 247 palette32 = (unsigned int *)s->palette; 248 if (bytestream2_get_bytes_left(&gb) >= PALETTE_COUNT * 3) { 249 for (i = 0; i < PALETTE_COUNT; i++) { 250 r = bytestream2_get_byteu(&gb) * 4; 251 g = bytestream2_get_byteu(&gb) * 4; 252 b = bytestream2_get_byteu(&gb) * 4; 253 palette32[i] = 0xFFU << 24 | (r << 16) | (g << 8) | (b); 254 palette32[i] |= palette32[i] >> 6 & 0x30303; 255 } 256 } else { 257 av_log(s->avctx, AV_LOG_ERROR, "Incomplete palette\n"); 258 return AVERROR_INVALIDDATA; 259 } 260 } 261 262 if (!s->size) 263 return 0; 264 265 /* originally UnpackFrame in VAG's code */ 266 if (bytestream2_get_bytes_left(&gb) < 1) 267 return AVERROR_INVALIDDATA; 268 meth = bytestream2_get_byteu(&gb); 269 if (meth & 0x80) { 270 int size; 271 if (!s->unpack_buffer_size) { 272 av_log(s->avctx, AV_LOG_ERROR, 273 "Trying to unpack LZ-compressed frame with no LZ buffer\n"); 274 return AVERROR_INVALIDDATA; 275 } 276 size = lz_unpack(gb.buffer, bytestream2_get_bytes_left(&gb), 277 s->unpack_buffer, s->unpack_buffer_size); 278 if (size < 0) 279 return size; 280 meth &= 0x7F; 281 bytestream2_init(&gb, s->unpack_buffer, size); 282 } 283 284 dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x]; 285 pp = &s->prev_frame->data[0][frame_y * s->prev_frame->linesize[0] + frame_x]; 286 switch (meth) { 287 case 1: 288 for (i = 0; i < frame_height; i++) { 289 ofs = 0; 290 do { 291 len = bytestream2_get_byte(&gb); 292 if (len & 0x80) { 293 len = (len & 0x7F) + 1; 294 if (ofs + len > frame_width || 295 bytestream2_get_bytes_left(&gb) < len) 296 return AVERROR_INVALIDDATA; 297 bytestream2_get_bufferu(&gb, &dp[ofs], len); 298 ofs += len; 299 } else { 300 /* interframe pixel copy */ 301 if (ofs + len + 1 > frame_width || !s->prev_frame->data[0]) 302 return AVERROR_INVALIDDATA; 303 memcpy(&dp[ofs], &pp[ofs], len + 1); 304 ofs += len + 1; 305 } 306 } while (ofs < frame_width); 307 if (ofs > frame_width) { 308 av_log(s->avctx, AV_LOG_ERROR, 309 "offset > width (%d > %d)\n", 310 ofs, frame_width); 311 return AVERROR_INVALIDDATA; 312 } 313 dp += frame->linesize[0]; 314 pp += s->prev_frame->linesize[0]; 315 } 316 break; 317 318 case 2: 319 for (i = 0; i < frame_height; i++) { 320 bytestream2_get_buffer(&gb, dp, frame_width); 321 dp += frame->linesize[0]; 322 pp += s->prev_frame->linesize[0]; 323 } 324 break; 325 326 case 3: 327 for (i = 0; i < frame_height; i++) { 328 ofs = 0; 329 do { 330 len = bytestream2_get_byte(&gb); 331 if (len & 0x80) { 332 len = (len & 0x7F) + 1; 333 if (bytestream2_peek_byte(&gb) == 0xFF) { 334 int slen = len; 335 bytestream2_get_byte(&gb); 336 len = rle_unpack(gb.buffer, &dp[ofs], 337 len, bytestream2_get_bytes_left(&gb), 338 frame_width - ofs); 339 ofs += slen; 340 bytestream2_skip(&gb, len); 341 } else { 342 bytestream2_get_buffer(&gb, &dp[ofs], len); 343 ofs += len; 344 } 345 } else { 346 /* interframe pixel copy */ 347 if (ofs + len + 1 > frame_width || !s->prev_frame->data[0]) 348 return AVERROR_INVALIDDATA; 349 memcpy(&dp[ofs], &pp[ofs], len + 1); 350 ofs += len + 1; 351 } 352 } while (ofs < frame_width); 353 if (ofs > frame_width) { 354 av_log(s->avctx, AV_LOG_ERROR, 355 "offset > width (%d > %d)\n", 356 ofs, frame_width); 357 return AVERROR_INVALIDDATA; 358 } 359 dp += frame->linesize[0]; 360 pp += s->prev_frame->linesize[0]; 361 } 362 break; 363 } 364 return 0; 365} 366 367static av_cold int vmdvideo_decode_end(AVCodecContext *avctx) 368{ 369 VmdVideoContext *s = avctx->priv_data; 370 371 av_frame_free(&s->prev_frame); 372 av_freep(&s->unpack_buffer); 373 s->unpack_buffer_size = 0; 374 375 return 0; 376} 377 378static av_cold int vmdvideo_decode_init(AVCodecContext *avctx) 379{ 380 VmdVideoContext *s = avctx->priv_data; 381 int i; 382 unsigned int *palette32; 383 int palette_index = 0; 384 unsigned char r, g, b; 385 unsigned char *vmd_header; 386 unsigned char *raw_palette; 387 388 s->avctx = avctx; 389 avctx->pix_fmt = AV_PIX_FMT_PAL8; 390 391 /* make sure the VMD header made it */ 392 if (s->avctx->extradata_size != VMD_HEADER_SIZE) { 393 av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", 394 VMD_HEADER_SIZE); 395 return AVERROR_INVALIDDATA; 396 } 397 vmd_header = (unsigned char *)avctx->extradata; 398 399 s->unpack_buffer_size = AV_RL32(&vmd_header[800]); 400 if (s->unpack_buffer_size) { 401 s->unpack_buffer = av_malloc(s->unpack_buffer_size); 402 if (!s->unpack_buffer) 403 return AVERROR(ENOMEM); 404 } 405 406 /* load up the initial palette */ 407 raw_palette = &vmd_header[28]; 408 palette32 = (unsigned int *)s->palette; 409 for (i = 0; i < PALETTE_COUNT; i++) { 410 r = raw_palette[palette_index++] * 4; 411 g = raw_palette[palette_index++] * 4; 412 b = raw_palette[palette_index++] * 4; 413 palette32[i] = 0xFFU << 24 | (r << 16) | (g << 8) | (b); 414 palette32[i] |= palette32[i] >> 6 & 0x30303; 415 } 416 417 s->prev_frame = av_frame_alloc(); 418 if (!s->prev_frame) { 419 vmdvideo_decode_end(avctx); 420 return AVERROR(ENOMEM); 421 } 422 423 return 0; 424} 425 426static int vmdvideo_decode_frame(AVCodecContext *avctx, 427 void *data, int *got_frame, 428 AVPacket *avpkt) 429{ 430 const uint8_t *buf = avpkt->data; 431 int buf_size = avpkt->size; 432 VmdVideoContext *s = avctx->priv_data; 433 AVFrame *frame = data; 434 int ret; 435 436 s->buf = buf; 437 s->size = buf_size; 438 439 if (buf_size < 16) 440 return AVERROR_INVALIDDATA; 441 442 if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) 443 return ret; 444 445 if ((ret = vmd_decode(s, frame)) < 0) 446 return ret; 447 448 /* make the palette available on the way out */ 449 memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4); 450 451 /* shuffle frames */ 452 av_frame_unref(s->prev_frame); 453 if ((ret = av_frame_ref(s->prev_frame, frame)) < 0) 454 return ret; 455 456 *got_frame = 1; 457 458 /* report that the buffer was completely consumed */ 459 return buf_size; 460} 461 462AVCodec ff_vmdvideo_decoder = { 463 .name = "vmdvideo", 464 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"), 465 .type = AVMEDIA_TYPE_VIDEO, 466 .id = AV_CODEC_ID_VMDVIDEO, 467 .priv_data_size = sizeof(VmdVideoContext), 468 .init = vmdvideo_decode_init, 469 .close = vmdvideo_decode_end, 470 .decode = vmdvideo_decode_frame, 471 .capabilities = CODEC_CAP_DR1, 472}; 473