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 int dp_size;
00227
00228 frame_x = AV_RL16(&s->buf[6]);
00229 frame_y = AV_RL16(&s->buf[8]);
00230 frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
00231 frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
00232 if (frame_x < 0 || frame_width < 0 ||
00233 frame_x >= s->avctx->width ||
00234 frame_width > s->avctx->width ||
00235 frame_x + frame_width > s->avctx->width)
00236 return;
00237 if (frame_y < 0 || frame_height < 0 ||
00238 frame_y >= s->avctx->height ||
00239 frame_height > s->avctx->height ||
00240 frame_y + frame_height > s->avctx->height)
00241 return;
00242
00243 if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
00244 (frame_x || frame_y)) {
00245
00246 s->x_off = frame_x;
00247 s->y_off = frame_y;
00248 }
00249 frame_x -= s->x_off;
00250 frame_y -= s->y_off;
00251
00252
00253
00254 if (s->prev_frame.data[0] &&
00255 (frame_x || frame_y || (frame_width != s->avctx->width) ||
00256 (frame_height != s->avctx->height))) {
00257
00258 memcpy(s->frame.data[0], s->prev_frame.data[0],
00259 s->avctx->height * s->frame.linesize[0]);
00260 }
00261
00262
00263 if (s->buf[15] & 0x02) {
00264 p += 2;
00265 palette32 = (unsigned int *)s->palette;
00266 for (i = 0; i < PALETTE_COUNT; i++) {
00267 r = *p++ * 4;
00268 g = *p++ * 4;
00269 b = *p++ * 4;
00270 palette32[i] = (r << 16) | (g << 8) | (b);
00271 }
00272 s->size -= (256 * 3 + 2);
00273 }
00274 if (s->size > 0) {
00275
00276 pb = p;
00277 pb_size = s->buf + s->size - pb;
00278 if (pb_size < 1)
00279 return;
00280 meth = *pb++; pb_size--;
00281 if (meth & 0x80) {
00282 lz_unpack(pb, pb_size,
00283 s->unpack_buffer, s->unpack_buffer_size);
00284 meth &= 0x7F;
00285 pb = s->unpack_buffer;
00286 pb_size = s->unpack_buffer_size;
00287 }
00288
00289 dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
00290 dp_size = s->frame.linesize[0] * s->avctx->height;
00291 pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
00292 switch (meth) {
00293 case 1:
00294 for (i = 0; i < frame_height; i++) {
00295 ofs = 0;
00296 do {
00297 if (pb_size < 1)
00298 return;
00299 len = *pb++;
00300 pb_size--;
00301 if (len & 0x80) {
00302 len = (len & 0x7F) + 1;
00303 if (ofs + len > frame_width || pb_size < len)
00304 return;
00305 memcpy(&dp[ofs], pb, len);
00306 pb += len;
00307 pb_size -= len;
00308 ofs += len;
00309 } else {
00310
00311 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
00312 return;
00313 memcpy(&dp[ofs], &pp[ofs], len + 1);
00314 ofs += len + 1;
00315 }
00316 } while (ofs < frame_width);
00317 if (ofs > frame_width) {
00318 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00319 ofs, frame_width);
00320 break;
00321 }
00322 dp += s->frame.linesize[0];
00323 pp += s->prev_frame.linesize[0];
00324 }
00325 break;
00326
00327 case 2:
00328 for (i = 0; i < frame_height; i++) {
00329 if (pb_size < frame_width)
00330 return;
00331 memcpy(dp, pb, frame_width);
00332 pb += frame_width;
00333 pb_size -= frame_width;
00334 dp += s->frame.linesize[0];
00335 pp += s->prev_frame.linesize[0];
00336 }
00337 break;
00338
00339 case 3:
00340 for (i = 0; i < frame_height; i++) {
00341 ofs = 0;
00342 do {
00343 if (pb_size < 1)
00344 return;
00345 len = *pb++;
00346 pb_size--;
00347 if (len & 0x80) {
00348 len = (len & 0x7F) + 1;
00349 if (pb_size < 1)
00350 return;
00351 if (*pb++ == 0xFF)
00352 len = rle_unpack(pb, &dp[ofs], len, pb_size, frame_width - ofs);
00353 else {
00354 if (pb_size < len)
00355 return;
00356 memcpy(&dp[ofs], pb, len);
00357 }
00358 pb += len;
00359 pb_size -= 1 + len;
00360 ofs += len;
00361 } else {
00362
00363 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
00364 return;
00365 memcpy(&dp[ofs], &pp[ofs], len + 1);
00366 ofs += len + 1;
00367 }
00368 } while (ofs < frame_width);
00369 if (ofs > frame_width) {
00370 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00371 ofs, frame_width);
00372 }
00373 dp += s->frame.linesize[0];
00374 pp += s->prev_frame.linesize[0];
00375 }
00376 break;
00377 }
00378 }
00379 }
00380
00381 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
00382 {
00383 VmdVideoContext *s = avctx->priv_data;
00384 int i;
00385 unsigned int *palette32;
00386 int palette_index = 0;
00387 unsigned char r, g, b;
00388 unsigned char *vmd_header;
00389 unsigned char *raw_palette;
00390
00391 s->avctx = avctx;
00392 avctx->pix_fmt = PIX_FMT_PAL8;
00393
00394
00395 if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
00396 av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
00397 VMD_HEADER_SIZE);
00398 return -1;
00399 }
00400 vmd_header = (unsigned char *)avctx->extradata;
00401
00402 s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
00403 s->unpack_buffer = av_malloc(s->unpack_buffer_size);
00404 if (!s->unpack_buffer)
00405 return -1;
00406
00407
00408 raw_palette = &vmd_header[28];
00409 palette32 = (unsigned int *)s->palette;
00410 for (i = 0; i < PALETTE_COUNT; i++) {
00411 r = raw_palette[palette_index++] * 4;
00412 g = raw_palette[palette_index++] * 4;
00413 b = raw_palette[palette_index++] * 4;
00414 palette32[i] = (r << 16) | (g << 8) | (b);
00415 }
00416
00417 return 0;
00418 }
00419
00420 static int vmdvideo_decode_frame(AVCodecContext *avctx,
00421 void *data, int *data_size,
00422 AVPacket *avpkt)
00423 {
00424 const uint8_t *buf = avpkt->data;
00425 int buf_size = avpkt->size;
00426 VmdVideoContext *s = avctx->priv_data;
00427
00428 s->buf = buf;
00429 s->size = buf_size;
00430
00431 if (buf_size < 16)
00432 return buf_size;
00433
00434 s->frame.reference = 1;
00435 if (avctx->get_buffer(avctx, &s->frame)) {
00436 av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
00437 return -1;
00438 }
00439
00440 vmd_decode(s);
00441
00442
00443 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
00444
00445
00446 FFSWAP(AVFrame, s->frame, s->prev_frame);
00447 if (s->frame.data[0])
00448 avctx->release_buffer(avctx, &s->frame);
00449
00450 *data_size = sizeof(AVFrame);
00451 *(AVFrame*)data = s->prev_frame;
00452
00453
00454 return buf_size;
00455 }
00456
00457 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
00458 {
00459 VmdVideoContext *s = avctx->priv_data;
00460
00461 if (s->prev_frame.data[0])
00462 avctx->release_buffer(avctx, &s->prev_frame);
00463 av_free(s->unpack_buffer);
00464
00465 return 0;
00466 }
00467
00468
00469
00470
00471
00472
00473 typedef struct VmdAudioContext {
00474 AVCodecContext *avctx;
00475 int channels;
00476 int bits;
00477 int block_align;
00478 int predictors[2];
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 s->avctx = avctx;
00502 s->channels = avctx->channels;
00503 s->bits = avctx->bits_per_coded_sample;
00504 s->block_align = avctx->block_align;
00505 avctx->sample_fmt = SAMPLE_FMT_S16;
00506
00507 av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
00508 s->channels, s->bits, s->block_align, avctx->sample_rate);
00509
00510 return 0;
00511 }
00512
00513 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
00514 const uint8_t *buf, int buf_size, int stereo)
00515 {
00516 int i;
00517 int chan = 0;
00518 int16_t *out = (int16_t*)data;
00519
00520 for(i = 0; i < buf_size; i++) {
00521 if(buf[i] & 0x80)
00522 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
00523 else
00524 s->predictors[chan] += vmdaudio_table[buf[i]];
00525 s->predictors[chan] = av_clip_int16(s->predictors[chan]);
00526 out[i] = s->predictors[chan];
00527 chan ^= stereo;
00528 }
00529 }
00530
00531 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
00532 const uint8_t *buf, int silence, int data_size)
00533 {
00534 int bytes_decoded = 0;
00535 int i;
00536
00537
00538
00539 if (s->channels == 2) {
00540
00541
00542 if (silence) {
00543 memset(data, 0, data_size * 2);
00544 } else {
00545 if (s->bits == 16)
00546 vmdaudio_decode_audio(s, data, buf, data_size, 1);
00547 else {
00548
00549 for (i = 0; i < data_size; i++){
00550 *data++ = buf[i] + 0x80;
00551 *data++ = buf[i] + 0x80;
00552 }
00553 }
00554 }
00555 } else {
00556 bytes_decoded = data_size * 2;
00557
00558
00559 if (silence) {
00560 memset(data, 0, data_size * 2);
00561 } else {
00562 if (s->bits == 16) {
00563 vmdaudio_decode_audio(s, data, buf, data_size, 0);
00564 } else {
00565
00566 for (i = 0; i < data_size; i++){
00567 *data++ = buf[i] + 0x80;
00568 *data++ = buf[i] + 0x80;
00569 }
00570 }
00571 }
00572 }
00573
00574 return data_size * 2;
00575 }
00576
00577 static int vmdaudio_decode_frame(AVCodecContext *avctx,
00578 void *data, int *data_size,
00579 AVPacket *avpkt)
00580 {
00581 const uint8_t *buf = avpkt->data;
00582 int buf_size = avpkt->size;
00583 VmdAudioContext *s = avctx->priv_data;
00584 unsigned char *output_samples = (unsigned char *)data;
00585
00586
00587 const unsigned char *p = buf + 16;
00588
00589 if (buf_size < 16)
00590 return buf_size;
00591
00592 if (buf[6] == 1) {
00593
00594 *data_size = vmdaudio_loadsound(s, output_samples, p, 0, buf_size - 16);
00595 } else if (buf[6] == 2) {
00596
00597 uint32_t flags = AV_RB32(p);
00598 int raw_block_size = s->block_align * s->bits / 8;
00599 int silent_chunks;
00600 if(flags == 0xFFFFFFFF)
00601 silent_chunks = 32;
00602 else
00603 silent_chunks = av_log2(flags + 1);
00604 if(*data_size < (s->block_align*silent_chunks + buf_size - 20) * 2)
00605 return -1;
00606 *data_size = 0;
00607 memset(output_samples, 0, raw_block_size * silent_chunks);
00608 output_samples += raw_block_size * silent_chunks;
00609 *data_size = raw_block_size * silent_chunks;
00610 *data_size += vmdaudio_loadsound(s, output_samples, p + 4, 0, buf_size - 20);
00611 } else if (buf[6] == 3) {
00612
00613 *data_size = vmdaudio_loadsound(s, output_samples, p, 1, 0);
00614 }
00615
00616 return buf_size;
00617 }
00618
00619
00620
00621
00622
00623
00624 AVCodec vmdvideo_decoder = {
00625 "vmdvideo",
00626 AVMEDIA_TYPE_VIDEO,
00627 CODEC_ID_VMDVIDEO,
00628 sizeof(VmdVideoContext),
00629 vmdvideo_decode_init,
00630 NULL,
00631 vmdvideo_decode_end,
00632 vmdvideo_decode_frame,
00633 CODEC_CAP_DR1,
00634 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
00635 };
00636
00637 AVCodec vmdaudio_decoder = {
00638 "vmdaudio",
00639 AVMEDIA_TYPE_AUDIO,
00640 CODEC_ID_VMDAUDIO,
00641 sizeof(VmdAudioContext),
00642 vmdaudio_decode_init,
00643 NULL,
00644 NULL,
00645 vmdaudio_decode_frame,
00646 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
00647 };