diff options
Diffstat (limited to 'libavcodec/bink.c')
-rw-r--r-- | libavcodec/bink.c | 100 |
1 files changed, 51 insertions, 49 deletions
diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 22e13c33dd..9bab4b992b 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -3,20 +3,20 @@ * Copyright (c) 2009 Konstantin Shishkov * Copyright (C) 2011 Peter Ross <pross@xvid.org> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -26,6 +26,7 @@ #include "dsputil.h" #include "binkdata.h" #include "binkdsp.h" +#include "hpeldsp.h" #include "internal.h" #include "mathops.h" @@ -112,6 +113,7 @@ typedef struct Bundle { typedef struct BinkContext { AVCodecContext *avctx; DSPContext dsp; + HpelDSPContext hdsp; BinkDSPContext bdsp; AVFrame *last; int version; ///< internal Bink file version @@ -171,7 +173,7 @@ static void init_lengths(BinkContext *c, int width, int bw) * * @param c decoder context */ -static av_cold void init_bundles(BinkContext *c) +static av_cold int init_bundles(BinkContext *c) { int bw, bh, blocks; int i; @@ -182,8 +184,12 @@ static av_cold void init_bundles(BinkContext *c) for (i = 0; i < BINKB_NB_SRC; i++) { c->bundle[i].data = av_malloc(blocks * 64); + if (!c->bundle[i].data) + return AVERROR(ENOMEM); c->bundle[i].data_end = c->bundle[i].data + blocks * 64; } + + return 0; } /** @@ -676,6 +682,10 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t * quant_idx = get_bits(gb, 4); } else { quant_idx = q; + if (quant_idx > 15U) { + av_log(NULL, AV_LOG_ERROR, "quant_index %d out of range\n", quant_idx); + return AVERROR_INVALIDDATA; + } } quant = quant_matrices[quant_idx]; @@ -860,7 +870,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = binkb_get_value(c, BINKB_SRC_INTRA_DC); qp = binkb_get_value(c, BINKB_SRC_INTRA_Q); - read_dct_coeffs(gb, dctblock, bink_scan, binkb_intra_quant, qp); + read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_intra_quant, qp); c->bdsp.idct_put(dst, stride, dctblock); break; case 3: @@ -870,7 +880,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, if (ref < ref_start || ref + 8*stride > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); } else { put_pixels8x8_overlapped(dst, ref, stride); } @@ -886,14 +896,14 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, if (ref < ref_start || ref + 8 * stride > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); } else { put_pixels8x8_overlapped(dst, ref, stride); } memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = binkb_get_value(c, BINKB_SRC_INTER_DC); qp = binkb_get_value(c, BINKB_SRC_INTER_Q); - read_dct_coeffs(gb, dctblock, bink_scan, binkb_inter_quant, qp); + read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_inter_quant, qp); c->bdsp.idct_add(dst, stride, dctblock); break; case 5: @@ -916,7 +926,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, if (ref < ref_start || ref + 8 * stride > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); } else { put_pixels8x8_overlapped(dst, ref, stride); } @@ -1005,7 +1015,7 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, } switch (blk) { case SKIP_BLOCK: - c->dsp.put_pixels_tab[1][0](dst, prev, stride, 8); + c->hdsp.put_pixels_tab[1][0](dst, prev, stride, 8); break; case SCALED_BLOCK: blk = get_value(c, BINK_SRC_SUB_BLOCK_TYPES); @@ -1076,7 +1086,7 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, bx*8 + xoff, by*8 + yoff); return AVERROR_INVALIDDATA; } - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); break; case RUN_BLOCK: scan = bink_patterns[get_bits(gb, 4)]; @@ -1110,7 +1120,7 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, bx*8 + xoff, by*8 + yoff); return AVERROR_INVALIDDATA; } - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); c->dsp.clear_block(block); v = get_bits(gb, 7); read_residue(gb, block, v); @@ -1130,7 +1140,12 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, xoff = get_value(c, BINK_SRC_X_OFF); yoff = get_value(c, BINK_SRC_Y_OFF); ref = prev + xoff + yoff * stride; - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); + if (ref < ref_start || ref > ref_end) { + av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", + bx*8 + xoff, by*8 + yoff); + return -1; + } + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTER_DC); read_dct_coeffs(gb, dctblock, bink_scan, bink_inter_quant, -1); @@ -1171,15 +1186,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac int bits_count = pkt->size << 3; if (c->version > 'b') { - if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - } } else { - if ((ret = ff_reget_buffer(avctx, c->last)) < 0) { - av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); + if ((ret = ff_reget_buffer(avctx, c->last)) < 0) return ret; - } if ((ret = av_frame_ref(frame, c->last)) < 0) return ret; } @@ -1228,41 +1239,28 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac static av_cold void binkb_calc_quant(void) { uint8_t inv_bink_scan[64]; - double s[64]; + static const int s[64]={ + 1073741824,1489322693,1402911301,1262586814,1073741824, 843633538, 581104888, 296244703, + 1489322693,2065749918,1945893874,1751258219,1489322693,1170153332, 806015634, 410903207, + 1402911301,1945893874,1832991949,1649649171,1402911301,1102260336, 759250125, 387062357, + 1262586814,1751258219,1649649171,1484645031,1262586814, 992008094, 683307060, 348346918, + 1073741824,1489322693,1402911301,1262586814,1073741824, 843633538, 581104888, 296244703, + 843633538,1170153332,1102260336, 992008094, 843633538, 662838617, 456571181, 232757969, + 581104888, 806015634, 759250125, 683307060, 581104888, 456571181, 314491699, 160326478, + 296244703, 410903207, 387062357, 348346918, 296244703, 232757969, 160326478, 81733730, + }; int i, j; - - for (j = 0; j < 8; j++) { - for (i = 0; i < 8; i++) { - if (j && j != 4) - if (i && i != 4) - s[j*8 + i] = cos(j * M_PI/16.0) * cos(i * M_PI/16.0) * 2.0; - else - s[j*8 + i] = cos(j * M_PI/16.0) * sqrt(2.0); - else - if (i && i != 4) - s[j*8 + i] = cos(i * M_PI/16.0) * sqrt(2.0); - else - s[j*8 + i] = 1.0; - } - } - +#define C (1LL<<30) for (i = 0; i < 64; i++) inv_bink_scan[bink_scan[i]] = i; for (j = 0; j < 16; j++) { for (i = 0; i < 64; i++) { int k = inv_bink_scan[i]; - if (s[i] == 1.0) { - binkb_intra_quant[j][k] = (1L << 12) * binkb_intra_seed[i] * - binkb_num[j]/binkb_den[j]; - binkb_inter_quant[j][k] = (1L << 12) * binkb_inter_seed[i] * - binkb_num[j]/binkb_den[j]; - } else { - binkb_intra_quant[j][k] = (1L << 12) * binkb_intra_seed[i] * s[i] * - binkb_num[j]/(double)binkb_den[j]; - binkb_inter_quant[j][k] = (1L << 12) * binkb_inter_seed[i] * s[i] * - binkb_num[j]/(double)binkb_den[j]; - } + binkb_intra_quant[j][k] = binkb_intra_seed[i] * (int64_t)s[i] * + binkb_num[j]/(binkb_den[j] * (C>>12)); + binkb_inter_quant[j][k] = binkb_inter_seed[i] * (int64_t)s[i] * + binkb_num[j]/(binkb_den[j] * (C>>12)); } } } @@ -1305,9 +1303,13 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; ff_dsputil_init(&c->dsp, avctx); + ff_hpeldsp_init(&c->hdsp, avctx->flags); ff_binkdsp_init(&c->bdsp); - init_bundles(c); + if ((ret = init_bundles(c)) < 0) { + free_bundles(c); + return ret; + } if (c->version == 'b') { if (!binkb_initialised) { |