Libav 0.7.1
libavcodec/vmdav.c
Go to the documentation of this file.
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, 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;  /* no speclen */
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     /* point to the start of the encoded data */
00191     const unsigned char *p = s->buf + 16;
00192 
00193     const unsigned char *pb;
00194     unsigned char meth;
00195     unsigned char *dp;   /* pointer to current frame */
00196     unsigned char *pp;   /* pointer to previous frame */
00197     unsigned char len;
00198     int ofs;
00199 
00200     int frame_x, frame_y;
00201     int frame_width, frame_height;
00202 
00203     frame_x = AV_RL16(&s->buf[6]);
00204     frame_y = AV_RL16(&s->buf[8]);
00205     frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
00206     frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
00207 
00208     if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
00209         (frame_x || frame_y)) {
00210 
00211         s->x_off = frame_x;
00212         s->y_off = frame_y;
00213     }
00214     frame_x -= s->x_off;
00215     frame_y -= s->y_off;
00216 
00217     /* if only a certain region will be updated, copy the entire previous
00218      * frame before the decode */
00219     if (frame_x || frame_y || (frame_width != s->avctx->width) ||
00220         (frame_height != s->avctx->height)) {
00221 
00222         memcpy(s->frame.data[0], s->prev_frame.data[0],
00223             s->avctx->height * s->frame.linesize[0]);
00224     }
00225 
00226     /* check if there is a new palette */
00227     if (s->buf[15] & 0x02) {
00228         p += 2;
00229         palette32 = (unsigned int *)s->palette;
00230         for (i = 0; i < PALETTE_COUNT; i++) {
00231             r = *p++ * 4;
00232             g = *p++ * 4;
00233             b = *p++ * 4;
00234             palette32[i] = (r << 16) | (g << 8) | (b);
00235         }
00236         s->size -= (256 * 3 + 2);
00237     }
00238     if (s->size >= 0) {
00239         /* originally UnpackFrame in VAG's code */
00240         pb = p;
00241         meth = *pb++;
00242         if (meth & 0x80) {
00243             lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
00244             meth &= 0x7F;
00245             pb = s->unpack_buffer;
00246         }
00247 
00248         dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
00249         pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
00250         switch (meth) {
00251         case 1:
00252             for (i = 0; i < frame_height; i++) {
00253                 ofs = 0;
00254                 do {
00255                     len = *pb++;
00256                     if (len & 0x80) {
00257                         len = (len & 0x7F) + 1;
00258                         if (ofs + len > frame_width)
00259                             return;
00260                         memcpy(&dp[ofs], pb, len);
00261                         pb += len;
00262                         ofs += len;
00263                     } else {
00264                         /* interframe pixel copy */
00265                         if (ofs + len + 1 > frame_width)
00266                             return;
00267                         memcpy(&dp[ofs], &pp[ofs], len + 1);
00268                         ofs += len + 1;
00269                     }
00270                 } while (ofs < frame_width);
00271                 if (ofs > frame_width) {
00272                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00273                         ofs, frame_width);
00274                     break;
00275                 }
00276                 dp += s->frame.linesize[0];
00277                 pp += s->prev_frame.linesize[0];
00278             }
00279             break;
00280 
00281         case 2:
00282             for (i = 0; i < frame_height; i++) {
00283                 memcpy(dp, pb, frame_width);
00284                 pb += frame_width;
00285                 dp += s->frame.linesize[0];
00286                 pp += s->prev_frame.linesize[0];
00287             }
00288             break;
00289 
00290         case 3:
00291             for (i = 0; i < frame_height; i++) {
00292                 ofs = 0;
00293                 do {
00294                     len = *pb++;
00295                     if (len & 0x80) {
00296                         len = (len & 0x7F) + 1;
00297                         if (*pb++ == 0xFF)
00298                             len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
00299                         else
00300                             memcpy(&dp[ofs], pb, len);
00301                         pb += len;
00302                         ofs += len;
00303                     } else {
00304                         /* interframe pixel copy */
00305                         if (ofs + len + 1 > frame_width)
00306                             return;
00307                         memcpy(&dp[ofs], &pp[ofs], len + 1);
00308                         ofs += len + 1;
00309                     }
00310                 } while (ofs < frame_width);
00311                 if (ofs > frame_width) {
00312                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00313                         ofs, frame_width);
00314                 }
00315                 dp += s->frame.linesize[0];
00316                 pp += s->prev_frame.linesize[0];
00317             }
00318             break;
00319         }
00320     }
00321 }
00322 
00323 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
00324 {
00325     VmdVideoContext *s = avctx->priv_data;
00326     int i;
00327     unsigned int *palette32;
00328     int palette_index = 0;
00329     unsigned char r, g, b;
00330     unsigned char *vmd_header;
00331     unsigned char *raw_palette;
00332 
00333     s->avctx = avctx;
00334     avctx->pix_fmt = PIX_FMT_PAL8;
00335 
00336     /* make sure the VMD header made it */
00337     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
00338         av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
00339             VMD_HEADER_SIZE);
00340         return -1;
00341     }
00342     vmd_header = (unsigned char *)avctx->extradata;
00343 
00344     s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
00345     s->unpack_buffer = av_malloc(s->unpack_buffer_size);
00346     if (!s->unpack_buffer)
00347         return -1;
00348 
00349     /* load up the initial palette */
00350     raw_palette = &vmd_header[28];
00351     palette32 = (unsigned int *)s->palette;
00352     for (i = 0; i < PALETTE_COUNT; i++) {
00353         r = raw_palette[palette_index++] * 4;
00354         g = raw_palette[palette_index++] * 4;
00355         b = raw_palette[palette_index++] * 4;
00356         palette32[i] = (r << 16) | (g << 8) | (b);
00357     }
00358 
00359     return 0;
00360 }
00361 
00362 static int vmdvideo_decode_frame(AVCodecContext *avctx,
00363                                  void *data, int *data_size,
00364                                  AVPacket *avpkt)
00365 {
00366     const uint8_t *buf = avpkt->data;
00367     int buf_size = avpkt->size;
00368     VmdVideoContext *s = avctx->priv_data;
00369 
00370     s->buf = buf;
00371     s->size = buf_size;
00372 
00373     if (buf_size < 16)
00374         return buf_size;
00375 
00376     s->frame.reference = 1;
00377     if (avctx->get_buffer(avctx, &s->frame)) {
00378         av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
00379         return -1;
00380     }
00381 
00382     vmd_decode(s);
00383 
00384     /* make the palette available on the way out */
00385     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
00386 
00387     /* shuffle frames */
00388     FFSWAP(AVFrame, s->frame, s->prev_frame);
00389     if (s->frame.data[0])
00390         avctx->release_buffer(avctx, &s->frame);
00391 
00392     *data_size = sizeof(AVFrame);
00393     *(AVFrame*)data = s->prev_frame;
00394 
00395     /* report that the buffer was completely consumed */
00396     return buf_size;
00397 }
00398 
00399 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
00400 {
00401     VmdVideoContext *s = avctx->priv_data;
00402 
00403     if (s->prev_frame.data[0])
00404         avctx->release_buffer(avctx, &s->prev_frame);
00405     av_free(s->unpack_buffer);
00406 
00407     return 0;
00408 }
00409 
00410 
00411 /*
00412  * Audio Decoder
00413  */
00414 
00415 #define BLOCK_TYPE_AUDIO    1
00416 #define BLOCK_TYPE_INITIAL  2
00417 #define BLOCK_TYPE_SILENCE  3
00418 
00419 typedef struct VmdAudioContext {
00420     AVCodecContext *avctx;
00421     int out_bps;
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     if (avctx->bits_per_coded_sample == 16)
00447         avctx->sample_fmt = AV_SAMPLE_FMT_S16;
00448     else
00449         avctx->sample_fmt = AV_SAMPLE_FMT_U8;
00450     s->out_bps = av_get_bits_per_sample_fmt(avctx->sample_fmt) >> 3;
00451 
00452     av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, "
00453            "block align = %d, sample rate = %d\n",
00454            avctx->channels, avctx->bits_per_coded_sample, avctx->block_align,
00455            avctx->sample_rate);
00456 
00457     return 0;
00458 }
00459 
00460 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
00461     const uint8_t *buf, int buf_size, int stereo)
00462 {
00463     int i;
00464     int chan = 0;
00465     int16_t *out = (int16_t*)data;
00466 
00467     for(i = 0; i < buf_size; i++) {
00468         if(buf[i] & 0x80)
00469             s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
00470         else
00471             s->predictors[chan] += vmdaudio_table[buf[i]];
00472         s->predictors[chan] = av_clip_int16(s->predictors[chan]);
00473         out[i] = s->predictors[chan];
00474         chan ^= stereo;
00475     }
00476 }
00477 
00478 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
00479     const uint8_t *buf, int silent_chunks, int data_size)
00480 {
00481     int silent_size = s->avctx->block_align * silent_chunks * s->out_bps;
00482 
00483     if (silent_chunks) {
00484         memset(data, s->out_bps == 2 ? 0x00 : 0x80, silent_size);
00485         data += silent_size;
00486     }
00487     if (s->avctx->bits_per_coded_sample == 16)
00488         vmdaudio_decode_audio(s, data, buf, data_size, s->avctx->channels == 2);
00489     else {
00490         /* just copy the data */
00491         memcpy(data, buf, data_size);
00492     }
00493 
00494     return silent_size + data_size * s->out_bps;
00495 }
00496 
00497 static int vmdaudio_decode_frame(AVCodecContext *avctx,
00498                                  void *data, int *data_size,
00499                                  AVPacket *avpkt)
00500 {
00501     const uint8_t *buf = avpkt->data;
00502     int buf_size = avpkt->size;
00503     VmdAudioContext *s = avctx->priv_data;
00504     int block_type, silent_chunks;
00505     unsigned char *output_samples = (unsigned char *)data;
00506 
00507     if (buf_size < 16) {
00508         av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");
00509         *data_size = 0;
00510         return buf_size;
00511     }
00512 
00513     block_type = buf[6];
00514     if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {
00515         av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);
00516         return AVERROR(EINVAL);
00517     }
00518     buf      += 16;
00519     buf_size -= 16;
00520 
00521     silent_chunks = 0;
00522     if (block_type == BLOCK_TYPE_INITIAL) {
00523         uint32_t flags = AV_RB32(buf);
00524         silent_chunks  = av_popcount(flags);
00525         buf      += 4;
00526         buf_size -= 4;
00527     } else if (block_type == BLOCK_TYPE_SILENCE) {
00528         silent_chunks = 1;
00529         buf_size = 0; // should already be zero but set it just to be sure
00530     }
00531 
00532     /* ensure output buffer is large enough */
00533     if (*data_size < (avctx->block_align*silent_chunks + buf_size) * s->out_bps)
00534         return -1;
00535 
00536     *data_size = vmdaudio_loadsound(s, output_samples, buf, silent_chunks, buf_size);
00537 
00538     return avpkt->size;
00539 }
00540 
00541 
00542 /*
00543  * Public Data Structures
00544  */
00545 
00546 AVCodec ff_vmdvideo_decoder = {
00547     "vmdvideo",
00548     AVMEDIA_TYPE_VIDEO,
00549     CODEC_ID_VMDVIDEO,
00550     sizeof(VmdVideoContext),
00551     vmdvideo_decode_init,
00552     NULL,
00553     vmdvideo_decode_end,
00554     vmdvideo_decode_frame,
00555     CODEC_CAP_DR1,
00556     .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
00557 };
00558 
00559 AVCodec ff_vmdaudio_decoder = {
00560     "vmdaudio",
00561     AVMEDIA_TYPE_AUDIO,
00562     CODEC_ID_VMDAUDIO,
00563     sizeof(VmdAudioContext),
00564     vmdaudio_decode_init,
00565     NULL,
00566     NULL,
00567     vmdaudio_decode_frame,
00568     .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
00569 };