annotate ffmpeg/libavcodec/dsicinav.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Delphine Software International CIN Audio/Video Decoders
yading@10 3 * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * Delphine Software International CIN audio/video decoders
yading@10 25 */
yading@10 26
yading@10 27 #include "libavutil/channel_layout.h"
yading@10 28 #include "avcodec.h"
yading@10 29 #include "bytestream.h"
yading@10 30 #include "internal.h"
yading@10 31 #include "mathops.h"
yading@10 32
yading@10 33
yading@10 34 typedef enum CinVideoBitmapIndex {
yading@10 35 CIN_CUR_BMP = 0, /* current */
yading@10 36 CIN_PRE_BMP = 1, /* previous */
yading@10 37 CIN_INT_BMP = 2 /* intermediate */
yading@10 38 } CinVideoBitmapIndex;
yading@10 39
yading@10 40 typedef struct CinVideoContext {
yading@10 41 AVCodecContext *avctx;
yading@10 42 AVFrame frame;
yading@10 43 unsigned int bitmap_size;
yading@10 44 uint32_t palette[256];
yading@10 45 uint8_t *bitmap_table[3];
yading@10 46 } CinVideoContext;
yading@10 47
yading@10 48 typedef struct CinAudioContext {
yading@10 49 int initial_decode_frame;
yading@10 50 int delta;
yading@10 51 } CinAudioContext;
yading@10 52
yading@10 53
yading@10 54 /* table defining a geometric sequence with multiplier = 32767 ^ (1 / 128) */
yading@10 55 static const int16_t cinaudio_delta16_table[256] = {
yading@10 56 0, 0, 0, 0, 0, 0, 0, 0,
yading@10 57 0, 0, 0, 0, 0, 0, 0, 0,
yading@10 58 0, 0, 0, -30210, -27853, -25680, -23677, -21829,
yading@10 59 -20126, -18556, -17108, -15774, -14543, -13408, -12362, -11398,
yading@10 60 -10508, -9689, -8933, -8236, -7593, -7001, -6455, -5951,
yading@10 61 -5487, -5059, -4664, -4300, -3964, -3655, -3370, -3107,
yading@10 62 -2865, -2641, -2435, -2245, -2070, -1908, -1759, -1622,
yading@10 63 -1495, -1379, -1271, -1172, -1080, -996, -918, -847,
yading@10 64 -781, -720, -663, -612, -564, -520, -479, -442,
yading@10 65 -407, -376, -346, -319, -294, -271, -250, -230,
yading@10 66 -212, -196, -181, -166, -153, -141, -130, -120,
yading@10 67 -111, -102, -94, -87, -80, -74, -68, -62,
yading@10 68 -58, -53, -49, -45, -41, -38, -35, -32,
yading@10 69 -30, -27, -25, -23, -21, -20, -18, -17,
yading@10 70 -15, -14, -13, -12, -11, -10, -9, -8,
yading@10 71 -7, -6, -5, -4, -3, -2, -1, 0,
yading@10 72 0, 1, 2, 3, 4, 5, 6, 7,
yading@10 73 8, 9, 10, 11, 12, 13, 14, 15,
yading@10 74 17, 18, 20, 21, 23, 25, 27, 30,
yading@10 75 32, 35, 38, 41, 45, 49, 53, 58,
yading@10 76 62, 68, 74, 80, 87, 94, 102, 111,
yading@10 77 120, 130, 141, 153, 166, 181, 196, 212,
yading@10 78 230, 250, 271, 294, 319, 346, 376, 407,
yading@10 79 442, 479, 520, 564, 612, 663, 720, 781,
yading@10 80 847, 918, 996, 1080, 1172, 1271, 1379, 1495,
yading@10 81 1622, 1759, 1908, 2070, 2245, 2435, 2641, 2865,
yading@10 82 3107, 3370, 3655, 3964, 4300, 4664, 5059, 5487,
yading@10 83 5951, 6455, 7001, 7593, 8236, 8933, 9689, 10508,
yading@10 84 11398, 12362, 13408, 14543, 15774, 17108, 18556, 20126,
yading@10 85 21829, 23677, 25680, 27853, 30210, 0, 0, 0,
yading@10 86 0, 0, 0, 0, 0, 0, 0, 0,
yading@10 87 0, 0, 0, 0, 0, 0, 0, 0
yading@10 88 };
yading@10 89
yading@10 90 static av_cold void destroy_buffers(CinVideoContext *cin)
yading@10 91 {
yading@10 92 int i;
yading@10 93
yading@10 94 for (i = 0; i < 3; ++i)
yading@10 95 av_freep(&cin->bitmap_table[i]);
yading@10 96 }
yading@10 97
yading@10 98 static av_cold int allocate_buffers(CinVideoContext *cin)
yading@10 99 {
yading@10 100 int i;
yading@10 101
yading@10 102 for (i = 0; i < 3; ++i) {
yading@10 103 cin->bitmap_table[i] = av_mallocz(cin->bitmap_size);
yading@10 104 if (!cin->bitmap_table[i]) {
yading@10 105 av_log(cin->avctx, AV_LOG_ERROR, "Can't allocate bitmap buffers.\n");
yading@10 106 destroy_buffers(cin);
yading@10 107 return AVERROR(ENOMEM);
yading@10 108 }
yading@10 109 }
yading@10 110
yading@10 111 return 0;
yading@10 112 }
yading@10 113
yading@10 114 static av_cold int cinvideo_decode_init(AVCodecContext *avctx)
yading@10 115 {
yading@10 116 CinVideoContext *cin = avctx->priv_data;
yading@10 117
yading@10 118 cin->avctx = avctx;
yading@10 119 avctx->pix_fmt = AV_PIX_FMT_PAL8;
yading@10 120
yading@10 121 avcodec_get_frame_defaults(&cin->frame);
yading@10 122
yading@10 123 cin->bitmap_size = avctx->width * avctx->height;
yading@10 124 if (allocate_buffers(cin))
yading@10 125 return AVERROR(ENOMEM);
yading@10 126
yading@10 127 return 0;
yading@10 128 }
yading@10 129
yading@10 130 static void cin_apply_delta_data(const unsigned char *src, unsigned char *dst, int size)
yading@10 131 {
yading@10 132 while (size--)
yading@10 133 *dst++ += *src++;
yading@10 134 }
yading@10 135
yading@10 136 static int cin_decode_huffman(const unsigned char *src, int src_size, unsigned char *dst, int dst_size)
yading@10 137 {
yading@10 138 int b, huff_code = 0;
yading@10 139 unsigned char huff_code_table[15];
yading@10 140 unsigned char *dst_cur = dst;
yading@10 141 unsigned char *dst_end = dst + dst_size;
yading@10 142 const unsigned char *src_end = src + src_size;
yading@10 143
yading@10 144 memcpy(huff_code_table, src, 15); src += 15;
yading@10 145
yading@10 146 while (src < src_end) {
yading@10 147 huff_code = *src++;
yading@10 148 if ((huff_code >> 4) == 15) {
yading@10 149 b = huff_code << 4;
yading@10 150 huff_code = *src++;
yading@10 151 *dst_cur++ = b | (huff_code >> 4);
yading@10 152 } else
yading@10 153 *dst_cur++ = huff_code_table[huff_code >> 4];
yading@10 154 if (dst_cur >= dst_end)
yading@10 155 break;
yading@10 156
yading@10 157 huff_code &= 15;
yading@10 158 if (huff_code == 15) {
yading@10 159 *dst_cur++ = *src++;
yading@10 160 } else
yading@10 161 *dst_cur++ = huff_code_table[huff_code];
yading@10 162 if (dst_cur >= dst_end)
yading@10 163 break;
yading@10 164 }
yading@10 165
yading@10 166 return dst_cur - dst;
yading@10 167 }
yading@10 168
yading@10 169 static int cin_decode_lzss(const unsigned char *src, int src_size, unsigned char *dst, int dst_size)
yading@10 170 {
yading@10 171 uint16_t cmd;
yading@10 172 int i, sz, offset, code;
yading@10 173 unsigned char *dst_end = dst + dst_size, *dst_start = dst;
yading@10 174 const unsigned char *src_end = src + src_size;
yading@10 175
yading@10 176 while (src < src_end && dst < dst_end) {
yading@10 177 code = *src++;
yading@10 178 for (i = 0; i < 8 && src < src_end && dst < dst_end; ++i) {
yading@10 179 if (code & (1 << i)) {
yading@10 180 *dst++ = *src++;
yading@10 181 } else {
yading@10 182 cmd = AV_RL16(src); src += 2;
yading@10 183 offset = cmd >> 4;
yading@10 184 if ((int) (dst - dst_start) < offset + 1)
yading@10 185 return AVERROR_INVALIDDATA;
yading@10 186 sz = (cmd & 0xF) + 2;
yading@10 187 /* don't use memcpy/memmove here as the decoding routine (ab)uses */
yading@10 188 /* buffer overlappings to repeat bytes in the destination */
yading@10 189 sz = FFMIN(sz, dst_end - dst);
yading@10 190 while (sz--) {
yading@10 191 *dst = *(dst - offset - 1);
yading@10 192 ++dst;
yading@10 193 }
yading@10 194 }
yading@10 195 }
yading@10 196 }
yading@10 197
yading@10 198 return 0;
yading@10 199 }
yading@10 200
yading@10 201 static int cin_decode_rle(const unsigned char *src, int src_size, unsigned char *dst, int dst_size)
yading@10 202 {
yading@10 203 int len, code;
yading@10 204 unsigned char *dst_end = dst + dst_size;
yading@10 205 const unsigned char *src_end = src + src_size;
yading@10 206
yading@10 207 while (src + 1 < src_end && dst < dst_end) {
yading@10 208 code = *src++;
yading@10 209 if (code & 0x80) {
yading@10 210 len = code - 0x7F;
yading@10 211 memset(dst, *src++, FFMIN(len, dst_end - dst));
yading@10 212 } else {
yading@10 213 len = code + 1;
yading@10 214 if (len > src_end-src) {
yading@10 215 av_log(NULL, AV_LOG_ERROR, "RLE overread\n");
yading@10 216 return AVERROR_INVALIDDATA;
yading@10 217 }
yading@10 218 memcpy(dst, src, FFMIN(len, dst_end - dst));
yading@10 219 src += len;
yading@10 220 }
yading@10 221 dst += len;
yading@10 222 }
yading@10 223 return 0;
yading@10 224 }
yading@10 225
yading@10 226 static int cinvideo_decode_frame(AVCodecContext *avctx,
yading@10 227 void *data, int *got_frame,
yading@10 228 AVPacket *avpkt)
yading@10 229 {
yading@10 230 const uint8_t *buf = avpkt->data;
yading@10 231 int buf_size = avpkt->size;
yading@10 232 CinVideoContext *cin = avctx->priv_data;
yading@10 233 int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size, res = 0;
yading@10 234
yading@10 235 palette_type = buf[0];
yading@10 236 palette_colors_count = AV_RL16(buf+1);
yading@10 237 bitmap_frame_type = buf[3];
yading@10 238 buf += 4;
yading@10 239
yading@10 240 bitmap_frame_size = buf_size - 4;
yading@10 241
yading@10 242 /* handle palette */
yading@10 243 if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0)))
yading@10 244 return AVERROR_INVALIDDATA;
yading@10 245 if (palette_type == 0) {
yading@10 246 if (palette_colors_count > 256)
yading@10 247 return AVERROR_INVALIDDATA;
yading@10 248 for (i = 0; i < palette_colors_count; ++i) {
yading@10 249 cin->palette[i] = 0xFFU << 24 | bytestream_get_le24(&buf);
yading@10 250 bitmap_frame_size -= 3;
yading@10 251 }
yading@10 252 } else {
yading@10 253 for (i = 0; i < palette_colors_count; ++i) {
yading@10 254 cin->palette[buf[0]] = 0xFFU << 24 | AV_RL24(buf+1);
yading@10 255 buf += 4;
yading@10 256 bitmap_frame_size -= 4;
yading@10 257 }
yading@10 258 }
yading@10 259
yading@10 260 /* note: the decoding routines below assumes that surface.width = surface.pitch */
yading@10 261 switch (bitmap_frame_type) {
yading@10 262 case 9:
yading@10 263 cin_decode_rle(buf, bitmap_frame_size,
yading@10 264 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 265 break;
yading@10 266 case 34:
yading@10 267 cin_decode_rle(buf, bitmap_frame_size,
yading@10 268 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 269 cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
yading@10 270 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 271 break;
yading@10 272 case 35:
yading@10 273 bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size,
yading@10 274 cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size);
yading@10 275 cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
yading@10 276 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 277 break;
yading@10 278 case 36:
yading@10 279 bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size,
yading@10 280 cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size);
yading@10 281 cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
yading@10 282 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 283 cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
yading@10 284 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 285 break;
yading@10 286 case 37:
yading@10 287 cin_decode_huffman(buf, bitmap_frame_size,
yading@10 288 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 289 break;
yading@10 290 case 38:
yading@10 291 res = cin_decode_lzss(buf, bitmap_frame_size,
yading@10 292 cin->bitmap_table[CIN_CUR_BMP],
yading@10 293 cin->bitmap_size);
yading@10 294 if (res < 0)
yading@10 295 return res;
yading@10 296 break;
yading@10 297 case 39:
yading@10 298 res = cin_decode_lzss(buf, bitmap_frame_size,
yading@10 299 cin->bitmap_table[CIN_CUR_BMP],
yading@10 300 cin->bitmap_size);
yading@10 301 if (res < 0)
yading@10 302 return res;
yading@10 303 cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
yading@10 304 cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
yading@10 305 break;
yading@10 306 }
yading@10 307
yading@10 308 if ((res = ff_reget_buffer(avctx, &cin->frame)) < 0)
yading@10 309 return res;
yading@10 310
yading@10 311 memcpy(cin->frame.data[1], cin->palette, sizeof(cin->palette));
yading@10 312 cin->frame.palette_has_changed = 1;
yading@10 313 for (y = 0; y < cin->avctx->height; ++y)
yading@10 314 memcpy(cin->frame.data[0] + (cin->avctx->height - 1 - y) * cin->frame.linesize[0],
yading@10 315 cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width,
yading@10 316 cin->avctx->width);
yading@10 317
yading@10 318 FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]);
yading@10 319
yading@10 320 if ((res = av_frame_ref(data, &cin->frame)) < 0)
yading@10 321 return res;
yading@10 322
yading@10 323 *got_frame = 1;
yading@10 324
yading@10 325 return buf_size;
yading@10 326 }
yading@10 327
yading@10 328 static av_cold int cinvideo_decode_end(AVCodecContext *avctx)
yading@10 329 {
yading@10 330 CinVideoContext *cin = avctx->priv_data;
yading@10 331
yading@10 332 av_frame_unref(&cin->frame);
yading@10 333
yading@10 334 destroy_buffers(cin);
yading@10 335
yading@10 336 return 0;
yading@10 337 }
yading@10 338
yading@10 339 static av_cold int cinaudio_decode_init(AVCodecContext *avctx)
yading@10 340 {
yading@10 341 CinAudioContext *cin = avctx->priv_data;
yading@10 342
yading@10 343 cin->initial_decode_frame = 1;
yading@10 344 cin->delta = 0;
yading@10 345 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
yading@10 346 avctx->channels = 1;
yading@10 347 avctx->channel_layout = AV_CH_LAYOUT_MONO;
yading@10 348
yading@10 349 return 0;
yading@10 350 }
yading@10 351
yading@10 352 static int cinaudio_decode_frame(AVCodecContext *avctx, void *data,
yading@10 353 int *got_frame_ptr, AVPacket *avpkt)
yading@10 354 {
yading@10 355 AVFrame *frame = data;
yading@10 356 const uint8_t *buf = avpkt->data;
yading@10 357 CinAudioContext *cin = avctx->priv_data;
yading@10 358 const uint8_t *buf_end = buf + avpkt->size;
yading@10 359 int16_t *samples;
yading@10 360 int delta, ret;
yading@10 361
yading@10 362 /* get output buffer */
yading@10 363 frame->nb_samples = avpkt->size - cin->initial_decode_frame;
yading@10 364 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
yading@10 365 return ret;
yading@10 366 samples = (int16_t *)frame->data[0];
yading@10 367
yading@10 368 delta = cin->delta;
yading@10 369 if (cin->initial_decode_frame) {
yading@10 370 cin->initial_decode_frame = 0;
yading@10 371 delta = sign_extend(AV_RL16(buf), 16);
yading@10 372 buf += 2;
yading@10 373 *samples++ = delta;
yading@10 374 }
yading@10 375 while (buf < buf_end) {
yading@10 376 delta += cinaudio_delta16_table[*buf++];
yading@10 377 delta = av_clip_int16(delta);
yading@10 378 *samples++ = delta;
yading@10 379 }
yading@10 380 cin->delta = delta;
yading@10 381
yading@10 382 *got_frame_ptr = 1;
yading@10 383
yading@10 384 return avpkt->size;
yading@10 385 }
yading@10 386
yading@10 387
yading@10 388 AVCodec ff_dsicinvideo_decoder = {
yading@10 389 .name = "dsicinvideo",
yading@10 390 .type = AVMEDIA_TYPE_VIDEO,
yading@10 391 .id = AV_CODEC_ID_DSICINVIDEO,
yading@10 392 .priv_data_size = sizeof(CinVideoContext),
yading@10 393 .init = cinvideo_decode_init,
yading@10 394 .close = cinvideo_decode_end,
yading@10 395 .decode = cinvideo_decode_frame,
yading@10 396 .capabilities = CODEC_CAP_DR1,
yading@10 397 .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"),
yading@10 398 };
yading@10 399
yading@10 400 AVCodec ff_dsicinaudio_decoder = {
yading@10 401 .name = "dsicinaudio",
yading@10 402 .type = AVMEDIA_TYPE_AUDIO,
yading@10 403 .id = AV_CODEC_ID_DSICINAUDIO,
yading@10 404 .priv_data_size = sizeof(CinAudioContext),
yading@10 405 .init = cinaudio_decode_init,
yading@10 406 .decode = cinaudio_decode_frame,
yading@10 407 .capabilities = CODEC_CAP_DR1,
yading@10 408 .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"),
yading@10 409 };