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