Libav 0.7.1
|
00001 /* 00002 * Sierra VMD Audio & Video Decoders 00003 * Copyright (C) 2004 the ffmpeg project 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 * Video Decoder 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; /* no speclen */ 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 /* point to the start of the encoded data */ 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; /* pointer to current frame */ 00220 unsigned char *pp; /* pointer to previous frame */ 00221 unsigned char len; 00222 int ofs; 00223 00224 int frame_x, frame_y; 00225 int frame_width, frame_height; 00226 00227 frame_x = AV_RL16(&s->buf[6]); 00228 frame_y = AV_RL16(&s->buf[8]); 00229 frame_width = AV_RL16(&s->buf[10]) - frame_x + 1; 00230 frame_height = AV_RL16(&s->buf[12]) - frame_y + 1; 00231 if (frame_x < 0 || frame_width < 0 || 00232 frame_x >= s->avctx->width || 00233 frame_width > s->avctx->width || 00234 frame_x + frame_width > s->avctx->width) 00235 return; 00236 if (frame_y < 0 || frame_height < 0 || 00237 frame_y >= s->avctx->height || 00238 frame_height > s->avctx->height || 00239 frame_y + frame_height > s->avctx->height) 00240 return; 00241 00242 if ((frame_width == s->avctx->width && frame_height == s->avctx->height) && 00243 (frame_x || frame_y)) { 00244 00245 s->x_off = frame_x; 00246 s->y_off = frame_y; 00247 } 00248 frame_x -= s->x_off; 00249 frame_y -= s->y_off; 00250 00251 /* if only a certain region will be updated, copy the entire previous 00252 * frame before the decode */ 00253 if (s->prev_frame.data[0] && 00254 (frame_x || frame_y || (frame_width != s->avctx->width) || 00255 (frame_height != s->avctx->height))) { 00256 00257 memcpy(s->frame.data[0], s->prev_frame.data[0], 00258 s->avctx->height * s->frame.linesize[0]); 00259 } 00260 00261 /* check if there is a new palette */ 00262 if (s->buf[15] & 0x02) { 00263 p += 2; 00264 palette32 = (unsigned int *)s->palette; 00265 for (i = 0; i < PALETTE_COUNT; i++) { 00266 r = *p++ * 4; 00267 g = *p++ * 4; 00268 b = *p++ * 4; 00269 palette32[i] = (r << 16) | (g << 8) | (b); 00270 } 00271 s->size -= (256 * 3 + 2); 00272 } 00273 if (s->size > 0) { 00274 /* originally UnpackFrame in VAG's code */ 00275 pb = p; 00276 pb_size = s->buf + s->size - pb; 00277 if (pb_size < 1) 00278 return; 00279 meth = *pb++; pb_size--; 00280 if (meth & 0x80) { 00281 lz_unpack(pb, pb_size, 00282 s->unpack_buffer, s->unpack_buffer_size); 00283 meth &= 0x7F; 00284 pb = s->unpack_buffer; 00285 pb_size = s->unpack_buffer_size; 00286 } 00287 00288 dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x]; 00289 pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x]; 00290 switch (meth) { 00291 case 1: 00292 for (i = 0; i < frame_height; i++) { 00293 ofs = 0; 00294 do { 00295 if (pb_size < 1) 00296 return; 00297 len = *pb++; 00298 pb_size--; 00299 if (len & 0x80) { 00300 len = (len & 0x7F) + 1; 00301 if (ofs + len > frame_width || pb_size < len) 00302 return; 00303 memcpy(&dp[ofs], pb, len); 00304 pb += len; 00305 pb_size -= len; 00306 ofs += len; 00307 } else { 00308 /* interframe pixel copy */ 00309 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) 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 break; 00319 } 00320 dp += s->frame.linesize[0]; 00321 pp += s->prev_frame.linesize[0]; 00322 } 00323 break; 00324 00325 case 2: 00326 for (i = 0; i < frame_height; i++) { 00327 if (pb_size < frame_width) 00328 return; 00329 memcpy(dp, pb, frame_width); 00330 pb += frame_width; 00331 pb_size -= frame_width; 00332 dp += s->frame.linesize[0]; 00333 pp += s->prev_frame.linesize[0]; 00334 } 00335 break; 00336 00337 case 3: 00338 for (i = 0; i < frame_height; i++) { 00339 ofs = 0; 00340 do { 00341 if (pb_size < 1) 00342 return; 00343 len = *pb++; 00344 pb_size--; 00345 if (len & 0x80) { 00346 len = (len & 0x7F) + 1; 00347 if (pb_size < 1) 00348 return; 00349 if (*pb++ == 0xFF) 00350 len = rle_unpack(pb, &dp[ofs], len, pb_size, frame_width - ofs); 00351 else { 00352 if (pb_size < len) 00353 return; 00354 memcpy(&dp[ofs], pb, len); 00355 } 00356 pb += len; 00357 pb_size -= 1 + len; 00358 ofs += len; 00359 } else { 00360 /* interframe pixel copy */ 00361 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) 00362 return; 00363 memcpy(&dp[ofs], &pp[ofs], len + 1); 00364 ofs += len + 1; 00365 } 00366 } while (ofs < frame_width); 00367 if (ofs > frame_width) { 00368 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n", 00369 ofs, frame_width); 00370 } 00371 dp += s->frame.linesize[0]; 00372 pp += s->prev_frame.linesize[0]; 00373 } 00374 break; 00375 } 00376 } 00377 } 00378 00379 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx) 00380 { 00381 VmdVideoContext *s = avctx->priv_data; 00382 int i; 00383 unsigned int *palette32; 00384 int palette_index = 0; 00385 unsigned char r, g, b; 00386 unsigned char *vmd_header; 00387 unsigned char *raw_palette; 00388 00389 s->avctx = avctx; 00390 avctx->pix_fmt = PIX_FMT_PAL8; 00391 00392 /* make sure the VMD header made it */ 00393 if (s->avctx->extradata_size != VMD_HEADER_SIZE) { 00394 av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n", 00395 VMD_HEADER_SIZE); 00396 return -1; 00397 } 00398 vmd_header = (unsigned char *)avctx->extradata; 00399 00400 s->unpack_buffer_size = AV_RL32(&vmd_header[800]); 00401 s->unpack_buffer = av_malloc(s->unpack_buffer_size); 00402 if (!s->unpack_buffer) 00403 return -1; 00404 00405 /* load up the initial palette */ 00406 raw_palette = &vmd_header[28]; 00407 palette32 = (unsigned int *)s->palette; 00408 for (i = 0; i < PALETTE_COUNT; i++) { 00409 r = raw_palette[palette_index++] * 4; 00410 g = raw_palette[palette_index++] * 4; 00411 b = raw_palette[palette_index++] * 4; 00412 palette32[i] = (r << 16) | (g << 8) | (b); 00413 } 00414 00415 return 0; 00416 } 00417 00418 static int vmdvideo_decode_frame(AVCodecContext *avctx, 00419 void *data, int *data_size, 00420 AVPacket *avpkt) 00421 { 00422 const uint8_t *buf = avpkt->data; 00423 int buf_size = avpkt->size; 00424 VmdVideoContext *s = avctx->priv_data; 00425 00426 s->buf = buf; 00427 s->size = buf_size; 00428 00429 if (buf_size < 16) 00430 return buf_size; 00431 00432 s->frame.reference = 1; 00433 if (avctx->get_buffer(avctx, &s->frame)) { 00434 av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n"); 00435 return -1; 00436 } 00437 00438 vmd_decode(s); 00439 00440 /* make the palette available on the way out */ 00441 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4); 00442 00443 /* shuffle frames */ 00444 FFSWAP(AVFrame, s->frame, s->prev_frame); 00445 if (s->frame.data[0]) 00446 avctx->release_buffer(avctx, &s->frame); 00447 00448 *data_size = sizeof(AVFrame); 00449 *(AVFrame*)data = s->prev_frame; 00450 00451 /* report that the buffer was completely consumed */ 00452 return buf_size; 00453 } 00454 00455 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx) 00456 { 00457 VmdVideoContext *s = avctx->priv_data; 00458 00459 if (s->prev_frame.data[0]) 00460 avctx->release_buffer(avctx, &s->prev_frame); 00461 av_free(s->unpack_buffer); 00462 00463 return 0; 00464 } 00465 00466 00467 /* 00468 * Audio Decoder 00469 */ 00470 00471 #define BLOCK_TYPE_AUDIO 1 00472 #define BLOCK_TYPE_INITIAL 2 00473 #define BLOCK_TYPE_SILENCE 3 00474 00475 typedef struct VmdAudioContext { 00476 AVCodecContext *avctx; 00477 int out_bps; 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 if (avctx->bits_per_coded_sample == 16) 00503 avctx->sample_fmt = AV_SAMPLE_FMT_S16; 00504 else 00505 avctx->sample_fmt = AV_SAMPLE_FMT_U8; 00506 s->out_bps = av_get_bits_per_sample_fmt(avctx->sample_fmt) >> 3; 00507 00508 av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " 00509 "block align = %d, sample rate = %d\n", 00510 avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, 00511 avctx->sample_rate); 00512 00513 return 0; 00514 } 00515 00516 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, 00517 const uint8_t *buf, int buf_size, int stereo) 00518 { 00519 int i; 00520 int chan = 0; 00521 int16_t *out = (int16_t*)data; 00522 00523 for(i = 0; i < buf_size; i++) { 00524 if(buf[i] & 0x80) 00525 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; 00526 else 00527 s->predictors[chan] += vmdaudio_table[buf[i]]; 00528 s->predictors[chan] = av_clip_int16(s->predictors[chan]); 00529 out[i] = s->predictors[chan]; 00530 chan ^= stereo; 00531 } 00532 } 00533 00534 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, 00535 const uint8_t *buf, int silent_chunks, int data_size) 00536 { 00537 int silent_size = s->avctx->block_align * silent_chunks * s->out_bps; 00538 00539 if (silent_chunks) { 00540 memset(data, s->out_bps == 2 ? 0x00 : 0x80, silent_size); 00541 data += silent_size; 00542 } 00543 if (s->avctx->bits_per_coded_sample == 16) 00544 vmdaudio_decode_audio(s, data, buf, data_size, s->avctx->channels == 2); 00545 else { 00546 /* just copy the data */ 00547 memcpy(data, buf, data_size); 00548 } 00549 00550 return silent_size + data_size * s->out_bps; 00551 } 00552 00553 static int vmdaudio_decode_frame(AVCodecContext *avctx, 00554 void *data, int *data_size, 00555 AVPacket *avpkt) 00556 { 00557 const uint8_t *buf = avpkt->data; 00558 int buf_size = avpkt->size; 00559 VmdAudioContext *s = avctx->priv_data; 00560 int block_type, silent_chunks; 00561 unsigned char *output_samples = (unsigned char *)data; 00562 00563 if (buf_size < 16) { 00564 av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); 00565 *data_size = 0; 00566 return buf_size; 00567 } 00568 00569 block_type = buf[6]; 00570 if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) { 00571 av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type); 00572 return AVERROR(EINVAL); 00573 } 00574 buf += 16; 00575 buf_size -= 16; 00576 00577 silent_chunks = 0; 00578 if (block_type == BLOCK_TYPE_INITIAL) { 00579 uint32_t flags = AV_RB32(buf); 00580 silent_chunks = av_popcount(flags); 00581 buf += 4; 00582 buf_size -= 4; 00583 } else if (block_type == BLOCK_TYPE_SILENCE) { 00584 silent_chunks = 1; 00585 buf_size = 0; // should already be zero but set it just to be sure 00586 } 00587 00588 /* ensure output buffer is large enough */ 00589 if (*data_size < (avctx->block_align*silent_chunks + buf_size) * s->out_bps) 00590 return -1; 00591 00592 *data_size = vmdaudio_loadsound(s, output_samples, buf, silent_chunks, buf_size); 00593 00594 return avpkt->size; 00595 } 00596 00597 00598 /* 00599 * Public Data Structures 00600 */ 00601 00602 AVCodec ff_vmdvideo_decoder = { 00603 "vmdvideo", 00604 AVMEDIA_TYPE_VIDEO, 00605 CODEC_ID_VMDVIDEO, 00606 sizeof(VmdVideoContext), 00607 vmdvideo_decode_init, 00608 NULL, 00609 vmdvideo_decode_end, 00610 vmdvideo_decode_frame, 00611 CODEC_CAP_DR1, 00612 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"), 00613 }; 00614 00615 AVCodec ff_vmdaudio_decoder = { 00616 "vmdaudio", 00617 AVMEDIA_TYPE_AUDIO, 00618 CODEC_ID_VMDAUDIO, 00619 sizeof(VmdAudioContext), 00620 vmdaudio_decode_init, 00621 NULL, 00622 NULL, 00623 vmdaudio_decode_frame, 00624 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), 00625 };