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 typedef struct VmdAudioContext {
00418 AVCodecContext *avctx;
00419 int channels;
00420 int bits;
00421 int block_align;
00422 int predictors[2];
00423 } VmdAudioContext;
00424
00425 static const uint16_t vmdaudio_table[128] = {
00426 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
00427 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
00428 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
00429 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
00430 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
00431 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
00432 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
00433 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
00434 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
00435 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
00436 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
00437 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
00438 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
00439 };
00440
00441 static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
00442 {
00443 VmdAudioContext *s = avctx->priv_data;
00444
00445 s->avctx = avctx;
00446 s->channels = avctx->channels;
00447 s->bits = avctx->bits_per_coded_sample;
00448 s->block_align = avctx->block_align;
00449 avctx->sample_fmt = SAMPLE_FMT_S16;
00450
00451 av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
00452 s->channels, s->bits, s->block_align, avctx->sample_rate);
00453
00454 return 0;
00455 }
00456
00457 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
00458 const uint8_t *buf, int buf_size, int stereo)
00459 {
00460 int i;
00461 int chan = 0;
00462 int16_t *out = (int16_t*)data;
00463
00464 for(i = 0; i < buf_size; i++) {
00465 if(buf[i] & 0x80)
00466 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
00467 else
00468 s->predictors[chan] += vmdaudio_table[buf[i]];
00469 s->predictors[chan] = av_clip_int16(s->predictors[chan]);
00470 out[i] = s->predictors[chan];
00471 chan ^= stereo;
00472 }
00473 }
00474
00475 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
00476 const uint8_t *buf, int silence, int data_size)
00477 {
00478 int bytes_decoded = 0;
00479 int i;
00480
00481
00482
00483 if (s->channels == 2) {
00484
00485
00486 if (silence) {
00487 memset(data, 0, data_size * 2);
00488 } else {
00489 if (s->bits == 16)
00490 vmdaudio_decode_audio(s, data, buf, data_size, 1);
00491 else {
00492
00493 for (i = 0; i < data_size; i++){
00494 *data++ = buf[i] + 0x80;
00495 *data++ = buf[i] + 0x80;
00496 }
00497 }
00498 }
00499 } else {
00500 bytes_decoded = data_size * 2;
00501
00502
00503 if (silence) {
00504 memset(data, 0, data_size * 2);
00505 } else {
00506 if (s->bits == 16) {
00507 vmdaudio_decode_audio(s, data, buf, data_size, 0);
00508 } else {
00509
00510 for (i = 0; i < data_size; i++){
00511 *data++ = buf[i] + 0x80;
00512 *data++ = buf[i] + 0x80;
00513 }
00514 }
00515 }
00516 }
00517
00518 return data_size * 2;
00519 }
00520
00521 static int vmdaudio_decode_frame(AVCodecContext *avctx,
00522 void *data, int *data_size,
00523 AVPacket *avpkt)
00524 {
00525 const uint8_t *buf = avpkt->data;
00526 int buf_size = avpkt->size;
00527 VmdAudioContext *s = avctx->priv_data;
00528 unsigned char *output_samples = (unsigned char *)data;
00529
00530
00531 const unsigned char *p = buf + 16;
00532
00533 if (buf_size < 16)
00534 return buf_size;
00535
00536 if (buf[6] == 1) {
00537
00538 *data_size = vmdaudio_loadsound(s, output_samples, p, 0, buf_size - 16);
00539 } else if (buf[6] == 2) {
00540
00541 uint32_t flags = AV_RB32(p);
00542 int raw_block_size = s->block_align * s->bits / 8;
00543 int silent_chunks;
00544 if(flags == 0xFFFFFFFF)
00545 silent_chunks = 32;
00546 else
00547 silent_chunks = av_log2(flags + 1);
00548 if(*data_size < (s->block_align*silent_chunks + buf_size - 20) * 2)
00549 return -1;
00550 *data_size = 0;
00551 memset(output_samples, 0, raw_block_size * silent_chunks);
00552 output_samples += raw_block_size * silent_chunks;
00553 *data_size = raw_block_size * silent_chunks;
00554 *data_size += vmdaudio_loadsound(s, output_samples, p + 4, 0, buf_size - 20);
00555 } else if (buf[6] == 3) {
00556
00557 *data_size = vmdaudio_loadsound(s, output_samples, p, 1, 0);
00558 }
00559
00560 return buf_size;
00561 }
00562
00563
00564
00565
00566
00567
00568 AVCodec vmdvideo_decoder = {
00569 "vmdvideo",
00570 AVMEDIA_TYPE_VIDEO,
00571 CODEC_ID_VMDVIDEO,
00572 sizeof(VmdVideoContext),
00573 vmdvideo_decode_init,
00574 NULL,
00575 vmdvideo_decode_end,
00576 vmdvideo_decode_frame,
00577 CODEC_CAP_DR1,
00578 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
00579 };
00580
00581 AVCodec vmdaudio_decoder = {
00582 "vmdaudio",
00583 AVMEDIA_TYPE_AUDIO,
00584 CODEC_ID_VMDAUDIO,
00585 sizeof(VmdAudioContext),
00586 vmdaudio_decode_init,
00587 NULL,
00588 NULL,
00589 vmdaudio_decode_frame,
00590 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
00591 };