• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • 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 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 
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 void 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;
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                 sz = (cmd & 0xF) + 2;
00164                 /* don't use memcpy/memmove here as the decoding routine (ab)uses */
00165                 /* buffer overlappings to repeat bytes in the destination */
00166                 sz = FFMIN(sz, dst_end - dst);
00167                 while (sz--) {
00168                     *dst = *(dst - offset - 1);
00169                     ++dst;
00170                 }
00171             }
00172         }
00173     }
00174 }
00175 
00176 static void cin_decode_rle(const unsigned char *src, int src_size, unsigned char *dst, int dst_size)
00177 {
00178     int len, code;
00179     unsigned char *dst_end = dst + dst_size;
00180     const unsigned char *src_end = src + src_size;
00181 
00182     while (src < src_end && dst < dst_end) {
00183         code = *src++;
00184         if (code & 0x80) {
00185             len = code - 0x7F;
00186             memset(dst, *src++, FFMIN(len, dst_end - dst));
00187         } else {
00188             len = code + 1;
00189             memcpy(dst, src, FFMIN(len, dst_end - dst));
00190             src += len;
00191         }
00192         dst += len;
00193     }
00194 }
00195 
00196 static int cinvideo_decode_frame(AVCodecContext *avctx,
00197                                  void *data, int *data_size,
00198                                  const uint8_t *buf, int buf_size)
00199 {
00200     CinVideoContext *cin = avctx->priv_data;
00201     int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size;
00202 
00203     cin->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00204     if (avctx->reget_buffer(avctx, &cin->frame)) {
00205         av_log(cin->avctx, AV_LOG_ERROR, "delphinecinvideo: reget_buffer() failed to allocate a frame\n");
00206         return -1;
00207     }
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 (palette_type == 0) {
00218         for (i = 0; i < palette_colors_count; ++i) {
00219             cin->palette[i] = bytestream_get_le24(&buf);
00220             bitmap_frame_size -= 3;
00221         }
00222     } else {
00223         for (i = 0; i < palette_colors_count; ++i) {
00224             cin->palette[buf[0]] = AV_RL24(buf+1);
00225             buf += 4;
00226             bitmap_frame_size -= 4;
00227         }
00228     }
00229     memcpy(cin->frame.data[1], cin->palette, sizeof(cin->palette));
00230     cin->frame.palette_has_changed = 1;
00231 
00232     /* note: the decoding routines below assumes that surface.width = surface.pitch */
00233     switch (bitmap_frame_type) {
00234     case 9:
00235         cin_decode_rle(buf, bitmap_frame_size,
00236           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00237         break;
00238     case 34:
00239         cin_decode_rle(buf, bitmap_frame_size,
00240           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00241         cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
00242           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00243         break;
00244     case 35:
00245         cin_decode_huffman(buf, bitmap_frame_size,
00246           cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size);
00247         cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
00248           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00249         break;
00250     case 36:
00251         bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size,
00252           cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size);
00253         cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
00254           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00255         cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
00256           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00257         break;
00258     case 37:
00259         cin_decode_huffman(buf, bitmap_frame_size,
00260           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00261         break;
00262     case 38:
00263         cin_decode_lzss(buf, bitmap_frame_size,
00264           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00265         break;
00266     case 39:
00267         cin_decode_lzss(buf, bitmap_frame_size,
00268           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00269         cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
00270           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00271         break;
00272     }
00273 
00274     for (y = 0; y < cin->avctx->height; ++y)
00275         memcpy(cin->frame.data[0] + (cin->avctx->height - 1 - y) * cin->frame.linesize[0],
00276           cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width,
00277           cin->avctx->width);
00278 
00279     FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]);
00280 
00281     *data_size = sizeof(AVFrame);
00282     *(AVFrame *)data = cin->frame;
00283 
00284     return buf_size;
00285 }
00286 
00287 static av_cold int cinvideo_decode_end(AVCodecContext *avctx)
00288 {
00289     CinVideoContext *cin = avctx->priv_data;
00290     int i;
00291 
00292     if (cin->frame.data[0])
00293         avctx->release_buffer(avctx, &cin->frame);
00294 
00295     for (i = 0; i < 3; ++i)
00296         av_free(cin->bitmap_table[i]);
00297 
00298     return 0;
00299 }
00300 
00301 static av_cold int cinaudio_decode_init(AVCodecContext *avctx)
00302 {
00303     CinAudioContext *cin = avctx->priv_data;
00304 
00305     cin->avctx = avctx;
00306     cin->initial_decode_frame = 1;
00307     cin->delta = 0;
00308     avctx->sample_fmt = SAMPLE_FMT_S16;
00309 
00310     return 0;
00311 }
00312 
00313 static int cinaudio_decode_frame(AVCodecContext *avctx,
00314                                  void *data, int *data_size,
00315                                  const uint8_t *buf, int buf_size)
00316 {
00317     CinAudioContext *cin = avctx->priv_data;
00318     const uint8_t *src = buf;
00319     int16_t *samples = (int16_t *)data;
00320 
00321     buf_size = FFMIN(buf_size, *data_size/2);
00322 
00323     if (cin->initial_decode_frame) {
00324         cin->initial_decode_frame = 0;
00325         cin->delta = (int16_t)AV_RL16(src); src += 2;
00326         *samples++ = cin->delta;
00327         buf_size -= 2;
00328     }
00329     while (buf_size > 0) {
00330         cin->delta += cinaudio_delta16_table[*src++];
00331         cin->delta = av_clip_int16(cin->delta);
00332         *samples++ = cin->delta;
00333         --buf_size;
00334     }
00335 
00336     *data_size = (uint8_t *)samples - (uint8_t *)data;
00337 
00338     return src - buf;
00339 }
00340 
00341 
00342 AVCodec dsicinvideo_decoder = {
00343     "dsicinvideo",
00344     CODEC_TYPE_VIDEO,
00345     CODEC_ID_DSICINVIDEO,
00346     sizeof(CinVideoContext),
00347     cinvideo_decode_init,
00348     NULL,
00349     cinvideo_decode_end,
00350     cinvideo_decode_frame,
00351     CODEC_CAP_DR1,
00352     .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"),
00353 };
00354 
00355 AVCodec dsicinaudio_decoder = {
00356     "dsicinaudio",
00357     CODEC_TYPE_AUDIO,
00358     CODEC_ID_DSICINAUDIO,
00359     sizeof(CinAudioContext),
00360     cinaudio_decode_init,
00361     NULL,
00362     NULL,
00363     cinaudio_decode_frame,
00364     .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"),
00365 };

Generated on Sat Feb 16 2013 09:23:11 for ffmpeg by  doxygen 1.7.1