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