• 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                                  AVPacket *avpkt)
00199 {
00200     const uint8_t *buf = avpkt->data;
00201     int buf_size = avpkt->size;
00202     CinVideoContext *cin = avctx->priv_data;
00203     int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size;
00204 
00205     cin->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00206     if (avctx->reget_buffer(avctx, &cin->frame)) {
00207         av_log(cin->avctx, AV_LOG_ERROR, "delphinecinvideo: reget_buffer() failed to allocate a frame\n");
00208         return -1;
00209     }
00210 
00211     palette_type = buf[0];
00212     palette_colors_count = AV_RL16(buf+1);
00213     bitmap_frame_type = buf[3];
00214     buf += 4;
00215 
00216     bitmap_frame_size = buf_size - 4;
00217 
00218     /* handle palette */
00219     if (palette_type == 0) {
00220         for (i = 0; i < palette_colors_count; ++i) {
00221             cin->palette[i] = bytestream_get_le24(&buf);
00222             bitmap_frame_size -= 3;
00223         }
00224     } else {
00225         for (i = 0; i < palette_colors_count; ++i) {
00226             cin->palette[buf[0]] = AV_RL24(buf+1);
00227             buf += 4;
00228             bitmap_frame_size -= 4;
00229         }
00230     }
00231     memcpy(cin->frame.data[1], cin->palette, sizeof(cin->palette));
00232     cin->frame.palette_has_changed = 1;
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         cin_decode_lzss(buf, bitmap_frame_size,
00266           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00267         break;
00268     case 39:
00269         cin_decode_lzss(buf, bitmap_frame_size,
00270           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00271         cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
00272           cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
00273         break;
00274     }
00275 
00276     for (y = 0; y < cin->avctx->height; ++y)
00277         memcpy(cin->frame.data[0] + (cin->avctx->height - 1 - y) * cin->frame.linesize[0],
00278           cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width,
00279           cin->avctx->width);
00280 
00281     FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]);
00282 
00283     *data_size = sizeof(AVFrame);
00284     *(AVFrame *)data = cin->frame;
00285 
00286     return buf_size;
00287 }
00288 
00289 static av_cold int cinvideo_decode_end(AVCodecContext *avctx)
00290 {
00291     CinVideoContext *cin = avctx->priv_data;
00292     int i;
00293 
00294     if (cin->frame.data[0])
00295         avctx->release_buffer(avctx, &cin->frame);
00296 
00297     for (i = 0; i < 3; ++i)
00298         av_free(cin->bitmap_table[i]);
00299 
00300     return 0;
00301 }
00302 
00303 static av_cold int cinaudio_decode_init(AVCodecContext *avctx)
00304 {
00305     CinAudioContext *cin = avctx->priv_data;
00306 
00307     cin->avctx = avctx;
00308     cin->initial_decode_frame = 1;
00309     cin->delta = 0;
00310     avctx->sample_fmt = SAMPLE_FMT_S16;
00311 
00312     return 0;
00313 }
00314 
00315 static int cinaudio_decode_frame(AVCodecContext *avctx,
00316                                  void *data, int *data_size,
00317                                  AVPacket *avpkt)
00318 {
00319     const uint8_t *buf = avpkt->data;
00320     int buf_size = avpkt->size;
00321     CinAudioContext *cin = avctx->priv_data;
00322     const uint8_t *src = buf;
00323     int16_t *samples = (int16_t *)data;
00324 
00325     buf_size = FFMIN(buf_size, *data_size/2);
00326 
00327     if (cin->initial_decode_frame) {
00328         cin->initial_decode_frame = 0;
00329         cin->delta = (int16_t)AV_RL16(src); src += 2;
00330         *samples++ = cin->delta;
00331         buf_size -= 2;
00332     }
00333     while (buf_size > 0) {
00334         cin->delta += cinaudio_delta16_table[*src++];
00335         cin->delta = av_clip_int16(cin->delta);
00336         *samples++ = cin->delta;
00337         --buf_size;
00338     }
00339 
00340     *data_size = (uint8_t *)samples - (uint8_t *)data;
00341 
00342     return src - buf;
00343 }
00344 
00345 
00346 AVCodec dsicinvideo_decoder = {
00347     "dsicinvideo",
00348     AVMEDIA_TYPE_VIDEO,
00349     CODEC_ID_DSICINVIDEO,
00350     sizeof(CinVideoContext),
00351     cinvideo_decode_init,
00352     NULL,
00353     cinvideo_decode_end,
00354     cinvideo_decode_frame,
00355     CODEC_CAP_DR1,
00356     .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"),
00357 };
00358 
00359 AVCodec dsicinaudio_decoder = {
00360     "dsicinaudio",
00361     AVMEDIA_TYPE_AUDIO,
00362     CODEC_ID_DSICINAUDIO,
00363     sizeof(CinAudioContext),
00364     cinaudio_decode_init,
00365     NULL,
00366     NULL,
00367     cinaudio_decode_frame,
00368     .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"),
00369 };

Generated on Fri Sep 16 2011 17:17:35 for FFmpeg by  doxygen 1.7.1