Mercurial > libavcodec.hg
annotate mimic.c @ 12266:48d6738904a9 libavcodec
Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
splits it into small optimization-specific macros which are selected for each
DSP function. The advantage of this approach is that the sse4 functions now
use the ssse3 codepath also without needing an explicit sse4 codepath.
author | rbultje |
---|---|
date | Sat, 24 Jul 2010 19:33:05 +0000 |
parents | 8a4984c5cacc |
children |
rev | line source |
---|---|
6508 | 1 /* |
2 * Copyright (C) 2005 Ole André Vadla Ravnås <oleavr@gmail.com> | |
3 * Copyright (C) 2008 Ramiro Polla <ramiro@lisha.ufsc.br> | |
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 #include <stdlib.h> | |
23 #include <string.h> | |
24 #include <stdint.h> | |
25 | |
26 #include "avcodec.h" | |
9428 | 27 #include "get_bits.h" |
6666 | 28 #include "bytestream.h" |
6508 | 29 #include "dsputil.h" |
30 | |
31 #define MIMIC_HEADER_SIZE 20 | |
32 | |
33 typedef struct { | |
34 AVCodecContext *avctx; | |
35 | |
36 int num_vblocks[3]; | |
37 int num_hblocks[3]; | |
38 | |
9414
5a738e8f9524
Use void * instead of uint8_t * for the destination buffer for dsp.bswap_buf
reimar
parents:
9413
diff
changeset
|
39 void *swap_buf; |
6508 | 40 int swap_buf_size; |
41 | |
42 int cur_index; | |
43 int prev_index; | |
44 | |
45 AVFrame buf_ptrs [16]; | |
46 AVPicture flipped_ptrs[16]; | |
47 | |
11369 | 48 DECLARE_ALIGNED(16, DCTELEM, dct_block)[64]; |
6508 | 49 |
50 GetBitContext gb; | |
51 ScanTable scantable; | |
52 DSPContext dsp; | |
6652 | 53 VLC vlc; |
6508 | 54 } MimicContext; |
55 | |
56 static const uint32_t huffcodes[] = { | |
57 0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
58 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
59 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000b, | |
60 0x0000001b, 0x00000038, 0x00000078, 0x00000079, 0x0000007a, 0x000000f9, | |
61 0x000000fa, 0x000003fb, 0x000007f8, 0x000007f9, 0x000007fa, 0x000007fb, | |
62 0x00000ff8, 0x00000ff9, 0x00000001, 0x00000039, 0x0000007b, 0x000000fb, | |
63 0x000001f8, 0x000001f9, 0x00000ffa, 0x00000ffb, 0x00001ff8, 0x00001ff9, | |
64 0x00001ffa, 0x00001ffb, 0x00003ff8, 0x00003ff9, 0x00003ffa, 0x00000000, | |
65 0x00000004, 0x0000003a, 0x000001fa, 0x00003ffb, 0x00007ff8, 0x00007ff9, | |
66 0x00007ffa, 0x00007ffb, 0x0000fff8, 0x0000fff9, 0x0000fffa, 0x0000fffb, | |
67 0x0001fff8, 0x0001fff9, 0x0001fffa, 0x00000000, 0x0000000c, 0x000000f8, | |
68 0x000001fb, 0x0001fffb, 0x0003fff8, 0x0003fff9, 0x0003fffa, 0x0003fffb, | |
69 0x0007fff8, 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9, | |
70 0x000ffffa, 0x00000000, 0x0000001a, 0x000003f8, 0x000ffffb, 0x001ffff8, | |
71 0x001ffff9, 0x001ffffa, 0x001ffffb, 0x003ffff8, 0x003ffff9, 0x003ffffa, | |
72 0x003ffffb, 0x007ffff8, 0x007ffff9, 0x007ffffa, 0x007ffffb, 0x00000000, | |
73 0x0000003b, 0x000003f9, 0x00fffff8, 0x00fffff9, 0x00fffffa, 0x00fffffb, | |
74 0x01fffff8, 0x01fffff9, 0x01fffffa, 0x01fffffb, 0x03fffff8, 0x03fffff9, | |
75 0x03fffffa, 0x03fffffb, 0x07fffff8, 0x00000000, 0x000003fa, 0x07fffff9, | |
76 0x07fffffa, 0x07fffffb, 0x0ffffff8, 0x0ffffff9, 0x0ffffffa, 0x0ffffffb, | |
77 0x1ffffff8, 0x1ffffff9, 0x1ffffffa, 0x1ffffffb, 0x3ffffff8, 0x3ffffff9, | |
78 0x3ffffffa, | |
79 }; | |
80 | |
81 static const uint8_t huffbits[] = { | |
82 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
83 0, 0, 0, 0, 2, 4, 5, 6, 7, 7, 7, 8, | |
84 8, 10, 11, 11, 11, 11, 12, 12, 2, 6, 7, 8, | |
85 9, 9, 12, 12, 13, 13, 13, 13, 14, 14, 14, 0, | |
86 3, 6, 9, 14, 15, 15, 15, 15, 16, 16, 16, 16, | |
87 17, 17, 17, 0, 4, 8, 9, 17, 18, 18, 18, 18, | |
88 19, 19, 19, 19, 20, 20, 20, 0, 5, 10, 20, 21, | |
89 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 0, | |
90 6, 10, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, | |
91 26, 26, 27, 0, 10, 27, 27, 27, 28, 28, 28, 28, | |
92 29, 29, 29, 29, 30, 30, 30, | |
93 }; | |
94 | |
95 static const uint8_t col_zag[64] = { | |
96 0, 8, 1, 2, 9, 16, 24, 17, | |
97 10, 3, 4, 11, 18, 25, 32, 40, | |
98 33, 26, 19, 12, 5, 6, 13, 20, | |
99 27, 34, 41, 48, 56, 49, 42, 35, | |
100 28, 21, 14, 7, 15, 22, 29, 36, | |
101 43, 50, 57, 58, 51, 44, 37, 30, | |
102 23, 31, 38, 45, 52, 59, 39, 46, | |
6653 | 103 53, 60, 61, 54, 47, 55, 62, 63, |
6508 | 104 }; |
105 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6508
diff
changeset
|
106 static av_cold int mimic_decode_init(AVCodecContext *avctx) |
6508 | 107 { |
108 MimicContext *ctx = avctx->priv_data; | |
109 | |
110 ctx->prev_index = 0; | |
111 ctx->cur_index = 15; | |
112 | |
8042 | 113 if(init_vlc(&ctx->vlc, 11, FF_ARRAY_ELEMS(huffbits), |
6508 | 114 huffbits, 1, 1, huffcodes, 4, 4, 0)) { |
115 av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n"); | |
116 return -1; | |
117 } | |
118 dsputil_init(&ctx->dsp, avctx); | |
119 ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, col_zag); | |
120 | |
121 return 0; | |
122 } | |
123 | |
8954
409d20e15da8
cosmetics: 'const static' --> 'static const' to avoid warnings of the type
diego
parents:
8288
diff
changeset
|
124 static const int8_t vlcdec_lookup[9][64] = { |
6508 | 125 { 0, }, |
126 { -1, 1, }, | |
127 { -3, 3, -2, 2, }, | |
128 { -7, 7, -6, 6, -5, 5, -4, 4, }, | |
129 { -15, 15, -14, 14, -13, 13, -12, 12, | |
130 -11, 11, -10, 10, -9, 9, -8, 8, }, | |
131 { -31, 31, -30, 30, -29, 29, -28, 28, | |
132 -27, 27, -26, 26, -25, 25, -24, 24, | |
133 -23, 23, -22, 22, -21, 21, -20, 20, | |
134 -19, 19, -18, 18, -17, 17, -16, 16, }, | |
135 { -63, 63, -62, 62, -61, 61, -60, 60, | |
136 -59, 59, -58, 58, -57, 57, -56, 56, | |
137 -55, 55, -54, 54, -53, 53, -52, 52, | |
138 -51, 51, -50, 50, -49, 49, -48, 48, | |
139 -47, 47, -46, 46, -45, 45, -44, 44, | |
140 -43, 43, -42, 42, -41, 41, -40, 40, | |
141 -39, 39, -38, 38, -37, 37, -36, 36, | |
142 -35, 35, -34, 34, -33, 33, -32, 32, }, | |
143 { -127, 127, -126, 126, -125, 125, -124, 124, | |
144 -123, 123, -122, 122, -121, 121, -120, 120, | |
145 -119, 119, -118, 118, -117, 117, -116, 116, | |
146 -115, 115, -114, 114, -113, 113, -112, 112, | |
147 -111, 111, -110, 110, -109, 109, -108, 108, | |
148 -107, 107, -106, 106, -105, 105, -104, 104, | |
149 -103, 103, -102, 102, -101, 101, -100, 100, | |
150 -99, 99, -98, 98, -97, 97, -96, 96, }, | |
151 { -95, 95, -94, 94, -93, 93, -92, 92, | |
152 -91, 91, -90, 90, -89, 89, -88, 88, | |
153 -87, 87, -86, 86, -85, 85, -84, 84, | |
154 -83, 83, -82, 82, -81, 81, -80, 80, | |
155 -79, 79, -78, 78, -77, 77, -76, 76, | |
156 -75, 75, -74, 74, -73, 73, -72, 72, | |
157 -71, 71, -70, 70, -69, 69, -68, 68, | |
158 -67, 67, -66, 66, -65, 65, -64, 64, }, | |
159 }; | |
160 | |
6654 | 161 static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale) |
6508 | 162 { |
6654 | 163 DCTELEM *block = ctx->dct_block; |
6508 | 164 unsigned int pos; |
165 | |
8288 | 166 ctx->dsp.clear_block(block); |
6508 | 167 |
168 block[0] = get_bits(&ctx->gb, 8) << 3; | |
169 | |
170 for(pos = 1; pos < num_coeffs; pos++) { | |
171 uint32_t vlc, num_bits; | |
172 int value; | |
173 int coeff; | |
174 | |
6684
0b8ef15fa20e
get_vlc2() only gets up to three levels in the tables. The last codes weren't being read properly.
ramiro
parents:
6668
diff
changeset
|
175 vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3); |
6508 | 176 if(!vlc) /* end-of-block code */ |
177 return 1; | |
178 if(vlc == -1) | |
179 return 0; | |
180 | |
181 /* pos_add and num_bits are coded in the vlc code */ | |
182 pos += vlc&15; // pos_add | |
183 num_bits = vlc>>4; // num_bits | |
184 | |
185 if(pos >= 64) | |
186 return 0; | |
187 | |
188 value = get_bits(&ctx->gb, num_bits); | |
189 | |
190 /* FFmpeg's IDCT behaves somewhat different from the original code, so | |
191 * a factor of 4 was added to the input */ | |
192 | |
193 coeff = vlcdec_lookup[num_bits][value]; | |
194 if(pos<3) | |
195 coeff <<= 4; | |
196 else /* TODO Use >> 10 instead of / 1001 */ | |
197 coeff = (coeff * qscale) / 1001; | |
198 | |
199 block[ctx->scantable.permutated[pos]] = coeff; | |
200 } | |
201 | |
202 return 1; | |
203 } | |
204 | |
205 static int decode(MimicContext *ctx, int quality, int num_coeffs, | |
206 int is_iframe) | |
207 { | |
208 int y, x, plane; | |
209 | |
210 for(plane = 0; plane < 3; plane++) { | |
211 const int is_chroma = !!plane; | |
212 const int qscale = av_clip(10000-quality,is_chroma?1000:2000,10000)<<2; | |
213 const int stride = ctx->flipped_ptrs[ctx->cur_index].linesize[plane]; | |
214 const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane]; | |
215 uint8_t *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane]; | |
216 | |
6653 | 217 for(y = 0; y < ctx->num_vblocks[plane]; y++) { |
6508 | 218 for(x = 0; x < ctx->num_hblocks[plane]; x++) { |
219 | |
220 /* Check for a change condition in the current block. | |
221 * - iframes always change. | |
222 * - Luma plane changes on get_bits1 == 0 | |
223 * - Chroma planes change on get_bits1 == 1 */ | |
224 if(is_iframe || get_bits1(&ctx->gb) == is_chroma) { | |
225 | |
226 /* Luma planes may use a backreference from the 15 last | |
227 * frames preceding the previous. (get_bits1 == 1) | |
228 * Chroma planes don't use backreferences. */ | |
229 if(is_chroma || is_iframe || !get_bits1(&ctx->gb)) { | |
230 | |
6654 | 231 if(!vlc_decode_block(ctx, num_coeffs, qscale)) |
6508 | 232 return 0; |
233 ctx->dsp.idct_put(dst, stride, ctx->dct_block); | |
234 } else { | |
235 unsigned int backref = get_bits(&ctx->gb, 4); | |
236 int index = (ctx->cur_index+backref)&15; | |
237 uint8_t *p = ctx->flipped_ptrs[index].data[0]; | |
238 | |
239 if(p) { | |
240 p += src - | |
241 ctx->flipped_ptrs[ctx->prev_index].data[plane]; | |
242 ctx->dsp.put_pixels_tab[1][0](dst, p, stride, 8); | |
243 } else { | |
244 av_log(ctx->avctx, AV_LOG_ERROR, | |
245 "No such backreference! Buggy sample.\n"); | |
246 } | |
247 } | |
248 } else { | |
249 ctx->dsp.put_pixels_tab[1][0](dst, src, stride, 8); | |
250 } | |
251 src += 8; | |
252 dst += 8; | |
253 } | |
254 src += (stride - ctx->num_hblocks[plane])<<3; | |
255 dst += (stride - ctx->num_hblocks[plane])<<3; | |
256 } | |
257 } | |
258 | |
259 return 1; | |
260 } | |
261 | |
262 /** | |
263 * Flip the buffer upside-down and put it in the YVU order to match the | |
264 * way Mimic encodes frames. | |
265 */ | |
266 static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVPicture *src) | |
267 { | |
268 int i; | |
269 dst->data[0] = src->data[0]+( ctx->avctx->height -1)*src->linesize[0]; | |
270 dst->data[1] = src->data[2]+((ctx->avctx->height>>1)-1)*src->linesize[2]; | |
271 dst->data[2] = src->data[1]+((ctx->avctx->height>>1)-1)*src->linesize[1]; | |
6653 | 272 for(i = 0; i < 3; i++) |
6508 | 273 dst->linesize[i] = -src->linesize[i]; |
274 } | |
275 | |
276 static int mimic_decode_frame(AVCodecContext *avctx, void *data, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8954
diff
changeset
|
277 int *data_size, AVPacket *avpkt) |
6508 | 278 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8954
diff
changeset
|
279 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8954
diff
changeset
|
280 int buf_size = avpkt->size; |
6508 | 281 MimicContext *ctx = avctx->priv_data; |
282 int is_pframe; | |
283 int width, height; | |
284 int quality, num_coeffs; | |
285 int swap_buf_size = buf_size - MIMIC_HEADER_SIZE; | |
286 | |
287 if(buf_size < MIMIC_HEADER_SIZE) { | |
288 av_log(avctx, AV_LOG_ERROR, "insufficient data\n"); | |
289 return -1; | |
290 } | |
291 | |
6667
4a5c7112e35c
The code now is pretty self explanatory about the header structure.
ramiro
parents:
6666
diff
changeset
|
292 buf += 2; /* some constant (always 256) */ |
6666 | 293 quality = bytestream_get_le16(&buf); |
294 width = bytestream_get_le16(&buf); | |
295 height = bytestream_get_le16(&buf); | |
6667
4a5c7112e35c
The code now is pretty self explanatory about the header structure.
ramiro
parents:
6666
diff
changeset
|
296 buf += 4; /* some constant */ |
6666 | 297 is_pframe = bytestream_get_le32(&buf); |
6668 | 298 num_coeffs = bytestream_get_byte(&buf); |
299 buf += 3; /* some constant */ | |
6508 | 300 |
301 if(!ctx->avctx) { | |
302 int i; | |
303 | |
304 if(!(width == 160 && height == 120) && | |
305 !(width == 320 && height == 240)) { | |
306 av_log(avctx, AV_LOG_ERROR, "invalid width/height!\n"); | |
307 return -1; | |
308 } | |
309 | |
310 ctx->avctx = avctx; | |
311 avctx->width = width; | |
312 avctx->height = height; | |
313 avctx->pix_fmt = PIX_FMT_YUV420P; | |
6653 | 314 for(i = 0; i < 3; i++) { |
6508 | 315 ctx->num_vblocks[i] = -((-height) >> (3 + !!i)); |
316 ctx->num_hblocks[i] = width >> (3 + !!i) ; | |
317 } | |
318 } else if(width != ctx->avctx->width || height != ctx->avctx->height) { | |
319 av_log(avctx, AV_LOG_ERROR, "resolution changing is not supported\n"); | |
320 return -1; | |
321 } | |
322 | |
323 if(is_pframe && !ctx->buf_ptrs[ctx->prev_index].data[0]) { | |
324 av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n"); | |
325 return -1; | |
326 } | |
327 | |
328 ctx->buf_ptrs[ctx->cur_index].reference = 1; | |
329 if(avctx->get_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index])) { | |
330 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
331 return -1; | |
332 } | |
333 | |
334 prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index], | |
335 (AVPicture*) &ctx->buf_ptrs[ctx->cur_index]); | |
336 | |
9415
141badec76fc
Add a av_fast_malloc function and replace several uses of av_fast_realloc,
reimar
parents:
9414
diff
changeset
|
337 av_fast_malloc(&ctx->swap_buf, &ctx->swap_buf_size, |
6508 | 338 swap_buf_size + FF_INPUT_BUFFER_PADDING_SIZE); |
339 if(!ctx->swap_buf) | |
9413
1eafaea58613
Use AVERROR(ENOMEM) instead of AVERROR_NOMEM / -1 in eatqi and mimic decoders
reimar
parents:
9355
diff
changeset
|
340 return AVERROR(ENOMEM); |
6508 | 341 |
9414
5a738e8f9524
Use void * instead of uint8_t * for the destination buffer for dsp.bswap_buf
reimar
parents:
9413
diff
changeset
|
342 ctx->dsp.bswap_buf(ctx->swap_buf, |
6666 | 343 (const uint32_t*) buf, |
6508 | 344 swap_buf_size>>2); |
345 init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3); | |
346 | |
347 if(!decode(ctx, quality, num_coeffs, !is_pframe)) { | |
348 avctx->release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]); | |
349 return -1; | |
350 } | |
351 | |
352 ctx->buf_ptrs[ctx->cur_index].pict_type = is_pframe ? FF_P_TYPE:FF_I_TYPE; | |
353 *(AVFrame*)data = ctx->buf_ptrs[ctx->cur_index]; | |
354 *data_size = sizeof(AVFrame); | |
355 | |
356 ctx->prev_index = ctx->cur_index; | |
357 ctx->cur_index--; | |
358 ctx->cur_index &= 15; | |
359 | |
360 /* Only release frames that aren't used for backreferences anymore */ | |
361 if(ctx->buf_ptrs[ctx->cur_index].data[0]) | |
362 avctx->release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]); | |
363 | |
364 return buf_size; | |
365 } | |
366 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6508
diff
changeset
|
367 static av_cold int mimic_decode_end(AVCodecContext *avctx) |
6508 | 368 { |
369 MimicContext *ctx = avctx->priv_data; | |
370 int i; | |
371 | |
372 av_free(ctx->swap_buf); | |
373 for(i = 0; i < 16; i++) | |
374 if(ctx->buf_ptrs[i].data[0]) | |
375 avctx->release_buffer(avctx, &ctx->buf_ptrs[i]); | |
6652 | 376 free_vlc(&ctx->vlc); |
6508 | 377 |
378 return 0; | |
379 } | |
380 | |
381 AVCodec mimic_decoder = { | |
382 "mimic", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11369
diff
changeset
|
383 AVMEDIA_TYPE_VIDEO, |
6508 | 384 CODEC_ID_MIMIC, |
385 sizeof(MimicContext), | |
386 mimic_decode_init, | |
387 NULL, | |
388 mimic_decode_end, | |
389 mimic_decode_frame, | |
390 CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6710
diff
changeset
|
391 .long_name = NULL_IF_CONFIG_SMALL("Mimic"), |
6508 | 392 }; |