Mercurial > libavcodec.hg
annotate bink.c @ 11352:6e0af2cfdcfe libavcodec
Do MC and IDCT in coding (hilbert) order
This increases the slice size to 64 pixels, due to having to decode an
entire chroma superblock row per slice.
This can be up to 6% slower depending on clip and CPU, but is necessary
for future optimizations that gain significantly more than was lost.
author | conrad |
---|---|
date | Wed, 03 Mar 2010 23:27:40 +0000 |
parents | e820a9d3f80c |
children | 98970e51365a |
rev | line source |
---|---|
11231 | 1 /* |
2 * Bink video decoder | |
3 * Copyright (c) 2009 Konstantin Shishkov | |
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 "avcodec.h" | |
23 #include "dsputil.h" | |
24 #include "binkdata.h" | |
25 #include "mathops.h" | |
26 | |
27 #define ALT_BITSTREAM_READER_LE | |
28 #include "get_bits.h" | |
29 | |
11251
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
30 #define BINK_FLAG_ALPHA 0x00100000 |
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
31 #define BINK_FLAG_GRAY 0x00020000 |
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
32 |
11231 | 33 static VLC bink_trees[16]; |
34 | |
35 /** | |
36 * IDs for different data types used in Bink video codec | |
37 */ | |
38 enum Sources { | |
39 BINK_SRC_BLOCK_TYPES = 0, ///< 8x8 block types | |
40 BINK_SRC_SUB_BLOCK_TYPES, ///< 16x16 block types (a subset of 8x8 block types) | |
41 BINK_SRC_COLORS, ///< pixel values used for different block types | |
42 BINK_SRC_PATTERN, ///< 8-bit values for 2-colour pattern fill | |
43 BINK_SRC_X_OFF, ///< X components of motion value | |
44 BINK_SRC_Y_OFF, ///< Y components of motion value | |
45 BINK_SRC_INTRA_DC, ///< DC values for intrablocks with DCT | |
46 BINK_SRC_INTER_DC, ///< DC values for intrablocks with DCT | |
47 BINK_SRC_RUN, ///< run lengths for special fill block | |
48 | |
49 BINK_NB_SRC | |
50 }; | |
51 | |
52 /** | |
53 * data needed to decode 4-bit Huffman-coded value | |
54 */ | |
55 typedef struct Tree { | |
56 int vlc_num; ///< tree number (in bink_trees[]) | |
57 uint8_t syms[16]; ///< leaf value to symbol mapping | |
58 } Tree; | |
59 | |
60 #define GET_HUFF(gb, tree) (tree).syms[get_vlc2(gb, bink_trees[(tree).vlc_num].table,\ | |
61 bink_trees[(tree).vlc_num].bits, 1)] | |
62 | |
63 /** | |
64 * data structure used for decoding single Bink data type | |
65 */ | |
66 typedef struct Bundle { | |
67 int len; ///< length of number of entries to decode (in bits) | |
68 Tree tree; ///< Huffman tree-related data | |
69 uint8_t *data; ///< buffer for decoded symbols | |
70 uint8_t *data_end; ///< buffer end | |
71 uint8_t *cur_dec; ///< pointer to the not yet decoded part of the buffer | |
72 uint8_t *cur_ptr; ///< pointer to the data that is not read from buffer yet | |
73 } Bundle; | |
74 | |
75 /* | |
76 * Decoder context | |
77 */ | |
78 typedef struct BinkContext { | |
79 AVCodecContext *avctx; | |
80 DSPContext dsp; | |
81 AVFrame pic, last; | |
82 int version; ///< internal Bink file version | |
11247 | 83 int has_alpha; |
11231 | 84 int swap_planes; |
85 ScanTable scantable; ///< permutated scantable for DCT coeffs decoding | |
86 | |
87 Bundle bundle[BINK_NB_SRC]; ///< bundles for decoding all data types | |
88 Tree col_high[16]; ///< trees for decoding high nibble in "colours" data type | |
89 int col_lastval; ///< value of last decoded high nibble in "colours" data type | |
90 } BinkContext; | |
91 | |
92 /** | |
93 * Bink video block types | |
94 */ | |
95 enum BlockTypes { | |
96 SKIP_BLOCK = 0, ///< skipped block | |
97 SCALED_BLOCK, ///< block has size 16x16 | |
98 MOTION_BLOCK, ///< block is copied from previous frame with some offset | |
99 RUN_BLOCK, ///< block is composed from runs of colours with custom scan order | |
100 RESIDUE_BLOCK, ///< motion block with some difference added | |
101 INTRA_BLOCK, ///< intra DCT block | |
102 FILL_BLOCK, ///< block is filled with single colour | |
103 INTER_BLOCK, ///< motion block with DCT applied to the difference | |
104 PATTERN_BLOCK, ///< block is filled with two colours following custom pattern | |
105 RAW_BLOCK, ///< uncoded 8x8 block | |
106 }; | |
107 | |
108 /** | |
109 * Initializes length length in all bundles. | |
110 * | |
111 * @param c decoder context | |
112 * @param width plane width | |
113 * @param bw plane width in 8x8 blocks | |
114 */ | |
115 static void init_lengths(BinkContext *c, int width, int bw) | |
116 { | |
117 c->bundle[BINK_SRC_BLOCK_TYPES].len = av_log2((width >> 3) + 511) + 1; | |
118 | |
119 c->bundle[BINK_SRC_SUB_BLOCK_TYPES].len = av_log2((width >> 4) + 511) + 1; | |
120 | |
121 c->bundle[BINK_SRC_COLORS].len = av_log2((width >> 3)*64 + 511) + 1; | |
122 | |
123 c->bundle[BINK_SRC_INTRA_DC].len = | |
124 c->bundle[BINK_SRC_INTER_DC].len = | |
125 c->bundle[BINK_SRC_X_OFF].len = | |
126 c->bundle[BINK_SRC_Y_OFF].len = av_log2((width >> 3) + 511) + 1; | |
127 | |
128 c->bundle[BINK_SRC_PATTERN].len = av_log2((bw << 3) + 511) + 1; | |
129 | |
130 c->bundle[BINK_SRC_RUN].len = av_log2((width >> 3)*48 + 511) + 1; | |
131 } | |
132 | |
133 /** | |
134 * Allocates memory for bundles. | |
135 * | |
136 * @param c decoder context | |
137 */ | |
138 static av_cold void init_bundles(BinkContext *c) | |
139 { | |
140 int bw, bh, blocks; | |
141 int i; | |
142 | |
143 bw = (c->avctx->width + 7) >> 3; | |
144 bh = (c->avctx->height + 7) >> 3; | |
145 blocks = bw * bh; | |
146 | |
147 for (i = 0; i < BINK_NB_SRC; i++) { | |
148 c->bundle[i].data = av_malloc(blocks * 64); | |
149 c->bundle[i].data_end = c->bundle[i].data + blocks * 64; | |
150 } | |
151 } | |
152 | |
153 /** | |
154 * Frees memory used by bundles. | |
155 * | |
156 * @param c decoder context | |
157 */ | |
158 static av_cold void free_bundles(BinkContext *c) | |
159 { | |
160 int i; | |
161 for (i = 0; i < BINK_NB_SRC; i++) | |
162 av_freep(&c->bundle[i].data); | |
163 } | |
164 | |
165 /** | |
166 * Merges two consequent lists of equal size depending on bits read. | |
167 * | |
168 * @param gb context for reading bits | |
169 * @param dst buffer where merged list will be written to | |
170 * @param src pointer to the head of the first list (the second lists starts at src+size) | |
171 * @param size input lists size | |
172 */ | |
173 static void merge(GetBitContext *gb, uint8_t *dst, uint8_t *src, int size) | |
174 { | |
175 uint8_t *src2 = src + size; | |
176 int size2 = size; | |
177 | |
178 do { | |
179 if (!get_bits1(gb)) { | |
180 *dst++ = *src++; | |
181 size--; | |
182 } else { | |
183 *dst++ = *src2++; | |
184 size2--; | |
185 } | |
186 } while (size && size2); | |
187 | |
188 while (size--) | |
189 *dst++ = *src++; | |
190 while (size2--) | |
191 *dst++ = *src2++; | |
192 } | |
193 | |
194 /** | |
195 * Reads information about Huffman tree used to decode data. | |
196 * | |
197 * @param gb context for reading bits | |
198 * @param tree pointer for storing tree data | |
199 */ | |
200 static void read_tree(GetBitContext *gb, Tree *tree) | |
201 { | |
202 uint8_t tmp1[16], tmp2[16], *in = tmp1, *out = tmp2; | |
203 int i, t, len; | |
204 | |
205 tree->vlc_num = get_bits(gb, 4); | |
206 if (!tree->vlc_num) { | |
207 for (i = 0; i < 16; i++) | |
208 tree->syms[i] = i; | |
209 return; | |
210 } | |
211 if (get_bits1(gb)) { | |
212 len = get_bits(gb, 3); | |
213 memset(tmp1, 0, sizeof(tmp1)); | |
214 for (i = 0; i <= len; i++) { | |
215 tree->syms[i] = get_bits(gb, 4); | |
216 tmp1[tree->syms[i]] = 1; | |
217 } | |
218 for (i = 0; i < 16; i++) | |
219 if (!tmp1[i]) | |
220 tree->syms[++len] = i; | |
221 } else { | |
222 len = get_bits(gb, 2); | |
223 for (i = 0; i < 16; i++) | |
224 in[i] = i; | |
225 for (i = 0; i <= len; i++) { | |
226 int size = 1 << i; | |
227 for (t = 0; t < 16; t += size << 1) | |
228 merge(gb, out + t, in + t, size); | |
229 FFSWAP(uint8_t*, in, out); | |
230 } | |
231 memcpy(tree->syms, in, 16); | |
232 } | |
233 } | |
234 | |
235 /** | |
236 * Prepares bundle for decoding data. | |
237 * | |
238 * @param gb context for reading bits | |
239 * @param c decoder context | |
240 * @param bundle_num number of the bundle to initialize | |
241 */ | |
242 static void read_bundle(GetBitContext *gb, BinkContext *c, int bundle_num) | |
243 { | |
244 int i; | |
245 | |
246 if (bundle_num == BINK_SRC_COLORS) { | |
247 for (i = 0; i < 16; i++) | |
248 read_tree(gb, &c->col_high[i]); | |
249 c->col_lastval = 0; | |
250 } | |
251 if (bundle_num != BINK_SRC_INTRA_DC && bundle_num != BINK_SRC_INTER_DC) | |
252 read_tree(gb, &c->bundle[bundle_num].tree); | |
253 c->bundle[bundle_num].cur_dec = | |
254 c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data; | |
255 } | |
256 | |
257 /** | |
258 * common check before starting decoding bundle data | |
259 * | |
260 * @param gb context for reading bits | |
261 * @param b bundle | |
262 * @param t variable where number of elements to decode will be stored | |
263 */ | |
264 #define CHECK_READ_VAL(gb, b, t) \ | |
265 if (!b->cur_dec || (b->cur_dec > b->cur_ptr)) \ | |
266 return 0; \ | |
267 t = get_bits(gb, b->len); \ | |
268 if (!t) { \ | |
269 b->cur_dec = NULL; \ | |
270 return 0; \ | |
271 } \ | |
272 | |
273 static int read_runs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) | |
274 { | |
275 int t, v; | |
276 const uint8_t *dec_end; | |
277 | |
278 CHECK_READ_VAL(gb, b, t); | |
279 dec_end = b->cur_dec + t; | |
280 if (dec_end > b->data_end) { | |
281 av_log(avctx, AV_LOG_ERROR, "Run value went out of bounds\n"); | |
282 return -1; | |
283 } | |
284 if (get_bits1(gb)) { | |
285 v = get_bits(gb, 4); | |
286 memset(b->cur_dec, v, t); | |
287 b->cur_dec += t; | |
288 } else { | |
289 while (b->cur_dec < dec_end) | |
290 *b->cur_dec++ = GET_HUFF(gb, b->tree); | |
291 } | |
292 return 0; | |
293 } | |
294 | |
295 static int read_motion_values(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) | |
296 { | |
297 int t, sign, v; | |
298 const uint8_t *dec_end; | |
299 | |
300 CHECK_READ_VAL(gb, b, t); | |
301 dec_end = b->cur_dec + t; | |
302 if (dec_end > b->data_end) { | |
303 av_log(avctx, AV_LOG_ERROR, "Too many motion values\n"); | |
304 return -1; | |
305 } | |
306 if (get_bits1(gb)) { | |
307 v = get_bits(gb, 4); | |
308 if (v) { | |
309 sign = -get_bits1(gb); | |
310 v = (v ^ sign) - sign; | |
311 } | |
312 memset(b->cur_dec, v, t); | |
313 b->cur_dec += t; | |
314 } else { | |
315 do { | |
316 v = GET_HUFF(gb, b->tree); | |
317 if (v) { | |
318 sign = -get_bits1(gb); | |
319 v = (v ^ sign) - sign; | |
320 } | |
321 *b->cur_dec++ = v; | |
322 } while (b->cur_dec < dec_end); | |
323 } | |
324 return 0; | |
325 } | |
326 | |
327 const uint8_t bink_rlelens[4] = { 4, 8, 12, 32 }; | |
328 | |
329 static int read_block_types(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) | |
330 { | |
331 int t, v; | |
332 int last = 0; | |
333 const uint8_t *dec_end; | |
334 | |
335 CHECK_READ_VAL(gb, b, t); | |
336 dec_end = b->cur_dec + t; | |
337 if (dec_end > b->data_end) { | |
338 av_log(avctx, AV_LOG_ERROR, "Too many block type values\n"); | |
339 return -1; | |
340 } | |
341 if (get_bits1(gb)) { | |
342 v = get_bits(gb, 4); | |
343 memset(b->cur_dec, v, t); | |
344 b->cur_dec += t; | |
345 } else { | |
346 do { | |
347 v = GET_HUFF(gb, b->tree); | |
348 if (v < 12) { | |
349 last = v; | |
350 *b->cur_dec++ = v; | |
351 } else { | |
352 int run = bink_rlelens[v - 12]; | |
353 | |
354 memset(b->cur_dec, last, run); | |
355 b->cur_dec += run; | |
356 } | |
357 } while (b->cur_dec < dec_end); | |
358 } | |
359 return 0; | |
360 } | |
361 | |
362 static int read_patterns(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) | |
363 { | |
364 int t, v; | |
365 const uint8_t *dec_end; | |
366 | |
367 CHECK_READ_VAL(gb, b, t); | |
368 dec_end = b->cur_dec + t; | |
369 if (dec_end > b->data_end) { | |
370 av_log(avctx, AV_LOG_ERROR, "Too many pattern values\n"); | |
371 return -1; | |
372 } | |
373 while (b->cur_dec < dec_end) { | |
374 v = GET_HUFF(gb, b->tree); | |
375 v |= GET_HUFF(gb, b->tree) << 4; | |
376 *b->cur_dec++ = v; | |
377 } | |
378 | |
379 return 0; | |
380 } | |
381 | |
382 static int read_colors(GetBitContext *gb, Bundle *b, BinkContext *c) | |
383 { | |
384 int t, sign, v; | |
385 const uint8_t *dec_end; | |
386 | |
387 CHECK_READ_VAL(gb, b, t); | |
388 dec_end = b->cur_dec + t; | |
389 if (dec_end > b->data_end) { | |
390 av_log(c->avctx, AV_LOG_ERROR, "Too many color values\n"); | |
391 return -1; | |
392 } | |
393 if (get_bits1(gb)) { | |
394 c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]); | |
395 v = GET_HUFF(gb, b->tree); | |
396 v = (c->col_lastval << 4) | v; | |
397 if (c->version < 'i') { | |
398 sign = ((int8_t) v) >> 7; | |
399 v = ((v & 0x7F) ^ sign) - sign; | |
400 v += 0x80; | |
401 } | |
402 memset(b->cur_dec, v, t); | |
403 b->cur_dec += t; | |
404 } else { | |
405 while (b->cur_dec < dec_end) { | |
406 c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]); | |
407 v = GET_HUFF(gb, b->tree); | |
408 v = (c->col_lastval << 4) | v; | |
409 if (c->version < 'i') { | |
410 sign = ((int8_t) v) >> 7; | |
411 v = ((v & 0x7F) ^ sign) - sign; | |
412 v += 0x80; | |
413 } | |
414 *b->cur_dec++ = v; | |
415 } | |
416 } | |
417 return 0; | |
418 } | |
419 | |
420 /** number of bits used to store first DC value in bundle */ | |
421 #define DC_START_BITS 11 | |
422 | |
423 static int read_dcs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b, | |
424 int start_bits, int has_sign) | |
425 { | |
426 int i, j, len, len2, bsize, sign, v, v2; | |
427 int16_t *dst = (int16_t*)b->cur_dec; | |
428 | |
429 CHECK_READ_VAL(gb, b, len); | |
430 v = get_bits(gb, start_bits - has_sign); | |
431 if (v && has_sign) { | |
432 sign = -get_bits1(gb); | |
433 v = (v ^ sign) - sign; | |
434 } | |
435 *dst++ = v; | |
436 len--; | |
437 for (i = 0; i < len; i += 8) { | |
438 len2 = FFMIN(len - i, 8); | |
439 bsize = get_bits(gb, 4); | |
440 if (bsize) { | |
441 for (j = 0; j < len2; j++) { | |
442 v2 = get_bits(gb, bsize); | |
443 if (v2) { | |
444 sign = -get_bits1(gb); | |
445 v2 = (v2 ^ sign) - sign; | |
446 } | |
447 v += v2; | |
448 *dst++ = v; | |
449 if (v < -32768 || v > 32767) { | |
450 av_log(avctx, AV_LOG_ERROR, "DC value went out of bounds: %d\n", v); | |
451 return -1; | |
452 } | |
453 } | |
454 } else { | |
455 for (j = 0; j < len2; j++) | |
456 *dst++ = v; | |
457 } | |
458 } | |
459 | |
460 b->cur_dec = (uint8_t*)dst; | |
461 return 0; | |
462 } | |
463 | |
464 /** | |
465 * Retrieves next value from bundle. | |
466 * | |
467 * @param c decoder context | |
468 * @param bundle bundle number | |
469 */ | |
470 static inline int get_value(BinkContext *c, int bundle) | |
471 { | |
472 int16_t ret; | |
473 | |
474 if (bundle < BINK_SRC_X_OFF || bundle == BINK_SRC_RUN) | |
475 return *c->bundle[bundle].cur_ptr++; | |
476 if (bundle == BINK_SRC_X_OFF || bundle == BINK_SRC_Y_OFF) | |
477 return (int8_t)*c->bundle[bundle].cur_ptr++; | |
478 ret = *(int16_t*)c->bundle[bundle].cur_ptr; | |
479 c->bundle[bundle].cur_ptr += 2; | |
480 return ret; | |
481 } | |
482 | |
483 /** | |
484 * Reads 8x8 block of DCT coefficients. | |
485 * | |
486 * @param gb context for reading bits | |
487 * @param block place for storing coefficients | |
488 * @param scan scan order table | |
489 * @param is_intra tells what set of quantizer matrices to use | |
490 * @return 0 for success, negative value in other cases | |
491 */ | |
492 static int read_dct_coeffs(GetBitContext *gb, DCTELEM block[64], const uint8_t *scan, | |
493 int is_intra) | |
494 { | |
495 int coef_list[128]; | |
496 int mode_list[128]; | |
497 int i, t, mask, bits, ccoef, mode, sign; | |
498 int list_start = 64, list_end = 64, list_pos; | |
499 int coef_count = 0; | |
500 int coef_idx[64]; | |
501 int quant_idx; | |
502 const uint32_t *quant; | |
503 | |
504 coef_list[list_end] = 4; mode_list[list_end++] = 0; | |
505 coef_list[list_end] = 24; mode_list[list_end++] = 0; | |
506 coef_list[list_end] = 44; mode_list[list_end++] = 0; | |
507 coef_list[list_end] = 1; mode_list[list_end++] = 3; | |
508 coef_list[list_end] = 2; mode_list[list_end++] = 3; | |
509 coef_list[list_end] = 3; mode_list[list_end++] = 3; | |
510 | |
511 bits = get_bits(gb, 4) - 1; | |
512 for (mask = 1 << bits; bits >= 0; mask >>= 1, bits--) { | |
513 list_pos = list_start; | |
514 while (list_pos < list_end) { | |
515 if (!(mode_list[list_pos] | coef_list[list_pos]) || !get_bits1(gb)) { | |
516 list_pos++; | |
517 continue; | |
518 } | |
519 ccoef = coef_list[list_pos]; | |
520 mode = mode_list[list_pos]; | |
521 switch (mode) { | |
522 case 0: | |
523 coef_list[list_pos] = ccoef + 4; | |
524 mode_list[list_pos] = 1; | |
525 case 2: | |
526 if (mode == 2) { | |
527 coef_list[list_pos] = 0; | |
528 mode_list[list_pos++] = 0; | |
529 } | |
530 for (i = 0; i < 4; i++, ccoef++) { | |
531 if (get_bits1(gb)) { | |
532 coef_list[--list_start] = ccoef; | |
533 mode_list[ list_start] = 3; | |
534 } else { | |
535 int t; | |
536 if (!bits) { | |
537 t = 1 - (get_bits1(gb) << 1); | |
538 } else { | |
539 t = get_bits(gb, bits) | mask; | |
540 sign = -get_bits1(gb); | |
541 t = (t ^ sign) - sign; | |
542 } | |
543 block[scan[ccoef]] = t; | |
544 coef_idx[coef_count++] = ccoef; | |
545 } | |
546 } | |
547 break; | |
548 case 1: | |
549 mode_list[list_pos] = 2; | |
550 for (i = 0; i < 3; i++) { | |
551 ccoef += 4; | |
552 coef_list[list_end] = ccoef; | |
553 mode_list[list_end++] = 2; | |
554 } | |
555 break; | |
556 case 3: | |
557 if (!bits) { | |
558 t = 1 - (get_bits1(gb) << 1); | |
559 } else { | |
560 t = get_bits(gb, bits) | mask; | |
561 sign = -get_bits1(gb); | |
562 t = (t ^ sign) - sign; | |
563 } | |
564 block[scan[ccoef]] = t; | |
565 coef_idx[coef_count++] = ccoef; | |
566 coef_list[list_pos] = 0; | |
567 mode_list[list_pos++] = 0; | |
568 break; | |
569 } | |
570 } | |
571 } | |
572 | |
573 quant_idx = get_bits(gb, 4); | |
574 quant = is_intra ? bink_intra_quant[quant_idx] | |
575 : bink_inter_quant[quant_idx]; | |
576 block[0] = (block[0] * quant[0]) >> 11; | |
577 for (i = 0; i < coef_count; i++) { | |
578 int idx = coef_idx[i]; | |
579 block[scan[idx]] = (block[scan[idx]] * quant[idx]) >> 11; | |
580 } | |
581 | |
582 return 0; | |
583 } | |
584 | |
585 /** | |
586 * Reads 8x8 block with residue after motion compensation. | |
587 * | |
588 * @param gb context for reading bits | |
589 * @param block place to store read data | |
590 * @param masks_count number of masks to decode | |
591 * @return 0 on success, negative value in other cases | |
592 */ | |
593 static int read_residue(GetBitContext *gb, DCTELEM block[64], int masks_count) | |
594 { | |
595 int coef_list[128]; | |
596 int mode_list[128]; | |
597 int i, sign, mask, ccoef, mode; | |
598 int list_start = 64, list_end = 64, list_pos; | |
599 int nz_coeff[64]; | |
600 int nz_coeff_count = 0; | |
601 | |
602 coef_list[list_end] = 4; mode_list[list_end++] = 0; | |
603 coef_list[list_end] = 24; mode_list[list_end++] = 0; | |
604 coef_list[list_end] = 44; mode_list[list_end++] = 0; | |
605 coef_list[list_end] = 0; mode_list[list_end++] = 2; | |
606 | |
607 for (mask = 1 << get_bits(gb, 3); mask; mask >>= 1) { | |
608 for (i = 0; i < nz_coeff_count; i++) { | |
609 if (!get_bits1(gb)) | |
610 continue; | |
611 if (block[nz_coeff[i]] < 0) | |
612 block[nz_coeff[i]] -= mask; | |
613 else | |
614 block[nz_coeff[i]] += mask; | |
615 masks_count--; | |
616 if (masks_count < 0) | |
617 return 0; | |
618 } | |
619 list_pos = list_start; | |
620 while (list_pos < list_end) { | |
621 if (!(coef_list[list_pos] | mode_list[list_pos]) || !get_bits1(gb)) { | |
622 list_pos++; | |
623 continue; | |
624 } | |
625 ccoef = coef_list[list_pos]; | |
626 mode = mode_list[list_pos]; | |
627 switch (mode) { | |
628 case 0: | |
629 coef_list[list_pos] = ccoef + 4; | |
630 mode_list[list_pos] = 1; | |
631 case 2: | |
632 if (mode == 2) { | |
633 coef_list[list_pos] = 0; | |
634 mode_list[list_pos++] = 0; | |
635 } | |
636 for (i = 0; i < 4; i++, ccoef++) { | |
637 if (get_bits1(gb)) { | |
638 coef_list[--list_start] = ccoef; | |
639 mode_list[ list_start] = 3; | |
640 } else { | |
641 nz_coeff[nz_coeff_count++] = bink_scan[ccoef]; | |
642 sign = -get_bits1(gb); | |
643 block[bink_scan[ccoef]] = (mask ^ sign) - sign; | |
644 masks_count--; | |
645 if (masks_count < 0) | |
646 return 0; | |
647 } | |
648 } | |
649 break; | |
650 case 1: | |
651 mode_list[list_pos] = 2; | |
652 for (i = 0; i < 3; i++) { | |
653 ccoef += 4; | |
654 coef_list[list_end] = ccoef; | |
655 mode_list[list_end++] = 2; | |
656 } | |
657 break; | |
658 case 3: | |
659 nz_coeff[nz_coeff_count++] = bink_scan[ccoef]; | |
660 sign = -get_bits1(gb); | |
661 block[bink_scan[ccoef]] = (mask ^ sign) - sign; | |
662 coef_list[list_pos] = 0; | |
663 mode_list[list_pos++] = 0; | |
664 masks_count--; | |
665 if (masks_count < 0) | |
666 return 0; | |
667 break; | |
668 } | |
669 } | |
670 } | |
671 | |
672 return 0; | |
673 } | |
674 | |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
675 static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
676 int is_chroma) |
11231 | 677 { |
678 int blk; | |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
679 int i, j, bx, by; |
11231 | 680 uint8_t *dst, *prev, *ref, *ref_start, *ref_end; |
681 int v, col[2]; | |
682 const uint8_t *scan; | |
683 int xoff, yoff; | |
684 DECLARE_ALIGNED_16(DCTELEM, block[64]); | |
685 DECLARE_ALIGNED_16(uint8_t, ublock[64]); | |
686 int coordmap[64]; | |
687 | |
11253 | 688 const int stride = c->pic.linesize[plane_idx]; |
689 int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3; | |
690 int bh = is_chroma ? (c->avctx->height + 15) >> 4 : (c->avctx->height + 7) >> 3; | |
691 int width = c->avctx->width >> is_chroma; | |
11231 | 692 |
11253 | 693 init_lengths(c, FFMAX(width, 8), bw); |
694 for (i = 0; i < BINK_NB_SRC; i++) | |
695 read_bundle(gb, c, i); | |
11231 | 696 |
11253 | 697 ref_start = c->last.data[plane_idx]; |
698 ref_end = c->last.data[plane_idx] | |
699 + (bw - 1 + c->last.linesize[plane_idx] * (bh - 1)) * 8; | |
700 | |
701 for (i = 0; i < 64; i++) | |
702 coordmap[i] = (i & 7) + (i >> 3) * stride; | |
11231 | 703 |
11253 | 704 for (by = 0; by < bh; by++) { |
705 if (read_block_types(c->avctx, gb, &c->bundle[BINK_SRC_BLOCK_TYPES]) < 0) | |
706 return -1; | |
707 if (read_block_types(c->avctx, gb, &c->bundle[BINK_SRC_SUB_BLOCK_TYPES]) < 0) | |
708 return -1; | |
709 if (read_colors(gb, &c->bundle[BINK_SRC_COLORS], c) < 0) | |
710 return -1; | |
711 if (read_patterns(c->avctx, gb, &c->bundle[BINK_SRC_PATTERN]) < 0) | |
712 return -1; | |
713 if (read_motion_values(c->avctx, gb, &c->bundle[BINK_SRC_X_OFF]) < 0) | |
714 return -1; | |
715 if (read_motion_values(c->avctx, gb, &c->bundle[BINK_SRC_Y_OFF]) < 0) | |
716 return -1; | |
717 if (read_dcs(c->avctx, gb, &c->bundle[BINK_SRC_INTRA_DC], DC_START_BITS, 0) < 0) | |
718 return -1; | |
719 if (read_dcs(c->avctx, gb, &c->bundle[BINK_SRC_INTER_DC], DC_START_BITS, 1) < 0) | |
720 return -1; | |
721 if (read_runs(c->avctx, gb, &c->bundle[BINK_SRC_RUN]) < 0) | |
722 return -1; | |
723 | |
724 if (by == bh) | |
725 break; | |
726 dst = c->pic.data[plane_idx] + 8*by*stride; | |
727 prev = c->last.data[plane_idx] + 8*by*stride; | |
728 for (bx = 0; bx < bw; bx++, dst += 8, prev += 8) { | |
729 blk = get_value(c, BINK_SRC_BLOCK_TYPES); | |
730 // 16x16 block type on odd line means part of the already decoded block, so skip it | |
731 if ((by & 1) && blk == SCALED_BLOCK) { | |
732 bx++; | |
733 dst += 8; | |
734 prev += 8; | |
735 continue; | |
736 } | |
737 switch (blk) { | |
738 case SKIP_BLOCK: | |
739 c->dsp.put_pixels_tab[1][0](dst, prev, stride, 8); | |
740 break; | |
741 case SCALED_BLOCK: | |
742 blk = get_value(c, BINK_SRC_SUB_BLOCK_TYPES); | |
743 switch (blk) { | |
11231 | 744 case RUN_BLOCK: |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
745 scan = bink_patterns[get_bits(gb, 4)]; |
11231 | 746 i = 0; |
747 do { | |
748 int run = get_value(c, BINK_SRC_RUN) + 1; | |
749 | |
750 i += run; | |
751 if (i > 64) { | |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
752 av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n"); |
11231 | 753 return -1; |
754 } | |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
755 if (get_bits1(gb)) { |
11231 | 756 v = get_value(c, BINK_SRC_COLORS); |
757 for (j = 0; j < run; j++) | |
11253 | 758 ublock[*scan++] = v; |
11231 | 759 } else { |
760 for (j = 0; j < run; j++) | |
11253 | 761 ublock[*scan++] = get_value(c, BINK_SRC_COLORS); |
11231 | 762 } |
763 } while (i < 63); | |
764 if (i == 63) | |
11253 | 765 ublock[*scan++] = get_value(c, BINK_SRC_COLORS); |
11231 | 766 break; |
767 case INTRA_BLOCK: | |
768 c->dsp.clear_block(block); | |
769 block[0] = get_value(c, BINK_SRC_INTRA_DC); | |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
770 read_dct_coeffs(gb, block, c->scantable.permutated, 1); |
11253 | 771 c->dsp.idct(block); |
772 c->dsp.put_pixels_nonclamped(block, ublock, 8); | |
11231 | 773 break; |
774 case FILL_BLOCK: | |
775 v = get_value(c, BINK_SRC_COLORS); | |
11253 | 776 c->dsp.fill_block_tab[0](dst, v, stride, 16); |
11231 | 777 break; |
778 case PATTERN_BLOCK: | |
779 for (i = 0; i < 2; i++) | |
780 col[i] = get_value(c, BINK_SRC_COLORS); | |
11253 | 781 for (j = 0; j < 8; j++) { |
11231 | 782 v = get_value(c, BINK_SRC_PATTERN); |
11253 | 783 for (i = 0; i < 8; i++, v >>= 1) |
784 ublock[i + j*8] = col[v & 1]; | |
11231 | 785 } |
786 break; | |
787 case RAW_BLOCK: | |
11253 | 788 for (j = 0; j < 8; j++) |
789 for (i = 0; i < 8; i++) | |
790 ublock[i + j*8] = get_value(c, BINK_SRC_COLORS); | |
11231 | 791 break; |
792 default: | |
11253 | 793 av_log(c->avctx, AV_LOG_ERROR, "Incorrect 16x16 block type %d\n", blk); |
794 return -1; | |
795 } | |
796 if (blk != FILL_BLOCK) | |
797 c->dsp.scale_block(ublock, dst, stride); | |
798 bx++; | |
799 dst += 8; | |
800 prev += 8; | |
801 break; | |
802 case MOTION_BLOCK: | |
803 xoff = get_value(c, BINK_SRC_X_OFF); | |
804 yoff = get_value(c, BINK_SRC_Y_OFF); | |
805 ref = prev + xoff + yoff * stride; | |
806 if (ref < ref_start || ref > ref_end) { | |
807 av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", | |
808 bx*8 + xoff, by*8 + yoff); | |
11231 | 809 return -1; |
810 } | |
11253 | 811 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); |
812 break; | |
813 case RUN_BLOCK: | |
814 scan = bink_patterns[get_bits(gb, 4)]; | |
815 i = 0; | |
816 do { | |
817 int run = get_value(c, BINK_SRC_RUN) + 1; | |
818 | |
819 i += run; | |
820 if (i > 64) { | |
821 av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n"); | |
822 return -1; | |
823 } | |
824 if (get_bits1(gb)) { | |
825 v = get_value(c, BINK_SRC_COLORS); | |
826 for (j = 0; j < run; j++) | |
827 dst[coordmap[*scan++]] = v; | |
828 } else { | |
829 for (j = 0; j < run; j++) | |
830 dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS); | |
831 } | |
832 } while (i < 63); | |
833 if (i == 63) | |
834 dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS); | |
835 break; | |
836 case RESIDUE_BLOCK: | |
837 xoff = get_value(c, BINK_SRC_X_OFF); | |
838 yoff = get_value(c, BINK_SRC_Y_OFF); | |
839 ref = prev + xoff + yoff * stride; | |
840 if (ref < ref_start || ref > ref_end) { | |
841 av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", | |
842 bx*8 + xoff, by*8 + yoff); | |
843 return -1; | |
844 } | |
845 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); | |
846 c->dsp.clear_block(block); | |
847 v = get_bits(gb, 7); | |
848 read_residue(gb, block, v); | |
849 c->dsp.add_pixels8(dst, block, stride); | |
850 break; | |
851 case INTRA_BLOCK: | |
852 c->dsp.clear_block(block); | |
853 block[0] = get_value(c, BINK_SRC_INTRA_DC); | |
854 read_dct_coeffs(gb, block, c->scantable.permutated, 1); | |
855 c->dsp.idct_put(dst, stride, block); | |
856 break; | |
857 case FILL_BLOCK: | |
858 v = get_value(c, BINK_SRC_COLORS); | |
859 c->dsp.fill_block_tab[1](dst, v, stride, 8); | |
860 break; | |
861 case INTER_BLOCK: | |
862 xoff = get_value(c, BINK_SRC_X_OFF); | |
863 yoff = get_value(c, BINK_SRC_Y_OFF); | |
864 ref = prev + xoff + yoff * stride; | |
865 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); | |
866 c->dsp.clear_block(block); | |
867 block[0] = get_value(c, BINK_SRC_INTER_DC); | |
868 read_dct_coeffs(gb, block, c->scantable.permutated, 0); | |
869 c->dsp.idct_add(dst, stride, block); | |
870 break; | |
871 case PATTERN_BLOCK: | |
872 for (i = 0; i < 2; i++) | |
873 col[i] = get_value(c, BINK_SRC_COLORS); | |
874 for (i = 0; i < 8; i++) { | |
875 v = get_value(c, BINK_SRC_PATTERN); | |
876 for (j = 0; j < 8; j++, v >>= 1) | |
877 dst[i*stride + j] = col[v & 1]; | |
878 } | |
879 break; | |
880 case RAW_BLOCK: | |
881 for (i = 0; i < 8; i++) | |
882 memcpy(dst + i*stride, c->bundle[BINK_SRC_COLORS].cur_ptr + i*8, 8); | |
883 c->bundle[BINK_SRC_COLORS].cur_ptr += 64; | |
884 break; | |
885 default: | |
886 av_log(c->avctx, AV_LOG_ERROR, "Unknown block type %d\n", blk); | |
887 return -1; | |
11231 | 888 } |
889 } | |
11253 | 890 } |
891 if (get_bits_count(gb) & 0x1F) //next plane data starts at 32-bit boundary | |
892 skip_bits_long(gb, 32 - (get_bits_count(gb) & 0x1F)); | |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
893 |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
894 return 0; |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
895 } |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
896 |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
897 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *pkt) |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
898 { |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
899 BinkContext * const c = avctx->priv_data; |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
900 GetBitContext gb; |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
901 int plane, plane_idx; |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
902 int bits_count = pkt->size << 3; |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
903 |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
904 if(c->pic.data[0]) |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
905 avctx->release_buffer(avctx, &c->pic); |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
906 |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
907 if(avctx->get_buffer(avctx, &c->pic) < 0){ |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
908 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
909 return -1; |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
910 } |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
911 |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
912 init_get_bits(&gb, pkt->data, bits_count); |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
913 if (c->has_alpha) { |
11254 | 914 if (c->version >= 'i') |
915 skip_bits_long(&gb, 32); | |
916 if (bink_decode_plane(c, &gb, 3, 0) < 0) | |
11252
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
917 return -1; |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
918 } |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
919 if (c->version >= 'i') |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
920 skip_bits_long(&gb, 32); |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
921 |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
922 for (plane = 0; plane < 3; plane++) { |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
923 plane_idx = (!plane || !c->swap_planes) ? plane : (plane ^ 3); |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
924 |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
925 if (bink_decode_plane(c, &gb, plane_idx, !!plane) < 0) |
d6513f6a949e
Move plane decoding code into separate function in Bink decoder
kostya
parents:
11251
diff
changeset
|
926 return -1; |
11245
1e9ff636c3db
Make Bink decoder to stop decoding planes after all bits are used.
kostya
parents:
11244
diff
changeset
|
927 if (get_bits_count(&gb) >= bits_count) |
1e9ff636c3db
Make Bink decoder to stop decoding planes after all bits are used.
kostya
parents:
11244
diff
changeset
|
928 break; |
11231 | 929 } |
930 emms_c(); | |
931 | |
932 *data_size = sizeof(AVFrame); | |
933 *(AVFrame*)data = c->pic; | |
934 | |
935 FFSWAP(AVFrame, c->pic, c->last); | |
936 | |
937 /* always report that the buffer was completely consumed */ | |
938 return pkt->size; | |
939 } | |
940 | |
941 static av_cold int decode_init(AVCodecContext *avctx) | |
942 { | |
943 BinkContext * const c = avctx->priv_data; | |
944 static VLC_TYPE table[16 * 128][2]; | |
945 int i; | |
11251
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
946 int flags; |
11231 | 947 |
948 c->version = avctx->codec_tag >> 24; | |
949 if (c->version < 'c') { | |
950 av_log(avctx, AV_LOG_ERROR, "Too old version '%c'\n", c->version); | |
951 return -1; | |
952 } | |
11251
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
953 if (avctx->extradata_size < 4) { |
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
954 av_log(avctx, AV_LOG_ERROR, "Extradata missing or too short\n"); |
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
955 return -1; |
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
956 } |
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
957 flags = AV_RL32(avctx->extradata); |
56e65f21e9c5
Bink video decoder now can use extradata to detect alpha plane presence
kostya
parents:
11247
diff
changeset
|
958 c->has_alpha = flags & BINK_FLAG_ALPHA; |
11231 | 959 c->swap_planes = c->version >= 'i'; |
960 if (!bink_trees[15].table) { | |
961 for (i = 0; i < 16; i++) { | |
962 const int maxbits = bink_tree_lens[i][15]; | |
963 bink_trees[i].table = table + i*128; | |
964 bink_trees[i].table_allocated = 1 << maxbits; | |
965 init_vlc(&bink_trees[i], maxbits, 16, | |
966 bink_tree_lens[i], 1, 1, | |
967 bink_tree_bits[i], 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); | |
968 } | |
969 } | |
970 c->avctx = avctx; | |
971 | |
972 c->pic.data[0] = NULL; | |
973 | |
974 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) { | |
975 return 1; | |
976 } | |
977 | |
11254 | 978 avctx->pix_fmt = c->has_alpha ? PIX_FMT_YUVA420P : PIX_FMT_YUV420P; |
11231 | 979 |
980 avctx->idct_algo = FF_IDCT_BINK; | |
981 dsputil_init(&c->dsp, avctx); | |
982 ff_init_scantable(c->dsp.idct_permutation, &c->scantable, bink_scan); | |
983 | |
984 init_bundles(c); | |
985 | |
986 return 0; | |
987 } | |
988 | |
989 static av_cold int decode_end(AVCodecContext *avctx) | |
990 { | |
991 BinkContext * const c = avctx->priv_data; | |
992 | |
993 if (c->pic.data[0]) | |
994 avctx->release_buffer(avctx, &c->pic); | |
995 if (c->last.data[0]) | |
996 avctx->release_buffer(avctx, &c->last); | |
997 | |
998 free_bundles(c); | |
999 return 0; | |
1000 } | |
1001 | |
1002 AVCodec bink_decoder = { | |
1003 "binkvideo", | |
1004 CODEC_TYPE_VIDEO, | |
1005 CODEC_ID_BINKVIDEO, | |
1006 sizeof(BinkContext), | |
1007 decode_init, | |
1008 NULL, | |
1009 decode_end, | |
1010 decode_frame, | |
1011 .long_name = NULL_IF_CONFIG_SMALL("Bink video"), | |
1012 }; |