summaryrefslogtreecommitdiff
path: root/libavcodec/ivi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/ivi.c')
-rw-r--r--libavcodec/ivi.c189
1 files changed, 125 insertions, 64 deletions
diff --git a/libavcodec/ivi.c b/libavcodec/ivi.c
index 2ff4824c92..71bf0e6e1c 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,15 +432,25 @@ 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];
+
+ if (band->tiles) {
+ int t;
+ for (t = 0; t < band->num_tiles; t++) {
+ av_freep(&band->tiles[t].mbs);
+ }
+ }
+
x_tiles = IVI_NUM_TILES(band->width, t_width);
y_tiles = IVI_NUM_TILES(band->height, t_height);
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 +473,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 +499,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 +508,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 +544,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 +592,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 +614,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 +656,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 +723,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 +752,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 +819,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++;
@@ -891,8 +921,16 @@ static void ivi_output_plane(IVIPlaneDesc *plane, uint8_t *dst, ptrdiff_t dst_pi
return;
for (y = 0; y < plane->height; y++) {
- for (x = 0; x < plane->width; x++)
- dst[x] = av_clip_uint8(src[x] + 128);
+ int m = 0;
+ int w = plane->width;
+ for (x = 0; x < w; x++) {
+ int t = src[x] + 128;
+ dst[x] = t;
+ m |= t;
+ }
+ if (m & ~255)
+ for (x = 0; x < w; x++)
+ dst[x] = av_clip_uint8(src[x] + 128);
src += pitch;
dst += dst_pitch;
}
@@ -924,7 +962,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 +984,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 +1000,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 +1008,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 +1044,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 +1062,7 @@ static int decode_band(IVI45DecContext *ctx,
}
#endif
- bitstream_align(&ctx->bc);
+ align_get_bits(&ctx->gb);
return result;
}
@@ -1029,7 +1076,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 +1117,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 +1128,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 +1138,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 +1175,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 +1222,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;