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