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, 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 };