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

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