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