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