Libav 0.7.1
|
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 };