ffmpeg / libavcodec / dsicinav.c @ 72415b2a
History | View | Annotate | Download (12.2 KB)
1 | 72450e50 | Baptiste Coudurier | /*
|
---|---|---|---|
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 | bad5537e | Diego Biurrun | * @file libavcodec/dsicinav.c
|
24 | 72450e50 | Baptiste Coudurier | * Delphine Software International CIN audio/video decoders
|
25 | */
|
||
26 | |||
27 | #include "avcodec.h" |
||
28 | 2c124cb6 | Ramiro Polla | #include "bytestream.h" |
29 | 72450e50 | Baptiste Coudurier | |
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 | 98a6fff9 | Zuxy Meng | static av_cold int cinvideo_decode_init(AVCodecContext *avctx) |
90 | 72450e50 | Baptiste Coudurier | { |
91 | e4141433 | Nicholas Tung | CinVideoContext *cin = avctx->priv_data; |
92 | 72450e50 | Baptiste Coudurier | unsigned int i; |
93 | |||
94 | cin->avctx = avctx; |
||
95 | avctx->pix_fmt = PIX_FMT_PAL8; |
||
96 | |||
97 | cin->frame.data[0] = NULL; |
||
98 | |||
99 | cin->bitmap_size = avctx->width * avctx->height; |
||
100 | for (i = 0; i < 3; ++i) { |
||
101 | cin->bitmap_table[i] = av_mallocz(cin->bitmap_size); |
||
102 | if (!cin->bitmap_table[i])
|
||
103 | av_log(avctx, AV_LOG_ERROR, "Can't allocate bitmap buffers.\n");
|
||
104 | } |
||
105 | |||
106 | return 0; |
||
107 | } |
||
108 | |||
109 | static void cin_apply_delta_data(const unsigned char *src, unsigned char *dst, int size) |
||
110 | { |
||
111 | while (size--)
|
||
112 | *dst++ += *src++; |
||
113 | } |
||
114 | |||
115 | static int cin_decode_huffman(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) |
||
116 | { |
||
117 | int b, huff_code = 0; |
||
118 | unsigned char huff_code_table[15]; |
||
119 | unsigned char *dst_cur = dst; |
||
120 | unsigned char *dst_end = dst + dst_size; |
||
121 | const unsigned char *src_end = src + src_size; |
||
122 | |||
123 | memcpy(huff_code_table, src, 15); src += 15; src_size -= 15; |
||
124 | |||
125 | while (src < src_end) {
|
||
126 | huff_code = *src++; |
||
127 | if ((huff_code >> 4) == 15) { |
||
128 | b = huff_code << 4;
|
||
129 | huff_code = *src++; |
||
130 | *dst_cur++ = b | (huff_code >> 4);
|
||
131 | } else
|
||
132 | *dst_cur++ = huff_code_table[huff_code >> 4];
|
||
133 | if (dst_cur >= dst_end)
|
||
134 | break;
|
||
135 | |||
136 | huff_code &= 15;
|
||
137 | if (huff_code == 15) { |
||
138 | *dst_cur++ = *src++; |
||
139 | } else
|
||
140 | *dst_cur++ = huff_code_table[huff_code]; |
||
141 | if (dst_cur >= dst_end)
|
||
142 | break;
|
||
143 | } |
||
144 | |||
145 | return dst_cur - dst;
|
||
146 | } |
||
147 | |||
148 | static void cin_decode_lzss(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) |
||
149 | { |
||
150 | uint16_t cmd; |
||
151 | int i, sz, offset, code;
|
||
152 | unsigned char *dst_end = dst + dst_size; |
||
153 | const unsigned char *src_end = src + src_size; |
||
154 | |||
155 | while (src < src_end && dst < dst_end) {
|
||
156 | code = *src++; |
||
157 | for (i = 0; i < 8 && src < src_end && dst < dst_end; ++i) { |
||
158 | if (code & (1 << i)) { |
||
159 | *dst++ = *src++; |
||
160 | } else {
|
||
161 | fead30d4 | Alex Beregszaszi | cmd = AV_RL16(src); src += 2;
|
162 | 72450e50 | Baptiste Coudurier | offset = cmd >> 4;
|
163 | sz = (cmd & 0xF) + 2; |
||
164 | /* don't use memcpy/memmove here as the decoding routine (ab)uses */
|
||
165 | /* buffer overlappings to repeat bytes in the destination */
|
||
166 | sz = FFMIN(sz, dst_end - dst); |
||
167 | while (sz--) {
|
||
168 | *dst = *(dst - offset - 1);
|
||
169 | ++dst; |
||
170 | } |
||
171 | } |
||
172 | } |
||
173 | } |
||
174 | } |
||
175 | |||
176 | static void cin_decode_rle(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) |
||
177 | { |
||
178 | int len, code;
|
||
179 | unsigned char *dst_end = dst + dst_size; |
||
180 | const unsigned char *src_end = src + src_size; |
||
181 | |||
182 | while (src < src_end && dst < dst_end) {
|
||
183 | code = *src++; |
||
184 | if (code & 0x80) { |
||
185 | len = code - 0x7F;
|
||
186 | memset(dst, *src++, FFMIN(len, dst_end - dst)); |
||
187 | } else {
|
||
188 | len = code + 1;
|
||
189 | memcpy(dst, src, FFMIN(len, dst_end - dst)); |
||
190 | src += len; |
||
191 | } |
||
192 | dst += len; |
||
193 | } |
||
194 | } |
||
195 | |||
196 | static int cinvideo_decode_frame(AVCodecContext *avctx, |
||
197 | void *data, int *data_size, |
||
198 | 7a00bbad | Thilo Borgmann | AVPacket *avpkt) |
199 | 72450e50 | Baptiste Coudurier | { |
200 | 7a00bbad | Thilo Borgmann | const uint8_t *buf = avpkt->data;
|
201 | int buf_size = avpkt->size;
|
||
202 | e4141433 | Nicholas Tung | CinVideoContext *cin = avctx->priv_data; |
203 | 72450e50 | Baptiste Coudurier | int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size;
|
204 | |||
205 | cin->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
||
206 | if (avctx->reget_buffer(avctx, &cin->frame)) {
|
||
207 | av_log(cin->avctx, AV_LOG_ERROR, "delphinecinvideo: reget_buffer() failed to allocate a frame\n");
|
||
208 | return -1; |
||
209 | } |
||
210 | |||
211 | palette_type = buf[0];
|
||
212 | 2c124cb6 | Ramiro Polla | palette_colors_count = AV_RL16(buf+1);
|
213 | 72450e50 | Baptiste Coudurier | bitmap_frame_type = buf[3];
|
214 | buf += 4;
|
||
215 | |||
216 | bitmap_frame_size = buf_size - 4;
|
||
217 | |||
218 | /* handle palette */
|
||
219 | if (palette_type == 0) { |
||
220 | for (i = 0; i < palette_colors_count; ++i) { |
||
221 | 2c124cb6 | Ramiro Polla | cin->palette[i] = bytestream_get_le24(&buf); |
222 | 72450e50 | Baptiste Coudurier | bitmap_frame_size -= 3;
|
223 | } |
||
224 | } else {
|
||
225 | for (i = 0; i < palette_colors_count; ++i) { |
||
226 | 2c124cb6 | Ramiro Polla | cin->palette[buf[0]] = AV_RL24(buf+1); |
227 | 72450e50 | Baptiste Coudurier | 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 | 1345f4ed | Diego Biurrun | FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]); |
282 | 72450e50 | Baptiste Coudurier | |
283 | *data_size = sizeof(AVFrame);
|
||
284 | *(AVFrame *)data = cin->frame; |
||
285 | |||
286 | return buf_size;
|
||
287 | } |
||
288 | |||
289 | 98a6fff9 | Zuxy Meng | static av_cold int cinvideo_decode_end(AVCodecContext *avctx) |
290 | 72450e50 | Baptiste Coudurier | { |
291 | e4141433 | Nicholas Tung | CinVideoContext *cin = avctx->priv_data; |
292 | 72450e50 | Baptiste Coudurier | 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 | 98a6fff9 | Zuxy Meng | static av_cold int cinaudio_decode_init(AVCodecContext *avctx) |
304 | 72450e50 | Baptiste Coudurier | { |
305 | e4141433 | Nicholas Tung | CinAudioContext *cin = avctx->priv_data; |
306 | 72450e50 | Baptiste Coudurier | |
307 | cin->avctx = avctx; |
||
308 | cin->initial_decode_frame = 1;
|
||
309 | cin->delta = 0;
|
||
310 | fd76c37f | Peter Ross | avctx->sample_fmt = SAMPLE_FMT_S16; |
311 | 72450e50 | Baptiste Coudurier | |
312 | return 0; |
||
313 | } |
||
314 | |||
315 | static int cinaudio_decode_frame(AVCodecContext *avctx, |
||
316 | void *data, int *data_size, |
||
317 | 7a00bbad | Thilo Borgmann | AVPacket *avpkt) |
318 | 72450e50 | Baptiste Coudurier | { |
319 | 7a00bbad | Thilo Borgmann | const uint8_t *buf = avpkt->data;
|
320 | int buf_size = avpkt->size;
|
||
321 | e4141433 | Nicholas Tung | CinAudioContext *cin = avctx->priv_data; |
322 | 7993df65 | Michael Niedermayer | const uint8_t *src = buf;
|
323 | 72450e50 | Baptiste Coudurier | int16_t *samples = (int16_t *)data; |
324 | |||
325 | 675a0583 | Kostya Shishkov | buf_size = FFMIN(buf_size, *data_size/2);
|
326 | |||
327 | 72450e50 | Baptiste Coudurier | if (cin->initial_decode_frame) {
|
328 | cin->initial_decode_frame = 0;
|
||
329 | fead30d4 | Alex Beregszaszi | cin->delta = (int16_t)AV_RL16(src); src += 2;
|
330 | 72450e50 | Baptiste Coudurier | *samples++ = cin->delta; |
331 | buf_size -= 2;
|
||
332 | } |
||
333 | while (buf_size > 0) { |
||
334 | cin->delta += cinaudio_delta16_table[*src++]; |
||
335 | aee481ce | Aurelien Jacobs | cin->delta = av_clip_int16(cin->delta); |
336 | 72450e50 | Baptiste Coudurier | *samples++ = cin->delta; |
337 | --buf_size; |
||
338 | } |
||
339 | |||
340 | *data_size = (uint8_t *)samples - (uint8_t *)data; |
||
341 | |||
342 | return src - buf;
|
||
343 | } |
||
344 | |||
345 | |||
346 | AVCodec dsicinvideo_decoder = { |
||
347 | "dsicinvideo",
|
||
348 | 72415b2a | Stefano Sabatini | AVMEDIA_TYPE_VIDEO, |
349 | 72450e50 | Baptiste Coudurier | CODEC_ID_DSICINVIDEO, |
350 | sizeof(CinVideoContext),
|
||
351 | cinvideo_decode_init, |
||
352 | NULL,
|
||
353 | cinvideo_decode_end, |
||
354 | cinvideo_decode_frame, |
||
355 | CODEC_CAP_DR1, |
||
356 | fe4bf374 | Stefano Sabatini | .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"),
|
357 | 72450e50 | Baptiste Coudurier | }; |
358 | |||
359 | AVCodec dsicinaudio_decoder = { |
||
360 | "dsicinaudio",
|
||
361 | 72415b2a | Stefano Sabatini | AVMEDIA_TYPE_AUDIO, |
362 | 72450e50 | Baptiste Coudurier | CODEC_ID_DSICINAUDIO, |
363 | sizeof(CinAudioContext),
|
||
364 | cinaudio_decode_init, |
||
365 | NULL,
|
||
366 | NULL,
|
||
367 | cinaudio_decode_frame, |
||
368 | fe4bf374 | Stefano Sabatini | .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"),
|
369 | 72450e50 | Baptiste Coudurier | }; |