diff options
Diffstat (limited to 'libavcodec/ivi.c')
-rw-r--r-- | libavcodec/ivi.c | 169 |
1 files changed, 107 insertions, 62 deletions
diff --git a/libavcodec/ivi.c b/libavcodec/ivi.c index 2ff4824..cea40d8 100644 --- a/libavcodec/ivi.c +++ b/libavcodec/ivi.c @@ -3,20 +3,20 @@ * * Copyright (c) 2009 Maxim Poliakovski * - * 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 */ @@ -29,11 +29,12 @@ #include <inttypes.h> #include "libavutil/attributes.h" +#include "libavutil/imgutils.h" #include "libavutil/timer.h" #define BITSTREAM_READER_LE #include "avcodec.h" -#include "bitstream.h" +#include "get_bits.h" #include "internal.h" #include "mathops.h" #include "ivi.h" @@ -88,12 +89,9 @@ static int ivi_mc(IVIBandDesc *band, ivi_mc_func mc, ivi_mc_avg_func mc_avg, int ref_size = (mc_type > 1) * band->pitch + (mc_type & 1); if (mc_type != -1) { - if (offs < 0 || ref_offs < 0 || !band->ref_buf) - return AVERROR_INVALIDDATA; - if (buf_size - min_size < offs) - return AVERROR_INVALIDDATA; - if (buf_size - min_size - ref_size < ref_offs) - return AVERROR_INVALIDDATA; + av_assert0(offs >= 0 && ref_offs >= 0 && band->ref_buf); + av_assert0(buf_size - min_size >= offs); + av_assert0(buf_size - min_size - ref_size >= ref_offs); } if (mc_type2 == -1) { @@ -137,7 +135,7 @@ static uint16_t inv_bits(uint16_t val, int nbits) /* * Generate a huffman codebook from the given descriptor - * and convert it into the Libav VLC table. + * and convert it into the FFmpeg VLC table. * * @param[in] cb pointer to codebook descriptor * @param[out] vlc where to place the generated VLC table @@ -225,7 +223,7 @@ static int ivi_huff_desc_cmp(const IVIHuffDesc *desc1, memcmp(desc1->xbits, desc2->xbits, desc1->num_rows); } -int ff_ivi_dec_huff_desc(BitstreamContext *bc, int desc_coded, int which_tab, +int ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab, IVIHuffTab *huff_tab, AVCodecContext *avctx) { int i, result; @@ -238,20 +236,20 @@ int ff_ivi_dec_huff_desc(BitstreamContext *bc, int desc_coded, int which_tab, return 0; } - huff_tab->tab_sel = bitstream_read(bc, 3); + huff_tab->tab_sel = get_bits(gb, 3); if (huff_tab->tab_sel == 7) { /* custom huffman table (explicitly encoded) */ - new_huff.num_rows = bitstream_read(bc, 4); + new_huff.num_rows = get_bits(gb, 4); if (!new_huff.num_rows) { av_log(avctx, AV_LOG_ERROR, "Empty custom Huffman table!\n"); return AVERROR_INVALIDDATA; } for (i = 0; i < new_huff.num_rows; i++) - new_huff.xbits[i] = bitstream_read(bc, 4); + new_huff.xbits[i] = get_bits(gb, 4); /* Have we got the same custom table? Rebuild if not. */ - if (ivi_huff_desc_cmp(&new_huff, &huff_tab->cust_desc)) { + if (ivi_huff_desc_cmp(&new_huff, &huff_tab->cust_desc) || !huff_tab->cust_tab.table) { ivi_huff_desc_copy(&huff_tab->cust_desc, &new_huff); if (huff_tab->cust_tab.table) @@ -286,6 +284,7 @@ static av_cold void ivi_free_buffers(IVIPlaneDesc *planes) int p, b, t; for (p = 0; p < 3; p++) { + if (planes[p].bands) for (b = 0; b < planes[p].num_bands; b++) { av_freep(&planes[p].bands[b].bufs[0]); av_freep(&planes[p].bands[b].bufs[1]); @@ -303,7 +302,7 @@ static av_cold void ivi_free_buffers(IVIPlaneDesc *planes) } } -av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg, +av_cold int ff_ivi_init_planes(AVCodecContext *avctx, IVIPlaneDesc *planes, const IVIPicConfig *cfg, int is_indeo4) { int p, b; @@ -313,7 +312,7 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg, ivi_free_buffers(planes); - if (cfg->pic_width < 1 || cfg->pic_height < 1 || + if (av_image_check_size2(cfg->pic_width, cfg->pic_height, avctx->max_pixels, AV_PIX_FMT_YUV410P, 0, avctx) < 0 || cfg->luma_bands < 1 || cfg->chroma_bands < 1) return AVERROR_INVALIDDATA; @@ -328,7 +327,7 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg, planes[1].num_bands = planes[2].num_bands = cfg->chroma_bands; for (p = 0; p < 3; p++) { - planes[p].bands = av_mallocz(planes[p].num_bands * sizeof(IVIBandDesc)); + planes[p].bands = av_mallocz_array(planes[p].num_bands, sizeof(IVIBandDesc)); if (!planes[p].bands) return AVERROR(ENOMEM); @@ -357,6 +356,7 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg, band->aheight = height_aligned; band->bufs[0] = av_mallocz(buf_size); band->bufs[1] = av_mallocz(buf_size); + band->bufsize = buf_size/2; if (!band->bufs[0] || !band->bufs[1]) return AVERROR(ENOMEM); @@ -398,14 +398,16 @@ static int ivi_init_tiles(IVIBandDesc *band, IVITile *ref_tile, band->mb_size); av_freep(&tile->mbs); - tile->mbs = av_malloc(tile->num_MBs * sizeof(IVIMbInfo)); + tile->mbs = av_mallocz_array(tile->num_MBs, sizeof(IVIMbInfo)); if (!tile->mbs) return AVERROR(ENOMEM); tile->ref_mbs = 0; if (p || b) { - if (tile->num_MBs != ref_tile->num_MBs) + if (tile->num_MBs != ref_tile->num_MBs) { + av_log(NULL, AV_LOG_DEBUG, "ref_tile mismatch\n"); return AVERROR_INVALIDDATA; + } tile->ref_mbs = ref_tile->mbs; ref_tile++; } @@ -430,6 +432,8 @@ av_cold int ff_ivi_init_tiles(IVIPlaneDesc *planes, t_width >>= 1; t_height >>= 1; } + if(t_width<=0 || t_height<=0) + return AVERROR(EINVAL); for (b = 0; b < planes[p].num_bands; b++) { band = &planes[p].bands[b]; @@ -438,7 +442,7 @@ av_cold int ff_ivi_init_tiles(IVIPlaneDesc *planes, band->num_tiles = x_tiles * y_tiles; av_freep(&band->tiles); - band->tiles = av_mallocz(band->num_tiles * sizeof(IVITile)); + band->tiles = av_mallocz_array(band->num_tiles, sizeof(IVITile)); if (!band->tiles) return AVERROR(ENOMEM); @@ -461,22 +465,22 @@ av_cold int ff_ivi_init_tiles(IVIPlaneDesc *planes, * if (tile_data_size >= 255) than this field four is byte long: 0xFF X1 X2 X3 * where X1-X3 is size of the tile data * - * @param[in,out] bc the Bitstream context + * @param[in,out] gb the GetBit context * @return size of the tile data in bytes */ -static int ivi_dec_tile_data_size(BitstreamContext *bc) +static int ivi_dec_tile_data_size(GetBitContext *gb) { int len; len = 0; - if (bitstream_read_bit(bc)) { - len = bitstream_read(bc, 8); + if (get_bits1(gb)) { + len = get_bits(gb, 8); if (len == 255) - len = bitstream_read(bc, 24); + len = get_bits_long(gb, 24); } /* align the bitstream reader on the byte boundary */ - bitstream_align(bc); + align_get_bits(gb); return len; } @@ -487,10 +491,6 @@ static int ivi_dc_transform(IVIBandDesc *band, int *prev_dc, int buf_offs, int buf_size = band->pitch * band->aheight - buf_offs; int min_size = (blk_size - 1) * band->pitch + blk_size; - if (!band->dc_transform) - return 0; - - if (min_size > buf_size) return AVERROR_INVALIDDATA; @@ -500,7 +500,7 @@ static int ivi_dc_transform(IVIBandDesc *band, int *prev_dc, int buf_offs, return 0; } -static int ivi_decode_coded_blocks(BitstreamContext *bc, IVIBandDesc *band, +static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, ivi_mc_func mc, ivi_mc_avg_func mc_avg, int mv_x, int mv_y, int mv_x2, int mv_y2, @@ -536,15 +536,16 @@ static int ivi_decode_coded_blocks(BitstreamContext *bc, IVIBandDesc *band, /* zero column flags */ memset(col_flags, 0, sizeof(col_flags)); while (scan_pos <= num_coeffs) { - sym = bitstream_read_vlc(bc, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); + sym = get_vlc2(gb, band->blk_vlc.tab->table, + IVI_VLC_BITS, 1); if (sym == rvmap->eob_sym) break; /* End of block */ /* Escape - run/val explicitly coded using 3 vlc codes */ if (sym == rvmap->esc_sym) { - run = bitstream_read_vlc(bc, band->blk_vlc.tab->table, IVI_VLC_BITS, 1) + 1; - lo = bitstream_read_vlc(bc, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); - hi = bitstream_read_vlc(bc, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); + run = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1) + 1; + lo = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); + hi = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); /* merge them and convert into signed val */ val = IVI_TOSIGNED((hi << 6) | lo); } else { @@ -583,6 +584,11 @@ static int ivi_decode_coded_blocks(BitstreamContext *bc, IVIBandDesc *band, col_flags[0] |= !!*prev_dc; } + if(band->transform_size > band->blk_size){ + av_log(NULL, AV_LOG_ERROR, "Too large transform\n"); + return AVERROR_INVALIDDATA; + } + /* apply inverse transform */ band->inv_transform(trvec, band->buf + offs, band->pitch, col_flags); @@ -600,12 +606,12 @@ static int ivi_decode_coded_blocks(BitstreamContext *bc, IVIBandDesc *band, * dequantize them, apply inverse transform and motion compensation * in order to reconstruct the picture. * - * @param[in,out] bc the Bitstream context + * @param[in,out] gb the GetBit context * @param[in] band pointer to the band descriptor * @param[in] tile pointer to the tile descriptor * @return result code: 0 - OK, -1 = error (corrupted blocks data) */ -static int ivi_decode_blocks(BitstreamContext *bc, IVIBandDesc *band, +static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile, AVCodecContext *avctx) { int mbn, blk, num_blocks, blk_size, ret, is_intra; @@ -642,7 +648,7 @@ static int ivi_decode_blocks(BitstreamContext *bc, IVIBandDesc *band, quant = band->glob_quant + mb->q_delta; if (avctx->codec_id == AV_CODEC_ID_INDEO4) - quant = av_clip(quant, 0, 31); + quant = av_clip_uintp2(quant, 5); else quant = av_clip(quant, 0, 23); @@ -709,7 +715,7 @@ static int ivi_decode_blocks(BitstreamContext *bc, IVIBandDesc *band, } if (cbp & 1) { /* block coded ? */ - ret = ivi_decode_coded_blocks(bc, band, mc_with_delta_func, + ret = ivi_decode_coded_blocks(gb, band, mc_with_delta_func, mc_avg_with_delta_func, mv_x, mv_y, mv_x2, mv_y2, &prev_dc, is_intra, @@ -738,7 +744,7 @@ static int ivi_decode_blocks(BitstreamContext *bc, IVIBandDesc *band, }// for blk }// for mbn - bitstream_align(bc); + align_get_bits(gb); return 0; } @@ -805,6 +811,22 @@ static int ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, mb->mv_y = ref_mb->mv_y; } need_mc |= mb->mv_x || mb->mv_y; /* tracking non-zero motion vectors */ + { + int dmv_x, dmv_y, cx, cy; + + dmv_x = mb->mv_x >> band->is_halfpel; + dmv_y = mb->mv_y >> band->is_halfpel; + cx = mb->mv_x & band->is_halfpel; + cy = mb->mv_y & band->is_halfpel; + + if ( mb->xpos + dmv_x < 0 + || mb->xpos + dmv_x + band->mb_size + cx > band->pitch + || mb->ypos + dmv_y < 0 + || mb->ypos + dmv_y + band->mb_size + cy > band->aheight) { + av_log(avctx, AV_LOG_ERROR, "MV out of bounds\n"); + return AVERROR_INVALIDDATA; + } + } } mb++; @@ -924,7 +946,7 @@ static int decode_band(IVI45DecContext *ctx, band->ref_buf = band->bufs[ctx->ref_buf]; band->b_ref_buf = 0; } - band->data_ptr = ctx->frame_data + (bitstream_tell(&ctx->bc) >> 3); + band->data_ptr = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3); result = ctx->decode_band_hdr(ctx, band, avctx); if (result) { @@ -946,9 +968,13 @@ static int decode_band(IVI45DecContext *ctx, idx2 = band->corr[i * 2 + 1]; FFSWAP(uint8_t, band->rv_map->runtab[idx1], band->rv_map->runtab[idx2]); FFSWAP(int16_t, band->rv_map->valtab[idx1], band->rv_map->valtab[idx2]); + if (idx1 == band->rv_map->eob_sym || idx2 == band->rv_map->eob_sym) + band->rv_map->eob_sym ^= idx1 ^ idx2; + if (idx1 == band->rv_map->esc_sym || idx2 == band->rv_map->esc_sym) + band->rv_map->esc_sym ^= idx1 ^ idx2; } - pos = bitstream_tell(&ctx->bc); + pos = get_bits_count(&ctx->gb); for (t = 0; t < band->num_tiles; t++) { tile = &band->tiles[t]; @@ -958,7 +984,7 @@ static int decode_band(IVI45DecContext *ctx, band->mb_size, tile->mb_size); return AVERROR_INVALIDDATA; } - tile->is_empty = bitstream_read_bit(&ctx->bc); + tile->is_empty = get_bits1(&ctx->gb); if (tile->is_empty) { result = ivi_process_empty_tile(avctx, band, tile, (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3)); @@ -966,24 +992,25 @@ static int decode_band(IVI45DecContext *ctx, break; ff_dlog(avctx, "Empty tile encountered!\n"); } else { - tile->data_size = ivi_dec_tile_data_size(&ctx->bc); + tile->data_size = ivi_dec_tile_data_size(&ctx->gb); if (!tile->data_size) { av_log(avctx, AV_LOG_ERROR, "Tile data size is zero!\n"); - return AVERROR_INVALIDDATA; + result = AVERROR_INVALIDDATA; + break; } result = ctx->decode_mb_info(ctx, band, tile, avctx); if (result < 0) break; - result = ivi_decode_blocks(&ctx->bc, band, tile, avctx); + result = ivi_decode_blocks(&ctx->gb, band, tile, avctx); if (result < 0) { av_log(avctx, AV_LOG_ERROR, "Corrupted tile data encountered!\n"); break; } - if (((bitstream_tell(&ctx->bc) - pos) >> 3) != tile->data_size) { + if (((get_bits_count(&ctx->gb) - pos) >> 3) != tile->data_size) { av_log(avctx, AV_LOG_ERROR, "Tile data_size mismatch!\n"); result = AVERROR_INVALIDDATA; @@ -1001,6 +1028,10 @@ static int decode_band(IVI45DecContext *ctx, idx2 = band->corr[i*2+1]; FFSWAP(uint8_t, band->rv_map->runtab[idx1], band->rv_map->runtab[idx2]); FFSWAP(int16_t, band->rv_map->valtab[idx1], band->rv_map->valtab[idx2]); + if (idx1 == band->rv_map->eob_sym || idx2 == band->rv_map->eob_sym) + band->rv_map->eob_sym ^= idx1 ^ idx2; + if (idx1 == band->rv_map->esc_sym || idx2 == band->rv_map->esc_sym) + band->rv_map->esc_sym ^= idx1 ^ idx2; } #ifdef DEBUG @@ -1015,7 +1046,7 @@ static int decode_band(IVI45DecContext *ctx, } #endif - bitstream_align(&ctx->bc); + align_get_bits(&ctx->gb); return result; } @@ -1029,7 +1060,9 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int buf_size = avpkt->size; int result, p, b; - bitstream_init8(&ctx->bc, buf, buf_size); + result = init_get_bits8(&ctx->gb, buf, buf_size); + if (result < 0) + return result; ctx->frame_data = buf; ctx->frame_size = buf_size; @@ -1068,6 +1101,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, //{ START_TIMER; if (ctx->is_nonnull_frame(ctx)) { + ctx->buf_invalid[ctx->dst_buf] = 1; for (p = 0; p < 3; p++) { for (b = 0; b < ctx->planes[p].num_bands; b++) { result = decode_band(ctx, &ctx->planes[p].bands[b], avctx); @@ -1078,6 +1112,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } } } + ctx->buf_invalid[ctx->dst_buf] = 0; } else { if (ctx->is_scalable) return AVERROR_INVALIDDATA; @@ -1087,17 +1122,20 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; } } + if (ctx->buf_invalid[ctx->dst_buf]) + return -1; //STOP_TIMER("decode_planes"); } + if (!ctx->is_nonnull_frame(ctx)) + return buf_size; + result = ff_set_dimensions(avctx, ctx->planes[0].width, ctx->planes[0].height); if (result < 0) return result; - if ((result = ff_get_buffer(avctx, frame, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + if ((result = ff_get_buffer(avctx, frame, 0)) < 0) return result; - } if (ctx->is_scalable) { if (ctx->is_indeo4) @@ -1121,14 +1159,18 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_INTRA) { int left; - while (bitstream_read(&ctx->bc, 8)); // skip version string - left = bitstream_tell(&ctx->bc) & 0x18; - bitstream_skip(&ctx->bc, 64 - left); - if (bitstream_bits_left(&ctx->bc) > 18 && - bitstream_peek(&ctx->bc, 21) == 0xBFFF8) { // syncheader + inter type + // skip version string + while (get_bits(&ctx->gb, 8)) { + if (get_bits_left(&ctx->gb) < 8) + return AVERROR_INVALIDDATA; + } + left = get_bits_count(&ctx->gb) & 0x18; + skip_bits_long(&ctx->gb, 64 - left); + if (get_bits_left(&ctx->gb) > 18 && + show_bits_long(&ctx->gb, 21) == 0xBFFF8) { // syncheader + inter type AVPacket pkt; - pkt.data = avpkt->data + (bitstream_tell(&ctx->bc) >> 3); - pkt.size = bitstream_bits_left(&ctx->bc) >> 3; + pkt.data = avpkt->data + (get_bits_count(&ctx->gb) >> 3); + pkt.size = get_bits_left(&ctx->gb) >> 3; ff_ivi_decode_frame(avctx, ctx->p_frame, &ctx->got_p_frame, &pkt); } } @@ -1164,6 +1206,9 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx) if (ctx->mb_vlc.cust_tab.table) ff_free_vlc(&ctx->mb_vlc.cust_tab); + if (ctx->blk_vlc.cust_tab.table) + ff_free_vlc(&ctx->blk_vlc.cust_tab); + av_frame_free(&ctx->p_frame); return 0; |