00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045
00046 #include "libavutil/intreadwrite.h"
00047 #include "avcodec.h"
00048
00049 #define VMD_HEADER_SIZE 0x330
00050 #define PALETTE_COUNT 256
00051
00052
00053
00054
00055
00056 typedef struct VmdVideoContext {
00057
00058 AVCodecContext *avctx;
00059 AVFrame frame;
00060 AVFrame prev_frame;
00061
00062 const unsigned char *buf;
00063 int size;
00064
00065 unsigned char palette[PALETTE_COUNT * 4];
00066 unsigned char *unpack_buffer;
00067 int unpack_buffer_size;
00068
00069 int x_off, y_off;
00070 } VmdVideoContext;
00071
00072 #define QUEUE_SIZE 0x1000
00073 #define QUEUE_MASK 0x0FFF
00074
00075 static void lz_unpack(const unsigned char *src, int src_len,
00076 unsigned char *dest, int dest_len)
00077 {
00078 const unsigned char *s;
00079 const unsigned char *s_end;
00080 unsigned char *d;
00081 unsigned char *d_end;
00082 unsigned char queue[QUEUE_SIZE];
00083 unsigned int qpos;
00084 unsigned int dataleft;
00085 unsigned int chainofs;
00086 unsigned int chainlen;
00087 unsigned int speclen;
00088 unsigned char tag;
00089 unsigned int i, j;
00090
00091 s = src;
00092 s_end = src + src_len;
00093 d = dest;
00094 d_end = d + dest_len;
00095
00096 if (s_end - s < 8)
00097 return;
00098 dataleft = AV_RL32(s);
00099 s += 4;
00100 memset(queue, 0x20, QUEUE_SIZE);
00101 if (AV_RL32(s) == 0x56781234) {
00102 s += 4;
00103 qpos = 0x111;
00104 speclen = 0xF + 3;
00105 } else {
00106 qpos = 0xFEE;
00107 speclen = 100;
00108 }
00109
00110 while (s_end - s > 0 && dataleft > 0) {
00111 tag = *s++;
00112 if ((tag == 0xFF) && (dataleft > 8)) {
00113 if (d_end - d < 8 || s_end - s < 8)
00114 return;
00115 for (i = 0; i < 8; i++) {
00116 queue[qpos++] = *d++ = *s++;
00117 qpos &= QUEUE_MASK;
00118 }
00119 dataleft -= 8;
00120 } else {
00121 for (i = 0; i < 8; i++) {
00122 if (dataleft == 0)
00123 break;
00124 if (tag & 0x01) {
00125 if (d_end - d < 1 || s_end - s < 1)
00126 return;
00127 queue[qpos++] = *d++ = *s++;
00128 qpos &= QUEUE_MASK;
00129 dataleft--;
00130 } else {
00131 if (s_end - s < 2)
00132 return;
00133 chainofs = *s++;
00134 chainofs |= ((*s & 0xF0) << 4);
00135 chainlen = (*s++ & 0x0F) + 3;
00136 if (chainlen == speclen) {
00137 if (s_end - s < 1)
00138 return;
00139 chainlen = *s++ + 0xF + 3;
00140 }
00141 if (d_end - d < chainlen)
00142 return;
00143 for (j = 0; j < chainlen; j++) {
00144 *d = queue[chainofs++ & QUEUE_MASK];
00145 queue[qpos++] = *d++;
00146 qpos &= QUEUE_MASK;
00147 }
00148 dataleft -= chainlen;
00149 }
00150 tag >>= 1;
00151 }
00152 }
00153 }
00154 }
00155
00156 static int rle_unpack(const unsigned char *src, int src_len, int src_count,
00157 unsigned char *dest, int dest_len)
00158 {
00159 const unsigned char *ps;
00160 const unsigned char *ps_end;
00161 unsigned char *pd;
00162 int i, l;
00163 unsigned char *dest_end = dest + dest_len;
00164
00165 ps = src;
00166 ps_end = src + src_len;
00167 pd = dest;
00168 if (src_count & 1) {
00169 if (ps_end - ps < 1)
00170 return 0;
00171 *pd++ = *ps++;
00172 }
00173
00174 src_count >>= 1;
00175 i = 0;
00176 do {
00177 if (ps_end - ps < 1)
00178 break;
00179 l = *ps++;
00180 if (l & 0x80) {
00181 l = (l & 0x7F) * 2;
00182 if (dest_end - pd < l || ps_end - ps < l)
00183 return ps - src;
00184 memcpy(pd, ps, l);
00185 ps += l;
00186 pd += l;
00187 } else {
00188 if (dest_end - pd < i || ps_end - ps < 2)
00189 return ps - src;
00190 for (i = 0; i < l; i++) {
00191 *pd++ = ps[0];
00192 *pd++ = ps[1];
00193 }
00194 ps += 2;
00195 }
00196 i += l;
00197 } while (i < src_count);
00198
00199 return ps - src;
00200 }
00201
00202 static void vmd_decode(VmdVideoContext *s)
00203 {
00204 int i;
00205 unsigned int *palette32;
00206 unsigned char r, g, b;
00207
00208
00209 const unsigned char *p = s->buf + 16;
00210 const unsigned char *p_end = s->buf + s->size;
00211
00212 const unsigned char *pb;
00213 const unsigned char *pb_end;
00214 unsigned char meth;
00215 unsigned char *dp;
00216 unsigned char *pp;
00217 unsigned char len;
00218 int ofs;
00219
00220 int frame_x, frame_y;
00221 int frame_width, frame_height;
00222
00223 frame_x = AV_RL16(&s->buf[6]);
00224 frame_y = AV_RL16(&s->buf[8]);
00225 frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
00226 frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
00227 if (frame_x < 0 || frame_width < 0 ||
00228 frame_x >= s->avctx->width ||
00229 frame_width > s->avctx->width ||
00230 frame_x + frame_width > s->avctx->width)
00231 return;
00232 if (frame_y < 0 || frame_height < 0 ||
00233 frame_y >= s->avctx->height ||
00234 frame_height > s->avctx->height ||
00235 frame_y + frame_height > s->avctx->height)
00236 return;
00237
00238 if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
00239 (frame_x || frame_y)) {
00240
00241 s->x_off = frame_x;
00242 s->y_off = frame_y;
00243 }
00244 frame_x -= s->x_off;
00245 frame_y -= s->y_off;
00246
00247
00248
00249 if (s->prev_frame.data[0] &&
00250 (frame_x || frame_y || (frame_width != s->avctx->width) ||
00251 (frame_height != s->avctx->height))) {
00252
00253 memcpy(s->frame.data[0], s->prev_frame.data[0],
00254 s->avctx->height * s->frame.linesize[0]);
00255 }
00256
00257
00258 if (s->buf[15] & 0x02) {
00259 if (p_end - p < 2 + 3 * PALETTE_COUNT)
00260 return;
00261 p += 2;
00262 palette32 = (unsigned int *)s->palette;
00263 for (i = 0; i < PALETTE_COUNT; i++) {
00264 r = *p++ * 4;
00265 g = *p++ * 4;
00266 b = *p++ * 4;
00267 palette32[i] = (r << 16) | (g << 8) | (b);
00268 }
00269 }
00270 if (p < p_end) {
00271
00272 pb = p;
00273 pb_end = p_end;
00274 meth = *pb++;
00275 if (meth & 0x80) {
00276 lz_unpack(pb, p_end - pb, s->unpack_buffer, s->unpack_buffer_size);
00277 meth &= 0x7F;
00278 pb = s->unpack_buffer;
00279 pb_end = s->unpack_buffer + s->unpack_buffer_size;
00280 }
00281
00282 dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
00283 pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
00284 switch (meth) {
00285 case 1:
00286 for (i = 0; i < frame_height; i++) {
00287 ofs = 0;
00288 do {
00289 if (pb_end - pb < 1)
00290 return;
00291 len = *pb++;
00292 if (len & 0x80) {
00293 len = (len & 0x7F) + 1;
00294 if (ofs + len > frame_width || pb_end - pb < len)
00295 return;
00296 memcpy(&dp[ofs], pb, len);
00297 pb += len;
00298 ofs += len;
00299 } else {
00300
00301 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
00302 return;
00303 memcpy(&dp[ofs], &pp[ofs], len + 1);
00304 ofs += len + 1;
00305 }
00306 } while (ofs < frame_width);
00307 if (ofs > frame_width) {
00308 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00309 ofs, frame_width);
00310 break;
00311 }
00312 dp += s->frame.linesize[0];
00313 pp += s->prev_frame.linesize[0];
00314 }
00315 break;
00316
00317 case 2:
00318 for (i = 0; i < frame_height; i++) {
00319 if (pb_end -pb < frame_width)
00320 return;
00321 memcpy(dp, pb, frame_width);
00322 pb += frame_width;
00323 dp += s->frame.linesize[0];
00324 pp += s->prev_frame.linesize[0];
00325 }
00326 break;
00327
00328 case 3:
00329 for (i = 0; i < frame_height; i++) {
00330 ofs = 0;
00331 do {
00332 if (pb_end - pb < 1)
00333 return;
00334 len = *pb++;
00335 if (len & 0x80) {
00336 len = (len & 0x7F) + 1;
00337 if (pb_end - pb < 1)
00338 return;
00339 if (*pb++ == 0xFF)
00340 len = rle_unpack(pb, pb_end - pb, len, &dp[ofs], frame_width - ofs);
00341 else {
00342 if (pb_end - pb < len)
00343 return;
00344 memcpy(&dp[ofs], pb, len);
00345 }
00346 pb += len;
00347 ofs += len;
00348 } else {
00349
00350 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
00351 return;
00352 memcpy(&dp[ofs], &pp[ofs], len + 1);
00353 ofs += len + 1;
00354 }
00355 } while (ofs < frame_width);
00356 if (ofs > frame_width) {
00357 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00358 ofs, frame_width);
00359 }
00360 dp += s->frame.linesize[0];
00361 pp += s->prev_frame.linesize[0];
00362 }
00363 break;
00364 }
00365 }
00366 }
00367
00368 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
00369 {
00370 VmdVideoContext *s = avctx->priv_data;
00371 int i;
00372 unsigned int *palette32;
00373 int palette_index = 0;
00374 unsigned char r, g, b;
00375 unsigned char *vmd_header;
00376 unsigned char *raw_palette;
00377
00378 s->avctx = avctx;
00379 avctx->pix_fmt = PIX_FMT_PAL8;
00380
00381
00382 if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
00383 av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
00384 VMD_HEADER_SIZE);
00385 return -1;
00386 }
00387 vmd_header = (unsigned char *)avctx->extradata;
00388
00389 s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
00390 s->unpack_buffer = av_malloc(s->unpack_buffer_size);
00391 if (!s->unpack_buffer)
00392 return -1;
00393
00394
00395 raw_palette = &vmd_header[28];
00396 palette32 = (unsigned int *)s->palette;
00397 for (i = 0; i < PALETTE_COUNT; i++) {
00398 r = raw_palette[palette_index++] * 4;
00399 g = raw_palette[palette_index++] * 4;
00400 b = raw_palette[palette_index++] * 4;
00401 palette32[i] = (r << 16) | (g << 8) | (b);
00402 }
00403
00404 avcodec_get_frame_defaults(&s->frame);
00405 avcodec_get_frame_defaults(&s->prev_frame);
00406
00407 return 0;
00408 }
00409
00410 static int vmdvideo_decode_frame(AVCodecContext *avctx,
00411 void *data, int *data_size,
00412 AVPacket *avpkt)
00413 {
00414 const uint8_t *buf = avpkt->data;
00415 int buf_size = avpkt->size;
00416 VmdVideoContext *s = avctx->priv_data;
00417
00418 s->buf = buf;
00419 s->size = buf_size;
00420
00421 if (buf_size < 16)
00422 return buf_size;
00423
00424 s->frame.reference = 1;
00425 if (avctx->get_buffer(avctx, &s->frame)) {
00426 av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
00427 return -1;
00428 }
00429
00430 vmd_decode(s);
00431
00432
00433 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
00434
00435
00436 FFSWAP(AVFrame, s->frame, s->prev_frame);
00437 if (s->frame.data[0])
00438 avctx->release_buffer(avctx, &s->frame);
00439
00440 *data_size = sizeof(AVFrame);
00441 *(AVFrame*)data = s->prev_frame;
00442
00443
00444 return buf_size;
00445 }
00446
00447 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
00448 {
00449 VmdVideoContext *s = avctx->priv_data;
00450
00451 if (s->prev_frame.data[0])
00452 avctx->release_buffer(avctx, &s->prev_frame);
00453 av_free(s->unpack_buffer);
00454
00455 return 0;
00456 }
00457
00458
00459
00460
00461
00462
00463 #define BLOCK_TYPE_AUDIO 1
00464 #define BLOCK_TYPE_INITIAL 2
00465 #define BLOCK_TYPE_SILENCE 3
00466
00467 typedef struct VmdAudioContext {
00468 AVCodecContext *avctx;
00469 int out_bps;
00470 int predictors[2];
00471 } VmdAudioContext;
00472
00473 static const uint16_t vmdaudio_table[128] = {
00474 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
00475 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
00476 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
00477 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
00478 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
00479 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
00480 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
00481 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
00482 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
00483 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
00484 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
00485 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
00486 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
00487 };
00488
00489 static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
00490 {
00491 VmdAudioContext *s = avctx->priv_data;
00492
00493 s->avctx = avctx;
00494 if (avctx->bits_per_coded_sample == 16)
00495 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
00496 else
00497 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
00498 s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt);
00499
00500 av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, "
00501 "block align = %d, sample rate = %d\n",
00502 avctx->channels, avctx->bits_per_coded_sample, avctx->block_align,
00503 avctx->sample_rate);
00504
00505 return 0;
00506 }
00507
00508 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
00509 const uint8_t *buf, int buf_size, int stereo)
00510 {
00511 int i;
00512 int chan = 0;
00513 int16_t *out = (int16_t*)data;
00514
00515 for(i = 0; i < buf_size; i++) {
00516 if(buf[i] & 0x80)
00517 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
00518 else
00519 s->predictors[chan] += vmdaudio_table[buf[i]];
00520 s->predictors[chan] = av_clip_int16(s->predictors[chan]);
00521 out[i] = s->predictors[chan];
00522 chan ^= stereo;
00523 }
00524 }
00525
00526 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
00527 const uint8_t *buf, int silent_chunks, int data_size)
00528 {
00529 int silent_size = s->avctx->block_align * silent_chunks * s->out_bps;
00530
00531 if (silent_chunks) {
00532 memset(data, s->out_bps == 2 ? 0x00 : 0x80, silent_size);
00533 data += silent_size;
00534 }
00535 if (s->avctx->bits_per_coded_sample == 16)
00536 vmdaudio_decode_audio(s, data, buf, data_size, s->avctx->channels == 2);
00537 else {
00538
00539 memcpy(data, buf, data_size);
00540 }
00541
00542 return silent_size + data_size * s->out_bps;
00543 }
00544
00545 static int vmdaudio_decode_frame(AVCodecContext *avctx,
00546 void *data, int *data_size,
00547 AVPacket *avpkt)
00548 {
00549 const uint8_t *buf = avpkt->data;
00550 int buf_size = avpkt->size;
00551 VmdAudioContext *s = avctx->priv_data;
00552 int block_type, silent_chunks;
00553 unsigned char *output_samples = (unsigned char *)data;
00554
00555 if (buf_size < 16) {
00556 av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");
00557 *data_size = 0;
00558 return buf_size;
00559 }
00560
00561 block_type = buf[6];
00562 if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {
00563 av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);
00564 return AVERROR(EINVAL);
00565 }
00566 buf += 16;
00567 buf_size -= 16;
00568
00569 silent_chunks = 0;
00570 if (block_type == BLOCK_TYPE_INITIAL) {
00571 uint32_t flags;
00572 if (buf_size < 4)
00573 return -1;
00574 flags = AV_RB32(buf);
00575 silent_chunks = av_popcount(flags);
00576 buf += 4;
00577 buf_size -= 4;
00578 } else if (block_type == BLOCK_TYPE_SILENCE) {
00579 silent_chunks = 1;
00580 buf_size = 0;
00581 }
00582
00583
00584 if (*data_size < (avctx->block_align*silent_chunks + buf_size) * s->out_bps)
00585 return -1;
00586
00587 *data_size = vmdaudio_loadsound(s, output_samples, buf, silent_chunks, buf_size);
00588
00589 return avpkt->size;
00590 }
00591
00592
00593
00594
00595
00596
00597 AVCodec ff_vmdvideo_decoder = {
00598 "vmdvideo",
00599 AVMEDIA_TYPE_VIDEO,
00600 CODEC_ID_VMDVIDEO,
00601 sizeof(VmdVideoContext),
00602 vmdvideo_decode_init,
00603 NULL,
00604 vmdvideo_decode_end,
00605 vmdvideo_decode_frame,
00606 CODEC_CAP_DR1,
00607 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
00608 };
00609
00610 AVCodec ff_vmdaudio_decoder = {
00611 "vmdaudio",
00612 AVMEDIA_TYPE_AUDIO,
00613 CODEC_ID_VMDAUDIO,
00614 sizeof(VmdAudioContext),
00615 vmdaudio_decode_init,
00616 NULL,
00617 NULL,
00618 vmdaudio_decode_frame,
00619 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
00620 };