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