Libav 0.7.1
libavcodec/dsicinav.c
Go to the documentation of this file.
00001 /*
00002  * Delphine Software International CIN Audio/Video Decoders
00003  * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
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 
00027 #include "avcodec.h"
00028 #include "bytestream.h"
00029 
00030 
00031 typedef enum CinVideoBitmapIndex {
00032     CIN_CUR_BMP = 0, /* current */
00033     CIN_PRE_BMP = 1, /* previous */
00034     CIN_INT_BMP = 2  /* intermediate */
00035 } CinVideoBitmapIndex;
00036 
00037 typedef struct CinVideoContext {
00038     AVCodecContext *avctx;
00039     AVFrame frame;
00040     unsigned int bitmap_size;
00041     uint32_t palette[256];
00042     uint8_t *bitmap_table[3];
00043 } CinVideoContext;
00044 
00045 typedef struct CinAudioContext {
00046     AVCodecContext *avctx;
00047     int initial_decode_frame;
00048     int delta;
00049 } CinAudioContext;
00050 
00051 
00052 /* table defining a geometric sequence with multiplier = 32767 ^ (1 / 128) */
00053 static const int16_t cinaudio_delta16_table[256] = {
00054          0,      0,      0,      0,      0,      0,      0,      0,
00055          0,      0,      0,      0,      0,      0,      0,      0,
00056          0,      0,      0, -30210, -27853, -25680, -23677, -21829,
00057     -20126, -18556, -17108, -15774, -14543, -13408, -12362, -11398,
00058     -10508,  -9689,  -8933,  -8236,  -7593,  -7001,  -6455,  -5951,
00059      -5487,  -5059,  -4664,  -4300,  -3964,  -3655,  -3370,  -3107,
00060      -2865,  -2641,  -2435,  -2245,  -2070,  -1908,  -1759,  -1622,
00061      -1495,  -1379,  -1271,  -1172,  -1080,   -996,   -918,   -847,
00062       -781,   -720,   -663,   -612,   -564,   -520,   -479,   -442,
00063       -407,   -376,   -346,   -319,   -294,   -271,   -250,   -230,
00064       -212,   -196,   -181,   -166,   -153,   -141,   -130,   -120,
00065       -111,   -102,    -94,    -87,    -80,    -74,    -68,    -62,
00066        -58,    -53,    -49,    -45,    -41,    -38,    -35,    -32,
00067        -30,    -27,    -25,    -23,    -21,    -20,    -18,    -17,
00068        -15,    -14,    -13,    -12,    -11,    -10,     -9,     -8,
00069         -7,     -6,     -5,     -4,     -3,     -2,     -1,      0,
00070          0,      1,      2,      3,      4,      5,      6,      7,
00071          8,      9,     10,     11,     12,     13,     14,     15,
00072         17,     18,     20,     21,     23,     25,     27,     30,
00073         32,     35,     38,     41,     45,     49,     53,     58,
00074         62,     68,     74,     80,     87,     94,    102,    111,
00075        120,    130,    141,    153,    166,    181,    196,    212,
00076        230,    250,    271,    294,    319,    346,    376,    407,
00077        442,    479,    520,    564,    612,    663,    720,    781,
00078        847,    918,    996,   1080,   1172,   1271,   1379,   1495,
00079       1622,   1759,   1908,   2070,   2245,   2435,   2641,   2865,
00080       3107,   3370,   3655,   3964,   4300,   4664,   5059,   5487,
00081       5951,   6455,   7001,   7593,   8236,   8933,   9689,  10508,
00082      11398,  12362,  13408,  14543,  15774,  17108,  18556,  20126,
00083      21829,  23677,  25680,  27853,  30210,      0,      0,      0,
00084          0,      0,      0,      0,      0,      0,      0,      0,
00085          0,      0,      0,      0,      0,      0,      0,      0
00086 };
00087 
00088 
00089 static av_cold int cinvideo_decode_init(AVCodecContext *avctx)
00090 {
00091     CinVideoContext *cin = avctx->priv_data;
00092     unsigned int i;
00093 
00094     cin->avctx = avctx;
00095     avctx->pix_fmt = PIX_FMT_PAL8;
00096 
00097     cin->frame.data[0] = NULL;
00098 
00099     cin->bitmap_size = avctx->width * avctx->height;
00100     for (i = 0; i < 3; ++i) {
00101         cin->bitmap_table[i] = av_mallocz(cin->bitmap_size);
00102         if (!cin->bitmap_table[i])
00103             av_log(avctx, AV_LOG_ERROR, "Can't allocate bitmap buffers.\n");
00104     }
00105 
00106     return 0;
00107 }
00108 
00109 static void cin_apply_delta_data(const unsigned char *src, unsigned char *dst, int size)
00110 {
00111     while (size--)
00112         *dst++ += *src++;
00113 }
00114 
00115 static int cin_decode_huffman(const unsigned char *src, int src_size, unsigned char *dst, int dst_size)
00116 {
00117     int b, huff_code = 0;
00118     unsigned char huff_code_table[15];
00119     unsigned char *dst_cur = dst;
00120     unsigned char *dst_end = dst + dst_size;
00121     const unsigned char *src_end = src + src_size;
00122 
00123     memcpy(huff_code_table, src, 15); src += 15; src_size -= 15;
00124 
00125     while (src < src_end) {
00126         huff_code = *src++;
00127         if ((huff_code >> 4) == 15) {
00128             b = huff_code << 4;
00129             huff_code = *src++;
00130             *dst_cur++ = b | (huff_code >> 4);
00131         } else
00132             *dst_cur++ = huff_code_table[huff_code >> 4];
00133         if (dst_cur >= dst_end)
00134             break;
00135 
00136         huff_code &= 15;
00137         if (huff_code == 15) {
00138             *dst_cur++ = *src++;
00139         } else
00140             *dst_cur++ = huff_code_table[huff_code];
00141         if (dst_cur >= dst_end)
00142             break;
00143     }
00144 
00145     return dst_cur - dst;
00146 }
00147 
00148 static int cin_decode_lzss(const unsigned char *src, int src_size, unsigned char *dst, int dst_size)
00149 {
00150     uint16_t cmd;
00151     int i, sz, offset, code;
00152     unsigned char *dst_end = dst + dst_size, *dst_start = dst;
00153     const unsigned char *src_end = src + src_size;
00154 
00155     while (src < src_end && dst < dst_end) {
00156         code = *src++;
00157         for (i = 0; i < 8 && src < src_end && dst < dst_end; ++i) {
00158             if (code & (1 << i)) {
00159                 *dst++ = *src++;
00160             } else {
00161                 cmd = AV_RL16(src); src += 2;
00162                 offset = cmd >> 4;
00163                 if ((int) (dst - dst_start) < offset + 1)
00164                     return AVERROR_INVALIDDATA;
00165                 sz = (cmd & 0xF) + 2;
00166                 /* don't use memcpy/memmove here as the decoding routine (ab)uses */
00167                 /* buffer overlappings to repeat bytes in the destination */
00168                 sz = FFMIN(sz, dst_end - dst);
00169                 while (sz--) {
00170                     *dst = *(dst - offset - 1);
00171                     ++dst;
00172                 }
00173             }
00174         }
00175     }
00176 
00177     return 0;
00178 }
00179 
00180 static void cin_decode_rle(const unsigned char *src, int src_size, unsigned char *dst, int dst_size)
00181 {
00182     int len, code;
00183     unsigned char *dst_end = dst + dst_size;
00184     const unsigned char *src_end = src + src_size;
00185 
00186     while (src < src_end && dst < dst_end) {
00187         code = *src++;
00188         if (code & 0x80) {
00189             len = code - 0x7F;
00190             memset(dst, *src++, FFMIN(len, dst_end - dst));
00191         } else {
00192             len = code + 1;
00193             memcpy(dst, src, FFMIN(len, dst_end - dst));
00194             src += len;
00195         }
00196         dst += len;
00197     }
00198 }
00199 
00200 static int cinvideo_decode_frame(AVCodecContext *avctx,
00201                                  void *data, int *data_size,
00202                                  AVPacket *avpkt)
00203 {
00204     const uint8_t *buf = avpkt->data;
00205     int buf_size = avpkt->size;
00206     CinVideoContext *cin = avctx->priv_data;
00207     int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size, res = 0;
00208 
00209     palette_type = buf[0];
00210     palette_colors_count = AV_RL16(buf+1);
00211     bitmap_frame_type = buf[3];
00212     buf += 4;
00213 
00214     bitmap_frame_size = buf_size - 4;
00215 
00216     /* handle palette */
00217     if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0)))
00218         return AVERROR_INVALIDDATA;
00219     if (palette_type == 0) {
00220         if (palette_colors_count > 256)
00221             return AVERROR_INVALIDDATA;
00222         for (i = 0; i < palette_colors_count; ++i) {
00223             cin->palette[i] = bytestream_get_le24(&buf);
00224             bitmap_frame_size -= 3;
00225         }
00226     } else {
00227         for (i = 0; i < palette_colors_count; ++i) {
00228             cin->palette[buf[0]] = AV_RL24(buf+1);
00229             buf += 4;
00230             bitmap_frame_size -= 4;
00231         }
00232     }
00233 
00234     /* note: the decoding routines below assumes that surface.width = surface.pitch */
00235     switch (bitmap_frame_type) {
00236     case 9:
00237         cin_decode_rle(buf, bitmap_frame_size,
00238           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00239         break;
00240     case 34:
00241         cin_decode_rle(buf, bitmap_frame_size,
00242           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00243         cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
00244           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00245         break;
00246     case 35:
00247         cin_decode_huffman(buf, bitmap_frame_size,
00248           cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size);
00249         cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
00250           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00251         break;
00252     case 36:
00253         bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size,
00254           cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size);
00255         cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
00256           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00257         cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
00258           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00259         break;
00260     case 37:
00261         cin_decode_huffman(buf, bitmap_frame_size,
00262           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00263         break;
00264     case 38:
00265         res = cin_decode_lzss(buf, bitmap_frame_size,
00266                               cin->bitmap_table[CIN_CUR_BMP],
00267                               cin->bitmap_size);
00268         if (res < 0)
00269             return res;
00270         break;
00271     case 39:
00272         res = cin_decode_lzss(buf, bitmap_frame_size,
00273                               cin->bitmap_table[CIN_CUR_BMP],
00274                               cin->bitmap_size);
00275         if (res < 0)
00276             return res;
00277         cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
00278           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00279         break;
00280     }
00281 
00282     cin->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00283     if (avctx->reget_buffer(avctx, &cin->frame)) {
00284         av_log(cin->avctx, AV_LOG_ERROR, "delphinecinvideo: reget_buffer() failed to allocate a frame\n");
00285         return -1;
00286     }
00287 
00288     memcpy(cin->frame.data[1], cin->palette, sizeof(cin->palette));
00289     cin->frame.palette_has_changed = 1;
00290     for (y = 0; y < cin->avctx->height; ++y)
00291         memcpy(cin->frame.data[0] + (cin->avctx->height - 1 - y) * cin->frame.linesize[0],
00292           cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width,
00293           cin->avctx->width);
00294 
00295     FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]);
00296 
00297     *data_size = sizeof(AVFrame);
00298     *(AVFrame *)data = cin->frame;
00299 
00300     return buf_size;
00301 }
00302 
00303 static av_cold int cinvideo_decode_end(AVCodecContext *avctx)
00304 {
00305     CinVideoContext *cin = avctx->priv_data;
00306     int i;
00307 
00308     if (cin->frame.data[0])
00309         avctx->release_buffer(avctx, &cin->frame);
00310 
00311     for (i = 0; i < 3; ++i)
00312         av_free(cin->bitmap_table[i]);
00313 
00314     return 0;
00315 }
00316 
00317 static av_cold int cinaudio_decode_init(AVCodecContext *avctx)
00318 {
00319     CinAudioContext *cin = avctx->priv_data;
00320 
00321     cin->avctx = avctx;
00322     cin->initial_decode_frame = 1;
00323     cin->delta = 0;
00324     avctx->sample_fmt = AV_SAMPLE_FMT_S16;
00325 
00326     return 0;
00327 }
00328 
00329 static int cinaudio_decode_frame(AVCodecContext *avctx,
00330                                  void *data, int *data_size,
00331                                  AVPacket *avpkt)
00332 {
00333     const uint8_t *buf = avpkt->data;
00334     int buf_size = avpkt->size;
00335     CinAudioContext *cin = avctx->priv_data;
00336     const uint8_t *src = buf;
00337     int16_t *samples = (int16_t *)data;
00338 
00339     buf_size = FFMIN(buf_size, *data_size/2);
00340 
00341     if (cin->initial_decode_frame) {
00342         cin->initial_decode_frame = 0;
00343         cin->delta = (int16_t)AV_RL16(src); src += 2;
00344         *samples++ = cin->delta;
00345         buf_size -= 2;
00346     }
00347     while (buf_size > 0) {
00348         cin->delta += cinaudio_delta16_table[*src++];
00349         cin->delta = av_clip_int16(cin->delta);
00350         *samples++ = cin->delta;
00351         --buf_size;
00352     }
00353 
00354     *data_size = (uint8_t *)samples - (uint8_t *)data;
00355 
00356     return src - buf;
00357 }
00358 
00359 
00360 AVCodec ff_dsicinvideo_decoder = {
00361     "dsicinvideo",
00362     AVMEDIA_TYPE_VIDEO,
00363     CODEC_ID_DSICINVIDEO,
00364     sizeof(CinVideoContext),
00365     cinvideo_decode_init,
00366     NULL,
00367     cinvideo_decode_end,
00368     cinvideo_decode_frame,
00369     CODEC_CAP_DR1,
00370     .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"),
00371 };
00372 
00373 AVCodec ff_dsicinaudio_decoder = {
00374     "dsicinaudio",
00375     AVMEDIA_TYPE_AUDIO,
00376     CODEC_ID_DSICINAUDIO,
00377     sizeof(CinAudioContext),
00378     cinaudio_decode_init,
00379     NULL,
00380     NULL,
00381     cinaudio_decode_frame,
00382     .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"),
00383 };