00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "libavutil/imgutils.h"
00024 #include "avcodec.h"
00025 #include "dsputil.h"
00026 #include "binkdata.h"
00027 #include "mathops.h"
00028
00029 #define ALT_BITSTREAM_READER_LE
00030 #include "get_bits.h"
00031
00032 #define BINK_FLAG_ALPHA 0x00100000
00033 #define BINK_FLAG_GRAY 0x00020000
00034
00035 static VLC bink_trees[16];
00036
00040 enum OldSources {
00041 BINKB_SRC_BLOCK_TYPES = 0,
00042 BINKB_SRC_COLORS,
00043 BINKB_SRC_PATTERN,
00044 BINKB_SRC_X_OFF,
00045 BINKB_SRC_Y_OFF,
00046 BINKB_SRC_INTRA_DC,
00047 BINKB_SRC_INTER_DC,
00048 BINKB_SRC_INTRA_Q,
00049 BINKB_SRC_INTER_Q,
00050 BINKB_SRC_INTER_COEFS,
00051
00052 BINKB_NB_SRC
00053 };
00054
00055 static const int binkb_bundle_sizes[BINKB_NB_SRC] = {
00056 4, 8, 8, 5, 5, 11, 11, 4, 4, 7
00057 };
00058
00059 static const int binkb_bundle_signed[BINKB_NB_SRC] = {
00060 0, 0, 0, 1, 1, 0, 1, 0, 0, 0
00061 };
00062
00063 static uint32_t binkb_intra_quant[16][64];
00064 static uint32_t binkb_inter_quant[16][64];
00065
00069 enum Sources {
00070 BINK_SRC_BLOCK_TYPES = 0,
00071 BINK_SRC_SUB_BLOCK_TYPES,
00072 BINK_SRC_COLORS,
00073 BINK_SRC_PATTERN,
00074 BINK_SRC_X_OFF,
00075 BINK_SRC_Y_OFF,
00076 BINK_SRC_INTRA_DC,
00077 BINK_SRC_INTER_DC,
00078 BINK_SRC_RUN,
00079
00080 BINK_NB_SRC
00081 };
00082
00086 typedef struct Tree {
00087 int vlc_num;
00088 uint8_t syms[16];
00089 } Tree;
00090
00091 #define GET_HUFF(gb, tree) (tree).syms[get_vlc2(gb, bink_trees[(tree).vlc_num].table,\
00092 bink_trees[(tree).vlc_num].bits, 1)]
00093
00097 typedef struct Bundle {
00098 int len;
00099 Tree tree;
00100 uint8_t *data;
00101 uint8_t *data_end;
00102 uint8_t *cur_dec;
00103 uint8_t *cur_ptr;
00104 } Bundle;
00105
00106
00107
00108
00109 typedef struct BinkContext {
00110 AVCodecContext *avctx;
00111 DSPContext dsp;
00112 AVFrame pic, last;
00113 int version;
00114 int has_alpha;
00115 int swap_planes;
00116 ScanTable scantable;
00117
00118 Bundle bundle[BINKB_NB_SRC];
00119 Tree col_high[16];
00120 int col_lastval;
00121 } BinkContext;
00122
00126 enum BlockTypes {
00127 SKIP_BLOCK = 0,
00128 SCALED_BLOCK,
00129 MOTION_BLOCK,
00130 RUN_BLOCK,
00131 RESIDUE_BLOCK,
00132 INTRA_BLOCK,
00133 FILL_BLOCK,
00134 INTER_BLOCK,
00135 PATTERN_BLOCK,
00136 RAW_BLOCK,
00137 };
00138
00146 static void init_lengths(BinkContext *c, int width, int bw)
00147 {
00148 c->bundle[BINK_SRC_BLOCK_TYPES].len = av_log2((width >> 3) + 511) + 1;
00149
00150 c->bundle[BINK_SRC_SUB_BLOCK_TYPES].len = av_log2((width >> 4) + 511) + 1;
00151
00152 c->bundle[BINK_SRC_COLORS].len = av_log2(bw*64 + 511) + 1;
00153
00154 c->bundle[BINK_SRC_INTRA_DC].len =
00155 c->bundle[BINK_SRC_INTER_DC].len =
00156 c->bundle[BINK_SRC_X_OFF].len =
00157 c->bundle[BINK_SRC_Y_OFF].len = av_log2((width >> 3) + 511) + 1;
00158
00159 c->bundle[BINK_SRC_PATTERN].len = av_log2((bw << 3) + 511) + 1;
00160
00161 c->bundle[BINK_SRC_RUN].len = av_log2(bw*48 + 511) + 1;
00162 }
00163
00169 static av_cold void init_bundles(BinkContext *c)
00170 {
00171 int bw, bh, blocks;
00172 int i;
00173
00174 bw = (c->avctx->width + 7) >> 3;
00175 bh = (c->avctx->height + 7) >> 3;
00176 blocks = bw * bh;
00177
00178 for (i = 0; i < BINKB_NB_SRC; i++) {
00179 c->bundle[i].data = av_malloc(blocks * 64);
00180 c->bundle[i].data_end = c->bundle[i].data + blocks * 64;
00181 }
00182 }
00183
00189 static av_cold void free_bundles(BinkContext *c)
00190 {
00191 int i;
00192 for (i = 0; i < BINKB_NB_SRC; i++)
00193 av_freep(&c->bundle[i].data);
00194 }
00195
00204 static void merge(GetBitContext *gb, uint8_t *dst, uint8_t *src, int size)
00205 {
00206 uint8_t *src2 = src + size;
00207 int size2 = size;
00208
00209 do {
00210 if (!get_bits1(gb)) {
00211 *dst++ = *src++;
00212 size--;
00213 } else {
00214 *dst++ = *src2++;
00215 size2--;
00216 }
00217 } while (size && size2);
00218
00219 while (size--)
00220 *dst++ = *src++;
00221 while (size2--)
00222 *dst++ = *src2++;
00223 }
00224
00231 static void read_tree(GetBitContext *gb, Tree *tree)
00232 {
00233 uint8_t tmp1[16], tmp2[16], *in = tmp1, *out = tmp2;
00234 int i, t, len;
00235
00236 tree->vlc_num = get_bits(gb, 4);
00237 if (!tree->vlc_num) {
00238 for (i = 0; i < 16; i++)
00239 tree->syms[i] = i;
00240 return;
00241 }
00242 if (get_bits1(gb)) {
00243 len = get_bits(gb, 3);
00244 memset(tmp1, 0, sizeof(tmp1));
00245 for (i = 0; i <= len; i++) {
00246 tree->syms[i] = get_bits(gb, 4);
00247 tmp1[tree->syms[i]] = 1;
00248 }
00249 for (i = 0; i < 16 && len < 16 - 1; i++)
00250 if (!tmp1[i])
00251 tree->syms[++len] = i;
00252 } else {
00253 len = get_bits(gb, 2);
00254 for (i = 0; i < 16; i++)
00255 in[i] = i;
00256 for (i = 0; i <= len; i++) {
00257 int size = 1 << i;
00258 for (t = 0; t < 16; t += size << 1)
00259 merge(gb, out + t, in + t, size);
00260 FFSWAP(uint8_t*, in, out);
00261 }
00262 memcpy(tree->syms, in, 16);
00263 }
00264 }
00265
00273 static void read_bundle(GetBitContext *gb, BinkContext *c, int bundle_num)
00274 {
00275 int i;
00276
00277 if (bundle_num == BINK_SRC_COLORS) {
00278 for (i = 0; i < 16; i++)
00279 read_tree(gb, &c->col_high[i]);
00280 c->col_lastval = 0;
00281 }
00282 if (bundle_num != BINK_SRC_INTRA_DC && bundle_num != BINK_SRC_INTER_DC)
00283 read_tree(gb, &c->bundle[bundle_num].tree);
00284 c->bundle[bundle_num].cur_dec =
00285 c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data;
00286 }
00287
00295 #define CHECK_READ_VAL(gb, b, t) \
00296 if (!b->cur_dec || (b->cur_dec > b->cur_ptr)) \
00297 return 0; \
00298 t = get_bits(gb, b->len); \
00299 if (!t) { \
00300 b->cur_dec = NULL; \
00301 return 0; \
00302 } \
00303
00304 static int read_runs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
00305 {
00306 int t, v;
00307 const uint8_t *dec_end;
00308
00309 CHECK_READ_VAL(gb, b, t);
00310 dec_end = b->cur_dec + t;
00311 if (dec_end > b->data_end) {
00312 av_log(avctx, AV_LOG_ERROR, "Run value went out of bounds\n");
00313 return -1;
00314 }
00315 if (get_bits1(gb)) {
00316 v = get_bits(gb, 4);
00317 memset(b->cur_dec, v, t);
00318 b->cur_dec += t;
00319 } else {
00320 while (b->cur_dec < dec_end)
00321 *b->cur_dec++ = GET_HUFF(gb, b->tree);
00322 }
00323 return 0;
00324 }
00325
00326 static int read_motion_values(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
00327 {
00328 int t, sign, v;
00329 const uint8_t *dec_end;
00330
00331 CHECK_READ_VAL(gb, b, t);
00332 dec_end = b->cur_dec + t;
00333 if (dec_end > b->data_end) {
00334 av_log(avctx, AV_LOG_ERROR, "Too many motion values\n");
00335 return -1;
00336 }
00337 if (get_bits1(gb)) {
00338 v = get_bits(gb, 4);
00339 if (v) {
00340 sign = -get_bits1(gb);
00341 v = (v ^ sign) - sign;
00342 }
00343 memset(b->cur_dec, v, t);
00344 b->cur_dec += t;
00345 } else {
00346 while (b->cur_dec < dec_end) {
00347 v = GET_HUFF(gb, b->tree);
00348 if (v) {
00349 sign = -get_bits1(gb);
00350 v = (v ^ sign) - sign;
00351 }
00352 *b->cur_dec++ = v;
00353 }
00354 }
00355 return 0;
00356 }
00357
00358 static const uint8_t bink_rlelens[4] = { 4, 8, 12, 32 };
00359
00360 static int read_block_types(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
00361 {
00362 int t, v;
00363 int last = 0;
00364 const uint8_t *dec_end;
00365
00366 CHECK_READ_VAL(gb, b, t);
00367 dec_end = b->cur_dec + t;
00368 if (dec_end > b->data_end) {
00369 av_log(avctx, AV_LOG_ERROR, "Too many block type values\n");
00370 return -1;
00371 }
00372 if (get_bits1(gb)) {
00373 v = get_bits(gb, 4);
00374 memset(b->cur_dec, v, t);
00375 b->cur_dec += t;
00376 } else {
00377 while (b->cur_dec < dec_end) {
00378 v = GET_HUFF(gb, b->tree);
00379 if (v < 12) {
00380 last = v;
00381 *b->cur_dec++ = v;
00382 } else {
00383 int run = bink_rlelens[v - 12];
00384
00385 if (dec_end - b->cur_dec < run)
00386 return -1;
00387 memset(b->cur_dec, last, run);
00388 b->cur_dec += run;
00389 }
00390 }
00391 }
00392 return 0;
00393 }
00394
00395 static int read_patterns(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
00396 {
00397 int t, v;
00398 const uint8_t *dec_end;
00399
00400 CHECK_READ_VAL(gb, b, t);
00401 dec_end = b->cur_dec + t;
00402 if (dec_end > b->data_end) {
00403 av_log(avctx, AV_LOG_ERROR, "Too many pattern values\n");
00404 return -1;
00405 }
00406 while (b->cur_dec < dec_end) {
00407 v = GET_HUFF(gb, b->tree);
00408 v |= GET_HUFF(gb, b->tree) << 4;
00409 *b->cur_dec++ = v;
00410 }
00411
00412 return 0;
00413 }
00414
00415 static int read_colors(GetBitContext *gb, Bundle *b, BinkContext *c)
00416 {
00417 int t, sign, v;
00418 const uint8_t *dec_end;
00419
00420 CHECK_READ_VAL(gb, b, t);
00421 dec_end = b->cur_dec + t;
00422 if (dec_end > b->data_end) {
00423 av_log(c->avctx, AV_LOG_ERROR, "Too many color values\n");
00424 return -1;
00425 }
00426 if (get_bits1(gb)) {
00427 c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]);
00428 v = GET_HUFF(gb, b->tree);
00429 v = (c->col_lastval << 4) | v;
00430 if (c->version < 'i') {
00431 sign = ((int8_t) v) >> 7;
00432 v = ((v & 0x7F) ^ sign) - sign;
00433 v += 0x80;
00434 }
00435 memset(b->cur_dec, v, t);
00436 b->cur_dec += t;
00437 } else {
00438 while (b->cur_dec < dec_end) {
00439 c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]);
00440 v = GET_HUFF(gb, b->tree);
00441 v = (c->col_lastval << 4) | v;
00442 if (c->version < 'i') {
00443 sign = ((int8_t) v) >> 7;
00444 v = ((v & 0x7F) ^ sign) - sign;
00445 v += 0x80;
00446 }
00447 *b->cur_dec++ = v;
00448 }
00449 }
00450 return 0;
00451 }
00452
00454 #define DC_START_BITS 11
00455
00456 static int read_dcs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b,
00457 int start_bits, int has_sign)
00458 {
00459 int i, j, len, len2, bsize, sign, v, v2;
00460 int16_t *dst = (int16_t*)b->cur_dec;
00461 int16_t *dst_end = (int16_t*)b->data_end;
00462
00463 CHECK_READ_VAL(gb, b, len);
00464 v = get_bits(gb, start_bits - has_sign);
00465 if (v && has_sign) {
00466 sign = -get_bits1(gb);
00467 v = (v ^ sign) - sign;
00468 }
00469 if (dst_end - dst < 1)
00470 return -1;
00471 *dst++ = v;
00472 len--;
00473 for (i = 0; i < len; i += 8) {
00474 len2 = FFMIN(len - i, 8);
00475 if (dst_end - dst < len2)
00476 return -1;
00477 bsize = get_bits(gb, 4);
00478 if (bsize) {
00479 for (j = 0; j < len2; j++) {
00480 v2 = get_bits(gb, bsize);
00481 if (v2) {
00482 sign = -get_bits1(gb);
00483 v2 = (v2 ^ sign) - sign;
00484 }
00485 v += v2;
00486 *dst++ = v;
00487 if (v < -32768 || v > 32767) {
00488 av_log(avctx, AV_LOG_ERROR, "DC value went out of bounds: %d\n", v);
00489 return -1;
00490 }
00491 }
00492 } else {
00493 for (j = 0; j < len2; j++)
00494 *dst++ = v;
00495 }
00496 }
00497
00498 b->cur_dec = (uint8_t*)dst;
00499 return 0;
00500 }
00501
00508 static inline int get_value(BinkContext *c, int bundle)
00509 {
00510 int ret;
00511
00512 if (bundle < BINK_SRC_X_OFF || bundle == BINK_SRC_RUN)
00513 return *c->bundle[bundle].cur_ptr++;
00514 if (bundle == BINK_SRC_X_OFF || bundle == BINK_SRC_Y_OFF)
00515 return (int8_t)*c->bundle[bundle].cur_ptr++;
00516 ret = *(int16_t*)c->bundle[bundle].cur_ptr;
00517 c->bundle[bundle].cur_ptr += 2;
00518 return ret;
00519 }
00520
00521 static void binkb_init_bundle(BinkContext *c, int bundle_num)
00522 {
00523 c->bundle[bundle_num].cur_dec =
00524 c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data;
00525 c->bundle[bundle_num].len = 13;
00526 }
00527
00528 static void binkb_init_bundles(BinkContext *c)
00529 {
00530 int i;
00531 for (i = 0; i < BINKB_NB_SRC; i++)
00532 binkb_init_bundle(c, i);
00533 }
00534
00535 static int binkb_read_bundle(BinkContext *c, GetBitContext *gb, int bundle_num)
00536 {
00537 const int bits = binkb_bundle_sizes[bundle_num];
00538 const int mask = 1 << (bits - 1);
00539 const int issigned = binkb_bundle_signed[bundle_num];
00540 Bundle *b = &c->bundle[bundle_num];
00541 int i, len;
00542
00543 CHECK_READ_VAL(gb, b, len);
00544 if (b->data_end - b->cur_dec < len * (1 + (bits > 8)))
00545 return -1;
00546 if (bits <= 8) {
00547 if (!issigned) {
00548 for (i = 0; i < len; i++)
00549 *b->cur_dec++ = get_bits(gb, bits);
00550 } else {
00551 for (i = 0; i < len; i++)
00552 *b->cur_dec++ = get_bits(gb, bits) - mask;
00553 }
00554 } else {
00555 int16_t *dst = (int16_t*)b->cur_dec;
00556
00557 if (!issigned) {
00558 for (i = 0; i < len; i++)
00559 *dst++ = get_bits(gb, bits);
00560 } else {
00561 for (i = 0; i < len; i++)
00562 *dst++ = get_bits(gb, bits) - mask;
00563 }
00564 b->cur_dec = (uint8_t*)dst;
00565 }
00566 return 0;
00567 }
00568
00569 static inline int binkb_get_value(BinkContext *c, int bundle_num)
00570 {
00571 int16_t ret;
00572 const int bits = binkb_bundle_sizes[bundle_num];
00573
00574 if (bits <= 8) {
00575 int val = *c->bundle[bundle_num].cur_ptr++;
00576 return binkb_bundle_signed[bundle_num] ? (int8_t)val : val;
00577 }
00578 ret = *(int16_t*)c->bundle[bundle_num].cur_ptr;
00579 c->bundle[bundle_num].cur_ptr += 2;
00580 return ret;
00581 }
00582
00583 static inline DCTELEM dequant(DCTELEM in, uint32_t quant, int dc)
00584 {
00585
00586
00587
00588
00589
00590
00591
00592 int32_t res = in * quant;
00593 res >>= 11;
00594 if (!dc)
00595 res = av_clip_int16(res);
00596 return res;
00597 }
00598
00608 static int read_dct_coeffs(GetBitContext *gb, DCTELEM block[64], const uint8_t *scan,
00609 const uint32_t quant_matrices[16][64], int q)
00610 {
00611 int coef_list[128];
00612 int mode_list[128];
00613 int i, t, mask, bits, ccoef, mode, sign;
00614 int list_start = 64, list_end = 64, list_pos;
00615 int coef_count = 0;
00616 int coef_idx[64];
00617 int quant_idx;
00618 const uint32_t *quant;
00619
00620 coef_list[list_end] = 4; mode_list[list_end++] = 0;
00621 coef_list[list_end] = 24; mode_list[list_end++] = 0;
00622 coef_list[list_end] = 44; mode_list[list_end++] = 0;
00623 coef_list[list_end] = 1; mode_list[list_end++] = 3;
00624 coef_list[list_end] = 2; mode_list[list_end++] = 3;
00625 coef_list[list_end] = 3; mode_list[list_end++] = 3;
00626
00627 bits = get_bits(gb, 4) - 1;
00628 for (mask = 1 << bits; bits >= 0; mask >>= 1, bits--) {
00629 list_pos = list_start;
00630 while (list_pos < list_end) {
00631 if (!(mode_list[list_pos] | coef_list[list_pos]) || !get_bits1(gb)) {
00632 list_pos++;
00633 continue;
00634 }
00635 ccoef = coef_list[list_pos];
00636 mode = mode_list[list_pos];
00637 switch (mode) {
00638 case 0:
00639 coef_list[list_pos] = ccoef + 4;
00640 mode_list[list_pos] = 1;
00641 case 2:
00642 if (mode == 2) {
00643 coef_list[list_pos] = 0;
00644 mode_list[list_pos++] = 0;
00645 }
00646 for (i = 0; i < 4; i++, ccoef++) {
00647 if (get_bits1(gb)) {
00648 coef_list[--list_start] = ccoef;
00649 mode_list[ list_start] = 3;
00650 } else {
00651 int t;
00652 if (!bits) {
00653 t = 1 - (get_bits1(gb) << 1);
00654 } else {
00655 t = get_bits(gb, bits) | mask;
00656 sign = -get_bits1(gb);
00657 t = (t ^ sign) - sign;
00658 }
00659 block[scan[ccoef]] = t;
00660 coef_idx[coef_count++] = ccoef;
00661 }
00662 }
00663 break;
00664 case 1:
00665 mode_list[list_pos] = 2;
00666 for (i = 0; i < 3; i++) {
00667 ccoef += 4;
00668 coef_list[list_end] = ccoef;
00669 mode_list[list_end++] = 2;
00670 }
00671 break;
00672 case 3:
00673 if (!bits) {
00674 t = 1 - (get_bits1(gb) << 1);
00675 } else {
00676 t = get_bits(gb, bits) | mask;
00677 sign = -get_bits1(gb);
00678 t = (t ^ sign) - sign;
00679 }
00680 block[scan[ccoef]] = t;
00681 coef_idx[coef_count++] = ccoef;
00682 coef_list[list_pos] = 0;
00683 mode_list[list_pos++] = 0;
00684 break;
00685 }
00686 }
00687 }
00688
00689 if (q == -1) {
00690 quant_idx = get_bits(gb, 4);
00691 } else {
00692 quant_idx = q;
00693 }
00694
00695 quant = quant_matrices[quant_idx];
00696
00697 block[0] = dequant(block[0], quant[0], 1);
00698 for (i = 0; i < coef_count; i++) {
00699 int idx = coef_idx[i];
00700 block[scan[idx]] = dequant(block[scan[idx]], quant[idx], 0);
00701 }
00702
00703 return 0;
00704 }
00705
00714 static int read_residue(GetBitContext *gb, DCTELEM block[64], int masks_count)
00715 {
00716 int coef_list[128];
00717 int mode_list[128];
00718 int i, sign, mask, ccoef, mode;
00719 int list_start = 64, list_end = 64, list_pos;
00720 int nz_coeff[64];
00721 int nz_coeff_count = 0;
00722
00723 coef_list[list_end] = 4; mode_list[list_end++] = 0;
00724 coef_list[list_end] = 24; mode_list[list_end++] = 0;
00725 coef_list[list_end] = 44; mode_list[list_end++] = 0;
00726 coef_list[list_end] = 0; mode_list[list_end++] = 2;
00727
00728 for (mask = 1 << get_bits(gb, 3); mask; mask >>= 1) {
00729 for (i = 0; i < nz_coeff_count; i++) {
00730 if (!get_bits1(gb))
00731 continue;
00732 if (block[nz_coeff[i]] < 0)
00733 block[nz_coeff[i]] -= mask;
00734 else
00735 block[nz_coeff[i]] += mask;
00736 masks_count--;
00737 if (masks_count < 0)
00738 return 0;
00739 }
00740 list_pos = list_start;
00741 while (list_pos < list_end) {
00742 if (!(coef_list[list_pos] | mode_list[list_pos]) || !get_bits1(gb)) {
00743 list_pos++;
00744 continue;
00745 }
00746 ccoef = coef_list[list_pos];
00747 mode = mode_list[list_pos];
00748 switch (mode) {
00749 case 0:
00750 coef_list[list_pos] = ccoef + 4;
00751 mode_list[list_pos] = 1;
00752 case 2:
00753 if (mode == 2) {
00754 coef_list[list_pos] = 0;
00755 mode_list[list_pos++] = 0;
00756 }
00757 for (i = 0; i < 4; i++, ccoef++) {
00758 if (get_bits1(gb)) {
00759 coef_list[--list_start] = ccoef;
00760 mode_list[ list_start] = 3;
00761 } else {
00762 nz_coeff[nz_coeff_count++] = bink_scan[ccoef];
00763 sign = -get_bits1(gb);
00764 block[bink_scan[ccoef]] = (mask ^ sign) - sign;
00765 masks_count--;
00766 if (masks_count < 0)
00767 return 0;
00768 }
00769 }
00770 break;
00771 case 1:
00772 mode_list[list_pos] = 2;
00773 for (i = 0; i < 3; i++) {
00774 ccoef += 4;
00775 coef_list[list_end] = ccoef;
00776 mode_list[list_end++] = 2;
00777 }
00778 break;
00779 case 3:
00780 nz_coeff[nz_coeff_count++] = bink_scan[ccoef];
00781 sign = -get_bits1(gb);
00782 block[bink_scan[ccoef]] = (mask ^ sign) - sign;
00783 coef_list[list_pos] = 0;
00784 mode_list[list_pos++] = 0;
00785 masks_count--;
00786 if (masks_count < 0)
00787 return 0;
00788 break;
00789 }
00790 }
00791 }
00792
00793 return 0;
00794 }
00795
00799 static inline void put_pixels8x8_overlapped(uint8_t *dst, uint8_t *src, int stride)
00800 {
00801 uint8_t tmp[64];
00802 int i;
00803 for (i = 0; i < 8; i++)
00804 memcpy(tmp + i*8, src + i*stride, 8);
00805 for (i = 0; i < 8; i++)
00806 memcpy(dst + i*stride, tmp + i*8, 8);
00807 }
00808
00809 static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx,
00810 int is_key, int is_chroma)
00811 {
00812 int blk;
00813 int i, j, bx, by;
00814 uint8_t *dst, *ref, *ref_start, *ref_end;
00815 int v, col[2];
00816 const uint8_t *scan;
00817 int xoff, yoff;
00818 LOCAL_ALIGNED_16(DCTELEM, block, [64]);
00819 int coordmap[64];
00820 int ybias = is_key ? -15 : 0;
00821 int qp;
00822
00823 const int stride = c->pic.linesize[plane_idx];
00824 int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3;
00825 int bh = is_chroma ? (c->avctx->height + 15) >> 4 : (c->avctx->height + 7) >> 3;
00826
00827 binkb_init_bundles(c);
00828 ref_start = c->pic.data[plane_idx];
00829 ref_end = c->pic.data[plane_idx] + (bh * c->pic.linesize[plane_idx] + bw) * 8;
00830
00831 for (i = 0; i < 64; i++)
00832 coordmap[i] = (i & 7) + (i >> 3) * stride;
00833
00834 for (by = 0; by < bh; by++) {
00835 for (i = 0; i < BINKB_NB_SRC; i++) {
00836 if (binkb_read_bundle(c, gb, i) < 0)
00837 return -1;
00838 }
00839
00840 dst = c->pic.data[plane_idx] + 8*by*stride;
00841 for (bx = 0; bx < bw; bx++, dst += 8) {
00842 blk = binkb_get_value(c, BINKB_SRC_BLOCK_TYPES);
00843 switch (blk) {
00844 case 0:
00845 break;
00846 case 1:
00847 scan = bink_patterns[get_bits(gb, 4)];
00848 i = 0;
00849 do {
00850 int mode, run;
00851
00852 mode = get_bits1(gb);
00853 run = get_bits(gb, binkb_runbits[i]) + 1;
00854
00855 i += run;
00856 if (i > 64) {
00857 av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n");
00858 return -1;
00859 }
00860 if (mode) {
00861 v = binkb_get_value(c, BINKB_SRC_COLORS);
00862 for (j = 0; j < run; j++)
00863 dst[coordmap[*scan++]] = v;
00864 } else {
00865 for (j = 0; j < run; j++)
00866 dst[coordmap[*scan++]] = binkb_get_value(c, BINKB_SRC_COLORS);
00867 }
00868 } while (i < 63);
00869 if (i == 63)
00870 dst[coordmap[*scan++]] = binkb_get_value(c, BINKB_SRC_COLORS);
00871 break;
00872 case 2:
00873 c->dsp.clear_block(block);
00874 block[0] = binkb_get_value(c, BINKB_SRC_INTRA_DC);
00875 qp = binkb_get_value(c, BINKB_SRC_INTRA_Q);
00876 read_dct_coeffs(gb, block, c->scantable.permutated, binkb_intra_quant, qp);
00877 c->dsp.idct_put(dst, stride, block);
00878 break;
00879 case 3:
00880 xoff = binkb_get_value(c, BINKB_SRC_X_OFF);
00881 yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias;
00882 ref = dst + xoff + yoff * stride;
00883 if (ref < ref_start || ref + 8*stride > ref_end) {
00884 av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n");
00885 } else if (ref + 8*stride < dst || ref >= dst + 8*stride) {
00886 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
00887 } else {
00888 put_pixels8x8_overlapped(dst, ref, stride);
00889 }
00890 c->dsp.clear_block(block);
00891 v = binkb_get_value(c, BINKB_SRC_INTER_COEFS);
00892 read_residue(gb, block, v);
00893 c->dsp.add_pixels8(dst, block, stride);
00894 break;
00895 case 4:
00896 xoff = binkb_get_value(c, BINKB_SRC_X_OFF);
00897 yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias;
00898 ref = dst + xoff + yoff * stride;
00899 if (ref < ref_start || ref + 8 * stride > ref_end) {
00900 av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n");
00901 } else if (ref + 8*stride < dst || ref >= dst + 8*stride) {
00902 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
00903 } else {
00904 put_pixels8x8_overlapped(dst, ref, stride);
00905 }
00906 c->dsp.clear_block(block);
00907 block[0] = binkb_get_value(c, BINKB_SRC_INTER_DC);
00908 qp = binkb_get_value(c, BINKB_SRC_INTER_Q);
00909 read_dct_coeffs(gb, block, c->scantable.permutated, binkb_inter_quant, qp);
00910 c->dsp.idct_add(dst, stride, block);
00911 break;
00912 case 5:
00913 v = binkb_get_value(c, BINKB_SRC_COLORS);
00914 c->dsp.fill_block_tab[1](dst, v, stride, 8);
00915 break;
00916 case 6:
00917 for (i = 0; i < 2; i++)
00918 col[i] = binkb_get_value(c, BINKB_SRC_COLORS);
00919 for (i = 0; i < 8; i++) {
00920 v = binkb_get_value(c, BINKB_SRC_PATTERN);
00921 for (j = 0; j < 8; j++, v >>= 1)
00922 dst[i*stride + j] = col[v & 1];
00923 }
00924 break;
00925 case 7:
00926 xoff = binkb_get_value(c, BINKB_SRC_X_OFF);
00927 yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias;
00928 ref = dst + xoff + yoff * stride;
00929 if (ref < ref_start || ref + 8 * stride > ref_end) {
00930 av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n");
00931 } else if (ref + 8*stride < dst || ref >= dst + 8*stride) {
00932 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
00933 } else {
00934 put_pixels8x8_overlapped(dst, ref, stride);
00935 }
00936 break;
00937 case 8:
00938 for (i = 0; i < 8; i++)
00939 memcpy(dst + i*stride, c->bundle[BINKB_SRC_COLORS].cur_ptr + i*8, 8);
00940 c->bundle[BINKB_SRC_COLORS].cur_ptr += 64;
00941 break;
00942 default:
00943 av_log(c->avctx, AV_LOG_ERROR, "Unknown block type %d\n", blk);
00944 return -1;
00945 }
00946 }
00947 }
00948 if (get_bits_count(gb) & 0x1F)
00949 skip_bits_long(gb, 32 - (get_bits_count(gb) & 0x1F));
00950
00951 return 0;
00952 }
00953
00954 static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx,
00955 int is_chroma)
00956 {
00957 int blk;
00958 int i, j, bx, by;
00959 uint8_t *dst, *prev, *ref, *ref_start, *ref_end;
00960 int v, col[2];
00961 const uint8_t *scan;
00962 int xoff, yoff;
00963 LOCAL_ALIGNED_16(DCTELEM, block, [64]);
00964 LOCAL_ALIGNED_16(uint8_t, ublock, [64]);
00965 int coordmap[64];
00966
00967 const int stride = c->pic.linesize[plane_idx];
00968 int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3;
00969 int bh = is_chroma ? (c->avctx->height + 15) >> 4 : (c->avctx->height + 7) >> 3;
00970 int width = c->avctx->width >> is_chroma;
00971
00972 init_lengths(c, FFMAX(width, 8), bw);
00973 for (i = 0; i < BINK_NB_SRC; i++)
00974 read_bundle(gb, c, i);
00975
00976 ref_start = c->last.data[plane_idx] ? c->last.data[plane_idx]
00977 : c->pic.data[plane_idx];
00978 ref_end = ref_start
00979 + (bw - 1 + c->last.linesize[plane_idx] * (bh - 1)) * 8;
00980
00981 for (i = 0; i < 64; i++)
00982 coordmap[i] = (i & 7) + (i >> 3) * stride;
00983
00984 for (by = 0; by < bh; by++) {
00985 if (read_block_types(c->avctx, gb, &c->bundle[BINK_SRC_BLOCK_TYPES]) < 0)
00986 return -1;
00987 if (read_block_types(c->avctx, gb, &c->bundle[BINK_SRC_SUB_BLOCK_TYPES]) < 0)
00988 return -1;
00989 if (read_colors(gb, &c->bundle[BINK_SRC_COLORS], c) < 0)
00990 return -1;
00991 if (read_patterns(c->avctx, gb, &c->bundle[BINK_SRC_PATTERN]) < 0)
00992 return -1;
00993 if (read_motion_values(c->avctx, gb, &c->bundle[BINK_SRC_X_OFF]) < 0)
00994 return -1;
00995 if (read_motion_values(c->avctx, gb, &c->bundle[BINK_SRC_Y_OFF]) < 0)
00996 return -1;
00997 if (read_dcs(c->avctx, gb, &c->bundle[BINK_SRC_INTRA_DC], DC_START_BITS, 0) < 0)
00998 return -1;
00999 if (read_dcs(c->avctx, gb, &c->bundle[BINK_SRC_INTER_DC], DC_START_BITS, 1) < 0)
01000 return -1;
01001 if (read_runs(c->avctx, gb, &c->bundle[BINK_SRC_RUN]) < 0)
01002 return -1;
01003
01004 if (by == bh)
01005 break;
01006 dst = c->pic.data[plane_idx] + 8*by*stride;
01007 prev = (c->last.data[plane_idx] ? c->last.data[plane_idx]
01008 : c->pic.data[plane_idx]) + 8*by*stride;
01009 for (bx = 0; bx < bw; bx++, dst += 8, prev += 8) {
01010 blk = get_value(c, BINK_SRC_BLOCK_TYPES);
01011
01012 if ((by & 1) && blk == SCALED_BLOCK) {
01013 bx++;
01014 dst += 8;
01015 prev += 8;
01016 continue;
01017 }
01018 switch (blk) {
01019 case SKIP_BLOCK:
01020 c->dsp.put_pixels_tab[1][0](dst, prev, stride, 8);
01021 break;
01022 case SCALED_BLOCK:
01023 blk = get_value(c, BINK_SRC_SUB_BLOCK_TYPES);
01024 switch (blk) {
01025 case RUN_BLOCK:
01026 scan = bink_patterns[get_bits(gb, 4)];
01027 i = 0;
01028 do {
01029 int run = get_value(c, BINK_SRC_RUN) + 1;
01030
01031 i += run;
01032 if (i > 64) {
01033 av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n");
01034 return -1;
01035 }
01036 if (get_bits1(gb)) {
01037 v = get_value(c, BINK_SRC_COLORS);
01038 for (j = 0; j < run; j++)
01039 ublock[*scan++] = v;
01040 } else {
01041 for (j = 0; j < run; j++)
01042 ublock[*scan++] = get_value(c, BINK_SRC_COLORS);
01043 }
01044 } while (i < 63);
01045 if (i == 63)
01046 ublock[*scan++] = get_value(c, BINK_SRC_COLORS);
01047 break;
01048 case INTRA_BLOCK:
01049 c->dsp.clear_block(block);
01050 block[0] = get_value(c, BINK_SRC_INTRA_DC);
01051 read_dct_coeffs(gb, block, c->scantable.permutated, bink_intra_quant, -1);
01052 c->dsp.idct(block);
01053 c->dsp.put_pixels_nonclamped(block, ublock, 8);
01054 break;
01055 case FILL_BLOCK:
01056 v = get_value(c, BINK_SRC_COLORS);
01057 c->dsp.fill_block_tab[0](dst, v, stride, 16);
01058 break;
01059 case PATTERN_BLOCK:
01060 for (i = 0; i < 2; i++)
01061 col[i] = get_value(c, BINK_SRC_COLORS);
01062 for (j = 0; j < 8; j++) {
01063 v = get_value(c, BINK_SRC_PATTERN);
01064 for (i = 0; i < 8; i++, v >>= 1)
01065 ublock[i + j*8] = col[v & 1];
01066 }
01067 break;
01068 case RAW_BLOCK:
01069 for (j = 0; j < 8; j++)
01070 for (i = 0; i < 8; i++)
01071 ublock[i + j*8] = get_value(c, BINK_SRC_COLORS);
01072 break;
01073 default:
01074 av_log(c->avctx, AV_LOG_ERROR, "Incorrect 16x16 block type %d\n", blk);
01075 return -1;
01076 }
01077 if (blk != FILL_BLOCK)
01078 c->dsp.scale_block(ublock, dst, stride);
01079 bx++;
01080 dst += 8;
01081 prev += 8;
01082 break;
01083 case MOTION_BLOCK:
01084 xoff = get_value(c, BINK_SRC_X_OFF);
01085 yoff = get_value(c, BINK_SRC_Y_OFF);
01086 ref = prev + xoff + yoff * stride;
01087 if (ref < ref_start || ref > ref_end) {
01088 av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n",
01089 bx*8 + xoff, by*8 + yoff);
01090 return -1;
01091 }
01092 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
01093 break;
01094 case RUN_BLOCK:
01095 scan = bink_patterns[get_bits(gb, 4)];
01096 i = 0;
01097 do {
01098 int run = get_value(c, BINK_SRC_RUN) + 1;
01099
01100 i += run;
01101 if (i > 64) {
01102 av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n");
01103 return -1;
01104 }
01105 if (get_bits1(gb)) {
01106 v = get_value(c, BINK_SRC_COLORS);
01107 for (j = 0; j < run; j++)
01108 dst[coordmap[*scan++]] = v;
01109 } else {
01110 for (j = 0; j < run; j++)
01111 dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS);
01112 }
01113 } while (i < 63);
01114 if (i == 63)
01115 dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS);
01116 break;
01117 case RESIDUE_BLOCK:
01118 xoff = get_value(c, BINK_SRC_X_OFF);
01119 yoff = get_value(c, BINK_SRC_Y_OFF);
01120 ref = prev + xoff + yoff * stride;
01121 if (ref < ref_start || ref > ref_end) {
01122 av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n",
01123 bx*8 + xoff, by*8 + yoff);
01124 return -1;
01125 }
01126 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
01127 c->dsp.clear_block(block);
01128 v = get_bits(gb, 7);
01129 read_residue(gb, block, v);
01130 c->dsp.add_pixels8(dst, block, stride);
01131 break;
01132 case INTRA_BLOCK:
01133 c->dsp.clear_block(block);
01134 block[0] = get_value(c, BINK_SRC_INTRA_DC);
01135 read_dct_coeffs(gb, block, c->scantable.permutated, bink_intra_quant, -1);
01136 c->dsp.idct_put(dst, stride, block);
01137 break;
01138 case FILL_BLOCK:
01139 v = get_value(c, BINK_SRC_COLORS);
01140 c->dsp.fill_block_tab[1](dst, v, stride, 8);
01141 break;
01142 case INTER_BLOCK:
01143 xoff = get_value(c, BINK_SRC_X_OFF);
01144 yoff = get_value(c, BINK_SRC_Y_OFF);
01145 ref = prev + xoff + yoff * stride;
01146 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
01147 c->dsp.clear_block(block);
01148 block[0] = get_value(c, BINK_SRC_INTER_DC);
01149 read_dct_coeffs(gb, block, c->scantable.permutated, bink_inter_quant, -1);
01150 c->dsp.idct_add(dst, stride, block);
01151 break;
01152 case PATTERN_BLOCK:
01153 for (i = 0; i < 2; i++)
01154 col[i] = get_value(c, BINK_SRC_COLORS);
01155 for (i = 0; i < 8; i++) {
01156 v = get_value(c, BINK_SRC_PATTERN);
01157 for (j = 0; j < 8; j++, v >>= 1)
01158 dst[i*stride + j] = col[v & 1];
01159 }
01160 break;
01161 case RAW_BLOCK:
01162 for (i = 0; i < 8; i++)
01163 memcpy(dst + i*stride, c->bundle[BINK_SRC_COLORS].cur_ptr + i*8, 8);
01164 c->bundle[BINK_SRC_COLORS].cur_ptr += 64;
01165 break;
01166 default:
01167 av_log(c->avctx, AV_LOG_ERROR, "Unknown block type %d\n", blk);
01168 return -1;
01169 }
01170 }
01171 }
01172 if (get_bits_count(gb) & 0x1F)
01173 skip_bits_long(gb, 32 - (get_bits_count(gb) & 0x1F));
01174
01175 return 0;
01176 }
01177
01178 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *pkt)
01179 {
01180 BinkContext * const c = avctx->priv_data;
01181 GetBitContext gb;
01182 int plane, plane_idx;
01183 int bits_count = pkt->size << 3;
01184
01185 if (c->version > 'b') {
01186 if(c->pic.data[0])
01187 avctx->release_buffer(avctx, &c->pic);
01188
01189 if(avctx->get_buffer(avctx, &c->pic) < 0){
01190 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
01191 return -1;
01192 }
01193 } else {
01194 if(avctx->reget_buffer(avctx, &c->pic) < 0){
01195 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
01196 return -1;
01197 }
01198 }
01199
01200 init_get_bits(&gb, pkt->data, bits_count);
01201 if (c->has_alpha) {
01202 if (c->version >= 'i')
01203 skip_bits_long(&gb, 32);
01204 if (bink_decode_plane(c, &gb, 3, 0) < 0)
01205 return -1;
01206 }
01207 if (c->version >= 'i')
01208 skip_bits_long(&gb, 32);
01209
01210 for (plane = 0; plane < 3; plane++) {
01211 plane_idx = (!plane || !c->swap_planes) ? plane : (plane ^ 3);
01212
01213 if (c->version > 'b') {
01214 if (bink_decode_plane(c, &gb, plane_idx, !!plane) < 0)
01215 return -1;
01216 } else {
01217 if (binkb_decode_plane(c, &gb, plane_idx, !pkt->pts, !!plane) < 0)
01218 return -1;
01219 }
01220 if (get_bits_count(&gb) >= bits_count)
01221 break;
01222 }
01223 emms_c();
01224
01225 *data_size = sizeof(AVFrame);
01226 *(AVFrame*)data = c->pic;
01227
01228 if (c->version > 'b')
01229 FFSWAP(AVFrame, c->pic, c->last);
01230
01231
01232 return pkt->size;
01233 }
01234
01238 static av_cold void binkb_calc_quant(void)
01239 {
01240 uint8_t inv_bink_scan[64];
01241 double s[64];
01242 int i, j;
01243
01244 for (j = 0; j < 8; j++) {
01245 for (i = 0; i < 8; i++) {
01246 if (j && j != 4)
01247 if (i && i != 4)
01248 s[j*8 + i] = cos(j * M_PI/16.0) * cos(i * M_PI/16.0) * 2.0;
01249 else
01250 s[j*8 + i] = cos(j * M_PI/16.0) * sqrt(2.0);
01251 else
01252 if (i && i != 4)
01253 s[j*8 + i] = cos(i * M_PI/16.0) * sqrt(2.0);
01254 else
01255 s[j*8 + i] = 1.0;
01256 }
01257 }
01258
01259 for (i = 0; i < 64; i++)
01260 inv_bink_scan[bink_scan[i]] = i;
01261
01262 for (j = 0; j < 16; j++) {
01263 for (i = 0; i < 64; i++) {
01264 int k = inv_bink_scan[i];
01265 if (s[i] == 1.0) {
01266 binkb_intra_quant[j][k] = (1L << 12) * binkb_intra_seed[i] *
01267 binkb_num[j]/binkb_den[j];
01268 binkb_inter_quant[j][k] = (1L << 12) * binkb_inter_seed[i] *
01269 binkb_num[j]/binkb_den[j];
01270 } else {
01271 binkb_intra_quant[j][k] = (1L << 12) * binkb_intra_seed[i] * s[i] *
01272 binkb_num[j]/(double)binkb_den[j];
01273 binkb_inter_quant[j][k] = (1L << 12) * binkb_inter_seed[i] * s[i] *
01274 binkb_num[j]/(double)binkb_den[j];
01275 }
01276 }
01277 }
01278 }
01279
01280 static av_cold int decode_init(AVCodecContext *avctx)
01281 {
01282 BinkContext * const c = avctx->priv_data;
01283 static VLC_TYPE table[16 * 128][2];
01284 static int binkb_initialised = 0;
01285 int i;
01286 int flags;
01287
01288 c->version = avctx->codec_tag >> 24;
01289 if (avctx->extradata_size < 4) {
01290 av_log(avctx, AV_LOG_ERROR, "Extradata missing or too short\n");
01291 return -1;
01292 }
01293 flags = AV_RL32(avctx->extradata);
01294 c->has_alpha = flags & BINK_FLAG_ALPHA;
01295 c->swap_planes = c->version >= 'h';
01296 if (!bink_trees[15].table) {
01297 for (i = 0; i < 16; i++) {
01298 const int maxbits = bink_tree_lens[i][15];
01299 bink_trees[i].table = table + i*128;
01300 bink_trees[i].table_allocated = 1 << maxbits;
01301 init_vlc(&bink_trees[i], maxbits, 16,
01302 bink_tree_lens[i], 1, 1,
01303 bink_tree_bits[i], 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE);
01304 }
01305 }
01306 c->avctx = avctx;
01307
01308 c->pic.data[0] = NULL;
01309
01310 if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
01311 return 1;
01312 }
01313
01314 avctx->pix_fmt = c->has_alpha ? PIX_FMT_YUVA420P : PIX_FMT_YUV420P;
01315
01316 avctx->idct_algo = FF_IDCT_BINK;
01317 dsputil_init(&c->dsp, avctx);
01318 ff_init_scantable(c->dsp.idct_permutation, &c->scantable, bink_scan);
01319
01320 init_bundles(c);
01321
01322 if (c->version == 'b') {
01323 if (!binkb_initialised) {
01324 binkb_calc_quant();
01325 binkb_initialised = 1;
01326 }
01327 }
01328
01329 return 0;
01330 }
01331
01332 static av_cold int decode_end(AVCodecContext *avctx)
01333 {
01334 BinkContext * const c = avctx->priv_data;
01335
01336 if (c->pic.data[0])
01337 avctx->release_buffer(avctx, &c->pic);
01338 if (c->last.data[0])
01339 avctx->release_buffer(avctx, &c->last);
01340
01341 free_bundles(c);
01342 return 0;
01343 }
01344
01345 AVCodec ff_bink_decoder = {
01346 "binkvideo",
01347 AVMEDIA_TYPE_VIDEO,
01348 CODEC_ID_BINKVIDEO,
01349 sizeof(BinkContext),
01350 decode_init,
01351 NULL,
01352 decode_end,
01353 decode_frame,
01354 .long_name = NULL_IF_CONFIG_SMALL("Bink video"),
01355 };