• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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     int dp_size;
00227 
00228     frame_x = AV_RL16(&s->buf[6]);
00229     frame_y = AV_RL16(&s->buf[8]);
00230     frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
00231     frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
00232     if (frame_x < 0 || frame_width < 0 ||
00233         frame_x >= s->avctx->width ||
00234         frame_width > s->avctx->width ||
00235         frame_x + frame_width > s->avctx->width)
00236         return;
00237     if (frame_y < 0 || frame_height < 0 ||
00238         frame_y >= s->avctx->height ||
00239         frame_height > s->avctx->height ||
00240         frame_y + frame_height > s->avctx->height)
00241         return;
00242 
00243     if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
00244         (frame_x || frame_y)) {
00245 
00246         s->x_off = frame_x;
00247         s->y_off = frame_y;
00248     }
00249     frame_x -= s->x_off;
00250     frame_y -= s->y_off;
00251 
00252     /* if only a certain region will be updated, copy the entire previous
00253      * frame before the decode */
00254     if (s->prev_frame.data[0] &&
00255         (frame_x || frame_y || (frame_width != s->avctx->width) ||
00256         (frame_height != s->avctx->height))) {
00257 
00258         memcpy(s->frame.data[0], s->prev_frame.data[0],
00259             s->avctx->height * s->frame.linesize[0]);
00260     }
00261 
00262     /* check if there is a new palette */
00263     if (s->buf[15] & 0x02) {
00264         p += 2;
00265         palette32 = (unsigned int *)s->palette;
00266         for (i = 0; i < PALETTE_COUNT; i++) {
00267             r = *p++ * 4;
00268             g = *p++ * 4;
00269             b = *p++ * 4;
00270             palette32[i] = (r << 16) | (g << 8) | (b);
00271         }
00272         s->size -= (256 * 3 + 2);
00273     }
00274     if (s->size > 0) {
00275         /* originally UnpackFrame in VAG's code */
00276         pb = p;
00277         pb_size = s->buf + s->size - pb;
00278         if (pb_size < 1)
00279             return;
00280         meth = *pb++; pb_size--;
00281         if (meth & 0x80) {
00282             lz_unpack(pb, pb_size,
00283                       s->unpack_buffer, s->unpack_buffer_size);
00284             meth &= 0x7F;
00285             pb = s->unpack_buffer;
00286             pb_size = s->unpack_buffer_size;
00287         }
00288 
00289         dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
00290         dp_size = s->frame.linesize[0] * s->avctx->height;
00291         pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
00292         switch (meth) {
00293         case 1:
00294             for (i = 0; i < frame_height; i++) {
00295                 ofs = 0;
00296                 do {
00297                     if (pb_size < 1)
00298                         return;
00299                     len = *pb++;
00300                     pb_size--;
00301                     if (len & 0x80) {
00302                         len = (len & 0x7F) + 1;
00303                         if (ofs + len > frame_width || pb_size < len)
00304                             return;
00305                         memcpy(&dp[ofs], pb, len);
00306                         pb += len;
00307                         pb_size -= len;
00308                         ofs += len;
00309                     } else {
00310                         /* interframe pixel copy */
00311                         if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
00312                             return;
00313                         memcpy(&dp[ofs], &pp[ofs], len + 1);
00314                         ofs += len + 1;
00315                     }
00316                 } while (ofs < frame_width);
00317                 if (ofs > frame_width) {
00318                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00319                         ofs, frame_width);
00320                     break;
00321                 }
00322                 dp += s->frame.linesize[0];
00323                 pp += s->prev_frame.linesize[0];
00324             }
00325             break;
00326 
00327         case 2:
00328             for (i = 0; i < frame_height; i++) {
00329                 if (pb_size < frame_width)
00330                     return;
00331                 memcpy(dp, pb, frame_width);
00332                 pb += frame_width;
00333                 pb_size -= frame_width;
00334                 dp += s->frame.linesize[0];
00335                 pp += s->prev_frame.linesize[0];
00336             }
00337             break;
00338 
00339         case 3:
00340             for (i = 0; i < frame_height; i++) {
00341                 ofs = 0;
00342                 do {
00343                     if (pb_size < 1)
00344                         return;
00345                     len = *pb++;
00346                     pb_size--;
00347                     if (len & 0x80) {
00348                         len = (len & 0x7F) + 1;
00349                         if (pb_size < 1)
00350                             return;
00351                         if (*pb++ == 0xFF)
00352                             len = rle_unpack(pb, &dp[ofs], len, pb_size, frame_width - ofs);
00353                         else {
00354                             if (pb_size < len)
00355                                 return;
00356                             memcpy(&dp[ofs], pb, len);
00357                         }
00358                         pb += len;
00359                         pb_size -= 1 + len;
00360                         ofs += len;
00361                     } else {
00362                         /* interframe pixel copy */
00363                         if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
00364                             return;
00365                         memcpy(&dp[ofs], &pp[ofs], len + 1);
00366                         ofs += len + 1;
00367                     }
00368                 } while (ofs < frame_width);
00369                 if (ofs > frame_width) {
00370                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
00371                         ofs, frame_width);
00372                 }
00373                 dp += s->frame.linesize[0];
00374                 pp += s->prev_frame.linesize[0];
00375             }
00376             break;
00377         }
00378     }
00379 }
00380 
00381 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
00382 {
00383     VmdVideoContext *s = avctx->priv_data;
00384     int i;
00385     unsigned int *palette32;
00386     int palette_index = 0;
00387     unsigned char r, g, b;
00388     unsigned char *vmd_header;
00389     unsigned char *raw_palette;
00390 
00391     s->avctx = avctx;
00392     avctx->pix_fmt = PIX_FMT_PAL8;
00393 
00394     /* make sure the VMD header made it */
00395     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
00396         av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
00397             VMD_HEADER_SIZE);
00398         return -1;
00399     }
00400     vmd_header = (unsigned char *)avctx->extradata;
00401 
00402     s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
00403     s->unpack_buffer = av_malloc(s->unpack_buffer_size);
00404     if (!s->unpack_buffer)
00405         return -1;
00406 
00407     /* load up the initial palette */
00408     raw_palette = &vmd_header[28];
00409     palette32 = (unsigned int *)s->palette;
00410     for (i = 0; i < PALETTE_COUNT; i++) {
00411         r = raw_palette[palette_index++] * 4;
00412         g = raw_palette[palette_index++] * 4;
00413         b = raw_palette[palette_index++] * 4;
00414         palette32[i] = (r << 16) | (g << 8) | (b);
00415     }
00416 
00417     return 0;
00418 }
00419 
00420 static int vmdvideo_decode_frame(AVCodecContext *avctx,
00421                                  void *data, int *data_size,
00422                                  AVPacket *avpkt)
00423 {
00424     const uint8_t *buf = avpkt->data;
00425     int buf_size = avpkt->size;
00426     VmdVideoContext *s = avctx->priv_data;
00427 
00428     s->buf = buf;
00429     s->size = buf_size;
00430 
00431     if (buf_size < 16)
00432         return buf_size;
00433 
00434     s->frame.reference = 1;
00435     if (avctx->get_buffer(avctx, &s->frame)) {
00436         av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
00437         return -1;
00438     }
00439 
00440     vmd_decode(s);
00441 
00442     /* make the palette available on the way out */
00443     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
00444 
00445     /* shuffle frames */
00446     FFSWAP(AVFrame, s->frame, s->prev_frame);
00447     if (s->frame.data[0])
00448         avctx->release_buffer(avctx, &s->frame);
00449 
00450     *data_size = sizeof(AVFrame);
00451     *(AVFrame*)data = s->prev_frame;
00452 
00453     /* report that the buffer was completely consumed */
00454     return buf_size;
00455 }
00456 
00457 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
00458 {
00459     VmdVideoContext *s = avctx->priv_data;
00460 
00461     if (s->prev_frame.data[0])
00462         avctx->release_buffer(avctx, &s->prev_frame);
00463     av_free(s->unpack_buffer);
00464 
00465     return 0;
00466 }
00467 
00468 
00469 /*
00470  * Audio Decoder
00471  */
00472 
00473 typedef struct VmdAudioContext {
00474     AVCodecContext *avctx;
00475     int channels;
00476     int bits;
00477     int block_align;
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     s->channels = avctx->channels;
00503     s->bits = avctx->bits_per_coded_sample;
00504     s->block_align = avctx->block_align;
00505     avctx->sample_fmt = SAMPLE_FMT_S16;
00506 
00507     av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
00508             s->channels, s->bits, s->block_align, avctx->sample_rate);
00509 
00510     return 0;
00511 }
00512 
00513 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
00514     const uint8_t *buf, int buf_size, int stereo)
00515 {
00516     int i;
00517     int chan = 0;
00518     int16_t *out = (int16_t*)data;
00519 
00520     for(i = 0; i < buf_size; i++) {
00521         if(buf[i] & 0x80)
00522             s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
00523         else
00524             s->predictors[chan] += vmdaudio_table[buf[i]];
00525         s->predictors[chan] = av_clip_int16(s->predictors[chan]);
00526         out[i] = s->predictors[chan];
00527         chan ^= stereo;
00528     }
00529 }
00530 
00531 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
00532     const uint8_t *buf, int silence, int data_size)
00533 {
00534     int bytes_decoded = 0;
00535     int i;
00536 
00537 //    if (silence)
00538 //        av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
00539     if (s->channels == 2) {
00540 
00541         /* stereo handling */
00542         if (silence) {
00543             memset(data, 0, data_size * 2);
00544         } else {
00545             if (s->bits == 16)
00546                 vmdaudio_decode_audio(s, data, buf, data_size, 1);
00547             else {
00548                 /* copy the data but convert it to signed */
00549                 for (i = 0; i < data_size; i++){
00550                     *data++ = buf[i] + 0x80;
00551                     *data++ = buf[i] + 0x80;
00552                 }
00553             }
00554         }
00555     } else {
00556         bytes_decoded = data_size * 2;
00557 
00558         /* mono handling */
00559         if (silence) {
00560             memset(data, 0, data_size * 2);
00561         } else {
00562             if (s->bits == 16) {
00563                 vmdaudio_decode_audio(s, data, buf, data_size, 0);
00564             } else {
00565                 /* copy the data but convert it to signed */
00566                 for (i = 0; i < data_size; i++){
00567                     *data++ = buf[i] + 0x80;
00568                     *data++ = buf[i] + 0x80;
00569                 }
00570             }
00571         }
00572     }
00573 
00574     return data_size * 2;
00575 }
00576 
00577 static int vmdaudio_decode_frame(AVCodecContext *avctx,
00578                                  void *data, int *data_size,
00579                                  AVPacket *avpkt)
00580 {
00581     const uint8_t *buf = avpkt->data;
00582     int buf_size = avpkt->size;
00583     VmdAudioContext *s = avctx->priv_data;
00584     unsigned char *output_samples = (unsigned char *)data;
00585 
00586     /* point to the start of the encoded data */
00587     const unsigned char *p = buf + 16;
00588 
00589     if (buf_size < 16)
00590         return buf_size;
00591 
00592     if (buf[6] == 1) {
00593         /* the chunk contains audio */
00594         *data_size = vmdaudio_loadsound(s, output_samples, p, 0, buf_size - 16);
00595     } else if (buf[6] == 2) {
00596         /* initial chunk, may contain audio and silence */
00597         uint32_t flags = AV_RB32(p);
00598         int raw_block_size = s->block_align * s->bits / 8;
00599         int silent_chunks;
00600         if(flags == 0xFFFFFFFF)
00601             silent_chunks = 32;
00602         else
00603             silent_chunks = av_log2(flags + 1);
00604         if(*data_size < (s->block_align*silent_chunks + buf_size - 20) * 2)
00605             return -1;
00606         *data_size = 0;
00607         memset(output_samples, 0, raw_block_size * silent_chunks);
00608         output_samples += raw_block_size * silent_chunks;
00609         *data_size = raw_block_size * silent_chunks;
00610         *data_size += vmdaudio_loadsound(s, output_samples, p + 4, 0, buf_size - 20);
00611     } else if (buf[6] == 3) {
00612         /* silent chunk */
00613         *data_size = vmdaudio_loadsound(s, output_samples, p, 1, 0);
00614     }
00615 
00616     return buf_size;
00617 }
00618 
00619 
00620 /*
00621  * Public Data Structures
00622  */
00623 
00624 AVCodec vmdvideo_decoder = {
00625     "vmdvideo",
00626     AVMEDIA_TYPE_VIDEO,
00627     CODEC_ID_VMDVIDEO,
00628     sizeof(VmdVideoContext),
00629     vmdvideo_decode_init,
00630     NULL,
00631     vmdvideo_decode_end,
00632     vmdvideo_decode_frame,
00633     CODEC_CAP_DR1,
00634     .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
00635 };
00636 
00637 AVCodec vmdaudio_decoder = {
00638     "vmdaudio",
00639     AVMEDIA_TYPE_AUDIO,
00640     CODEC_ID_VMDAUDIO,
00641     sizeof(VmdAudioContext),
00642     vmdaudio_decode_init,
00643     NULL,
00644     NULL,
00645     vmdaudio_decode_frame,
00646     .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
00647 };

Generated on Wed Dec 21 2011 18:44:10 for FFmpeg by  doxygen 1.7.1