X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=libavcodec%2Fbink.c;h=74336974d023d5e0337a09763ef130ba6b33b7fa;hb=081961f819c0b16c7a860d7da7d39f1fd91bd2f0;hp=b81fda53d8e637eedd1e98f9aefc241ac45d4ac7;hpb=93af2734ee609133eaeca28329d7f13241dd411f;p=ffmpeg diff --git a/libavcodec/bink.c b/libavcodec/bink.c index b81fda53d8e..74336974d02 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -20,17 +20,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes.h" #include "libavutil/imgutils.h" +#include "libavutil/internal.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" -#include "dsputil.h" #include "binkdata.h" #include "binkdsp.h" +#include "blockdsp.h" +#include "get_bits.h" +#include "hpeldsp.h" #include "internal.h" #include "mathops.h" -#define BITSTREAM_READER_LE -#include "get_bits.h" - #define BINK_FLAG_ALPHA 0x00100000 #define BINK_FLAG_GRAY 0x00020000 @@ -110,9 +113,10 @@ typedef struct Bundle { */ typedef struct BinkContext { AVCodecContext *avctx; - DSPContext dsp; - BinkDSPContext bdsp; - AVFrame *pic, *last; + BlockDSPContext bdsp; + HpelDSPContext hdsp; + BinkDSPContext binkdsp; + AVFrame *last; int version; ///< internal Bink file version int has_alpha; int swap_planes; @@ -521,14 +525,14 @@ static inline int get_value(BinkContext *c, int bundle) return ret; } -static void binkb_init_bundle(BinkContext *c, int bundle_num) +static av_cold void binkb_init_bundle(BinkContext *c, int bundle_num) { c->bundle[bundle_num].cur_dec = c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data; c->bundle[bundle_num].len = 13; } -static void binkb_init_bundles(BinkContext *c) +static av_cold void binkb_init_bundles(BinkContext *c) { int i; for (i = 0; i < BINKB_NB_SRC; i++) @@ -677,6 +681,9 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t * quant_idx = q; } + if (quant_idx >= 16) + return AVERROR_INVALIDDATA; + quant = quant_matrices[quant_idx]; block[0] = (block[0] * quant[0]) >> 11; @@ -696,7 +703,7 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t * * @param masks_count number of masks to decode * @return 0 on success, negative value in other cases */ -static int read_residue(GetBitContext *gb, DCTELEM block[64], int masks_count) +static int read_residue(GetBitContext *gb, int16_t block[64], int masks_count) { int coef_list[128]; int mode_list[128]; @@ -791,8 +798,8 @@ static inline void put_pixels8x8_overlapped(uint8_t *dst, uint8_t *src, int stri memcpy(dst + i*stride, tmp + i*8, 8); } -static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, - int is_key, int is_chroma) +static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, + int plane_idx, int is_key, int is_chroma) { int blk, ret; int i, j, bx, by; @@ -800,19 +807,19 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, int v, col[2]; const uint8_t *scan; int xoff, yoff; - LOCAL_ALIGNED_16(DCTELEM, block, [64]); + LOCAL_ALIGNED_16(int16_t, block, [64]); LOCAL_ALIGNED_16(int32_t, dctblock, [64]); int coordmap[64]; int ybias = is_key ? -15 : 0; int qp; - const int stride = c->pic->linesize[plane_idx]; + const int stride = frame->linesize[plane_idx]; int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3; int bh = is_chroma ? (c->avctx->height + 15) >> 4 : (c->avctx->height + 7) >> 3; binkb_init_bundles(c); - ref_start = c->pic->data[plane_idx]; - ref_end = c->pic->data[plane_idx] + (bh * c->pic->linesize[plane_idx] + bw) * 8; + ref_start = frame->data[plane_idx]; + ref_end = frame->data[plane_idx] + (bh * frame->linesize[plane_idx] + bw) * 8; for (i = 0; i < 64; i++) coordmap[i] = (i & 7) + (i >> 3) * stride; @@ -823,7 +830,7 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, return ret; } - dst = c->pic->data[plane_idx] + 8*by*stride; + dst = frame->data[plane_idx] + 8*by*stride; for (bx = 0; bx < bw; bx++, dst += 8) { blk = binkb_get_value(c, BINKB_SRC_BLOCK_TYPES); switch (blk) { @@ -860,7 +867,7 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, 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); - c->bdsp.idct_put(dst, stride, dctblock); + c->binkdsp.idct_put(dst, stride, dctblock); break; case 3: xoff = binkb_get_value(c, BINKB_SRC_X_OFF); @@ -869,14 +876,14 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, 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); } - c->dsp.clear_block(block); + c->bdsp.clear_block(block); v = binkb_get_value(c, BINKB_SRC_INTER_COEFS); read_residue(gb, block, v); - c->dsp.add_pixels8(dst, block, stride); + c->binkdsp.add_pixels8(dst, block, stride); break; case 4: xoff = binkb_get_value(c, BINKB_SRC_X_OFF); @@ -885,7 +892,7 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, 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); } @@ -893,11 +900,11 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, 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); - c->bdsp.idct_add(dst, stride, dctblock); + c->binkdsp.idct_add(dst, stride, dctblock); break; case 5: v = binkb_get_value(c, BINKB_SRC_COLORS); - c->dsp.fill_block_tab[1](dst, v, stride, 8); + c->bdsp.fill_block_tab[1](dst, v, stride, 8); break; case 6: for (i = 0; i < 2; i++) @@ -915,7 +922,7 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, 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); } @@ -937,21 +944,38 @@ static int binkb_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, return 0; } -static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, - int is_chroma) +static int bink_put_pixels(BinkContext *c, + uint8_t *dst, uint8_t *prev, int stride, + uint8_t *ref_start, + uint8_t *ref_end) +{ + int xoff = get_value(c, BINK_SRC_X_OFF); + int yoff = get_value(c, BINK_SRC_Y_OFF); + uint8_t *ref = prev + xoff + yoff * stride; + if (ref < ref_start || ref > ref_end) { + av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", + xoff, yoff); + return AVERROR_INVALIDDATA; + } + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + + return 0; +} + +static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, + int plane_idx, int is_chroma) { int blk, ret; int i, j, bx, by; - uint8_t *dst, *prev, *ref, *ref_start, *ref_end; + uint8_t *dst, *prev, *ref_start, *ref_end; int v, col[2]; const uint8_t *scan; - int xoff, yoff; - LOCAL_ALIGNED_16(DCTELEM, block, [64]); + LOCAL_ALIGNED_16(int16_t, block, [64]); LOCAL_ALIGNED_16(uint8_t, ublock, [64]); LOCAL_ALIGNED_16(int32_t, dctblock, [64]); int coordmap[64]; - const int stride = c->pic->linesize[plane_idx]; + const int stride = frame->linesize[plane_idx]; int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3; int bh = is_chroma ? (c->avctx->height + 15) >> 4 : (c->avctx->height + 7) >> 3; int width = c->avctx->width >> is_chroma; @@ -961,7 +985,7 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, read_bundle(gb, c, i); ref_start = c->last->data[plane_idx] ? c->last->data[plane_idx] - : c->pic->data[plane_idx]; + : frame->data[plane_idx]; ref_end = ref_start + (bw - 1 + c->last->linesize[plane_idx] * (bh - 1)) * 8; @@ -990,9 +1014,9 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, if (by == bh) break; - dst = c->pic->data[plane_idx] + 8*by*stride; + dst = frame->data[plane_idx] + 8*by*stride; prev = (c->last->data[plane_idx] ? c->last->data[plane_idx] - : c->pic->data[plane_idx]) + 8*by*stride; + : frame->data[plane_idx]) + 8*by*stride; for (bx = 0; bx < bw; bx++, dst += 8, prev += 8) { blk = get_value(c, BINK_SRC_BLOCK_TYPES); // 16x16 block type on odd line means part of the already decoded block, so skip it @@ -1004,7 +1028,7 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, } 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); @@ -1036,11 +1060,11 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1); - c->bdsp.idct_put(ublock, 8, dctblock); + c->binkdsp.idct_put(ublock, 8, dctblock); break; case FILL_BLOCK: v = get_value(c, BINK_SRC_COLORS); - c->dsp.fill_block_tab[0](dst, v, stride, 16); + c->bdsp.fill_block_tab[0](dst, v, stride, 16); break; case PATTERN_BLOCK: for (i = 0; i < 2; i++) @@ -1061,21 +1085,16 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, return AVERROR_INVALIDDATA; } if (blk != FILL_BLOCK) - c->bdsp.scale_block(ublock, dst, stride); + c->binkdsp.scale_block(ublock, dst, stride); bx++; dst += 8; prev += 8; break; case MOTION_BLOCK: - xoff = get_value(c, BINK_SRC_X_OFF); - yoff = get_value(c, BINK_SRC_Y_OFF); - ref = prev + xoff + yoff * stride; - 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 AVERROR_INVALIDDATA; - } - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); + ret = bink_put_pixels(c, dst, prev, stride, + ref_start, ref_end); + if (ret < 0) + return ret; break; case RUN_BLOCK: scan = bink_patterns[get_bits(gb, 4)]; @@ -1101,39 +1120,34 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS); break; case RESIDUE_BLOCK: - xoff = get_value(c, BINK_SRC_X_OFF); - yoff = get_value(c, BINK_SRC_Y_OFF); - ref = prev + xoff + yoff * stride; - 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 AVERROR_INVALIDDATA; - } - c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8); - c->dsp.clear_block(block); + ret = bink_put_pixels(c, dst, prev, stride, + ref_start, ref_end); + if (ret < 0) + return ret; + c->bdsp.clear_block(block); v = get_bits(gb, 7); read_residue(gb, block, v); - c->dsp.add_pixels8(dst, block, stride); + c->binkdsp.add_pixels8(dst, block, stride); break; case INTRA_BLOCK: memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1); - c->bdsp.idct_put(dst, stride, dctblock); + c->binkdsp.idct_put(dst, stride, dctblock); break; case FILL_BLOCK: v = get_value(c, BINK_SRC_COLORS); - c->dsp.fill_block_tab[1](dst, v, stride, 8); + c->bdsp.fill_block_tab[1](dst, v, stride, 8); break; case INTER_BLOCK: - 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); + ret = bink_put_pixels(c, dst, prev, stride, + ref_start, ref_end); + if (ret < 0) + return ret; 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); - c->bdsp.idct_add(dst, stride, dctblock); + c->binkdsp.idct_add(dst, stride, dctblock); break; case PATTERN_BLOCK: for (i = 0; i < 2; i++) @@ -1164,30 +1178,30 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) { BinkContext * const c = avctx->priv_data; + AVFrame *frame = data; GetBitContext gb; int plane, plane_idx, ret; int bits_count = pkt->size << 3; if (c->version > 'b') { - if(c->pic->data[0]) - avctx->release_buffer(avctx, c->pic); - - if ((ret = ff_get_buffer(avctx, c->pic)) < 0) { + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } } else { - if ((ret = avctx->reget_buffer(avctx, c->pic)) < 0) { + if ((ret = ff_reget_buffer(avctx, c->last)) < 0) { av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return ret; } + if ((ret = av_frame_ref(frame, c->last)) < 0) + return ret; } init_get_bits(&gb, pkt->data, bits_count); if (c->has_alpha) { if (c->version >= 'i') skip_bits_long(&gb, 32); - if ((ret = bink_decode_plane(c, &gb, 3, 0)) < 0) + if ((ret = bink_decode_plane(c, frame, &gb, 3, 0)) < 0) return ret; } if (c->version >= 'i') @@ -1197,10 +1211,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac plane_idx = (!plane || !c->swap_planes) ? plane : (plane ^ 3); if (c->version > 'b') { - if ((ret = bink_decode_plane(c, &gb, plane_idx, !!plane)) < 0) + if ((ret = bink_decode_plane(c, frame, &gb, plane_idx, !!plane)) < 0) return ret; } else { - if ((ret = binkb_decode_plane(c, &gb, plane_idx, !pkt->pts, !!plane)) < 0) + if ((ret = binkb_decode_plane(c, frame, &gb, plane_idx, + !avctx->frame_number, !!plane)) < 0) return ret; } if (get_bits_count(&gb) >= bits_count) @@ -1208,18 +1223,20 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac } emms_c(); - *got_frame = 1; - *(AVFrame*)data = *c->pic; + if (c->version > 'b') { + av_frame_unref(c->last); + if ((ret = av_frame_ref(c->last, frame)) < 0) + return ret; + } - if (c->version > 'b') - FFSWAP(AVFrame*, c->pic, c->last); + *got_frame = 1; /* always report that the buffer was completely consumed */ return pkt->size; } /** - * Caclulate quantization tables for version b + * Calculate quantization tables for version b */ static av_cold void binkb_calc_quant(void) { @@ -1291,21 +1308,18 @@ static av_cold int decode_init(AVCodecContext *avctx) } c->avctx = avctx; - c->pic = avcodec_alloc_frame(); - c->last = avcodec_alloc_frame(); - if (!c->pic || !c->last) { - avcodec_free_frame(&c->pic); - avcodec_free_frame(&c->last); + c->last = av_frame_alloc(); + if (!c->last) return AVERROR(ENOMEM); - } if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) return ret; avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; - ff_dsputil_init(&c->dsp, avctx); - ff_binkdsp_init(&c->bdsp); + ff_blockdsp_init(&c->bdsp, avctx); + ff_hpeldsp_init(&c->hdsp, avctx->flags); + ff_binkdsp_init(&c->binkdsp); init_bundles(c); @@ -1323,12 +1337,7 @@ static av_cold int decode_end(AVCodecContext *avctx) { BinkContext * const c = avctx->priv_data; - if (c->pic->data[0]) - avctx->release_buffer(avctx, c->pic); - if (c->last->data[0]) - avctx->release_buffer(avctx, c->last); - avcodec_free_frame(&c->pic); - avcodec_free_frame(&c->last); + av_frame_free(&c->last); free_bundles(c); return 0; @@ -1336,12 +1345,12 @@ static av_cold int decode_end(AVCodecContext *avctx) AVCodec ff_bink_decoder = { .name = "binkvideo", + .long_name = NULL_IF_CONFIG_SMALL("Bink video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_BINKVIDEO, .priv_data_size = sizeof(BinkContext), .init = decode_init, .close = decode_end, .decode = decode_frame, - .long_name = NULL_IF_CONFIG_SMALL("Bink video"), - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, };