summaryrefslogtreecommitdiff
path: root/libavcodec/indeo3.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/indeo3.c')
-rw-r--r--libavcodec/indeo3.c99
1 files changed, 64 insertions, 35 deletions
diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c
index 261c651b52..a8206dbb00 100644
--- a/libavcodec/indeo3.c
+++ b/libavcodec/indeo3.c
@@ -2,20 +2,20 @@
* Indeo Video v3 compatible decoder
* Copyright (c) 2009 - 2011 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
*/
@@ -149,14 +149,11 @@ static av_cold void build_requant_tab(void)
static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx,
- AVCodecContext *avctx)
+ AVCodecContext *avctx, int luma_width, int luma_height)
{
- int p, luma_width, luma_height, chroma_width, chroma_height;
+ int p, chroma_width, chroma_height;
int luma_pitch, chroma_pitch, luma_size, chroma_size;
- luma_width = ctx->width;
- luma_height = ctx->height;
-
if (luma_width < 16 || luma_width > 640 ||
luma_height < 16 || luma_height > 480 ||
luma_width & 3 || luma_height & 3) {
@@ -165,6 +162,9 @@ static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx,
return AVERROR_INVALIDDATA;
}
+ ctx->width = luma_width ;
+ ctx->height = luma_height;
+
chroma_width = FFALIGN(luma_width >> 2, 4);
chroma_height = FFALIGN(luma_height >> 2, 4);
@@ -207,6 +207,9 @@ static av_cold void free_frame_buffers(Indeo3DecodeContext *ctx)
{
int p;
+ ctx->width=
+ ctx->height= 0;
+
for (p = 0; p < 3; p++) {
av_freep(&ctx->planes[p].buffers[0]);
av_freep(&ctx->planes[p].buffers[1]);
@@ -231,8 +234,11 @@ static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell)
/* setup output and reference pointers */
offset_dst = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2);
dst = plane->pixels[ctx->buf_sel] + offset_dst;
+ if(cell->mv_ptr){
mv_y = cell->mv_ptr[0];
mv_x = cell->mv_ptr[1];
+ }else
+ mv_x= mv_y= 0;
offset = offset_dst + mv_y * plane->pitch + mv_x;
src = plane->pixels[ctx->buf_sel ^ 1] + offset;
@@ -579,6 +585,19 @@ static int decode_cell(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
/* setup output and reference pointers */
offset = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2);
block = plane->pixels[ctx->buf_sel] + offset;
+
+ if (cell->mv_ptr) {
+ mv_y = cell->mv_ptr[0];
+ mv_x = cell->mv_ptr[1];
+ if ( mv_x + 4*cell->xpos < 0
+ || mv_y + 4*cell->ypos < 0
+ || mv_x + 4*cell->xpos + 4*cell->width > plane->width
+ || mv_y + 4*cell->ypos + 4*cell->height > plane->height) {
+ av_log(avctx, AV_LOG_ERROR, "motion vector %d %d outside reference\n", mv_x + 4*cell->xpos, mv_y + 4*cell->ypos);
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
if (!cell->mv_ptr) {
/* use previous line as reference for INTRA cells */
ref_block = block - plane->pitch;
@@ -621,7 +640,7 @@ static int decode_cell(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
/* of the predicted cell in order to avoid overflows. */
if (vq_index >= 8 && ref_block) {
for (x = 0; x < cell->width << 2; x++)
- ref_block[x] = requant_tab[vq_index & 7][ref_block[x]];
+ ref_block[x] = requant_tab[vq_index & 7][ref_block[x] & 127];
}
error = IV3_NOERR;
@@ -722,6 +741,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
{
Cell curr_cell;
int bytes_used;
+ int mv_x, mv_y;
if (depth <= 0) {
av_log(avctx, AV_LOG_ERROR, "Stack overflow (corrupted binary tree)!\n");
@@ -747,7 +767,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
return AVERROR_INVALIDDATA;
}
- while (1) { /* loop until return */
+ while (get_bits_left(&ctx->gb) >= 2) { /* loop until return */
RESYNC_BITSTREAM;
switch (code = get_bits(&ctx->gb, 2)) {
case H_SPLIT:
@@ -772,6 +792,17 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
CHECK_CELL
if (!curr_cell.mv_ptr)
return AVERROR_INVALIDDATA;
+
+ mv_y = curr_cell.mv_ptr[0];
+ mv_x = curr_cell.mv_ptr[1];
+ if ( mv_x + 4*curr_cell.xpos < 0
+ || mv_y + 4*curr_cell.ypos < 0
+ || mv_x + 4*curr_cell.xpos + 4*curr_cell.width > plane->width
+ || mv_y + 4*curr_cell.ypos + 4*curr_cell.height > plane->height) {
+ av_log(avctx, AV_LOG_ERROR, "motion vector %d %d outside reference\n", mv_x + 4*curr_cell.xpos, mv_y + 4*curr_cell.ypos);
+ return AVERROR_INVALIDDATA;
+ }
+
copy_cell(ctx, plane, &curr_cell);
return 0;
}
@@ -782,6 +813,10 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
/* get motion vector index and setup the pointer to the mv set */
if (!ctx->need_resync)
ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3];
+ if (ctx->next_cell_data >= ctx->last_byte) {
+ av_log(avctx, AV_LOG_ERROR, "motion vector out of array\n");
+ return AVERROR_INVALIDDATA;
+ }
mv_idx = *(ctx->next_cell_data++);
if (mv_idx >= ctx->num_vectors) {
av_log(avctx, AV_LOG_ERROR, "motion vector index out of range\n");
@@ -808,7 +843,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
}
}//while
- return 0;
+ return AVERROR_INVALIDDATA;
}
@@ -821,13 +856,13 @@ static int decode_plane(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
/* each plane data starts with mc_vector_count field, */
/* an optional array of motion vectors followed by the vq data */
- num_vectors = bytestream_get_le32(&data);
+ num_vectors = bytestream_get_le32(&data); data_size -= 4;
if (num_vectors > 256) {
av_log(ctx->avctx, AV_LOG_ERROR,
"Read invalid number of motion vectors %d\n", num_vectors);
return AVERROR_INVALIDDATA;
}
- if (num_vectors * 2 >= data_size)
+ if (num_vectors * 2 > data_size)
return AVERROR_INVALIDDATA;
ctx->num_vectors = num_vectors;
@@ -838,7 +873,7 @@ static int decode_plane(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
ctx->skip_bits = 0;
ctx->need_resync = 0;
- ctx->last_byte = data + data_size - 1;
+ ctx->last_byte = data + data_size;
/* initialize the 1st cell and set its dimensions to whole plane */
curr_cell.xpos = curr_cell.ypos = 0;
@@ -875,6 +910,7 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
/* parse the bitstream header */
bs_hdr = buf_ptr;
+ buf_size -= 16;
if (bytestream_get_le16(&buf_ptr) != 32) {
av_log(avctx, AV_LOG_ERROR, "Unsupported codec version!\n");
@@ -911,12 +947,8 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
"Invalid picture dimensions: %d x %d!\n", width, height);
return AVERROR_INVALIDDATA;
}
-
- ctx->width = width;
- ctx->height = height;
-
free_frame_buffers(ctx);
- if ((res = allocate_frame_buffers(ctx, avctx)) < 0)
+ if ((res = allocate_frame_buffers(ctx, avctx, width, height)) < 0)
return res;
avcodec_set_dimensions(avctx, width, height);
}
@@ -1011,17 +1043,14 @@ static av_cold int decode_init(AVCodecContext *avctx)
Indeo3DecodeContext *ctx = avctx->priv_data;
ctx->avctx = avctx;
- ctx->width = avctx->width;
- ctx->height = avctx->height;
avctx->pix_fmt = AV_PIX_FMT_YUV410P;
+ avcodec_get_frame_defaults(&ctx->frame);
build_requant_tab();
ff_dsputil_init(&ctx->dsp, avctx);
- allocate_frame_buffers(ctx, avctx);
-
- return 0;
+ return allocate_frame_buffers(ctx, avctx, avctx->width, avctx->height);
}
@@ -1056,6 +1085,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
/* use BS_BUFFER flag for buffer switching */
ctx->buf_sel = (ctx->frame_flags >> BS_BUFFER) & 1;
+ if (ctx->frame.data[0])
+ avctx->release_buffer(avctx, &ctx->frame);
+
+ ctx->frame.reference = 0;
+ if ((res = ff_get_buffer(avctx, &ctx->frame)) < 0) {
+ av_log(ctx->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return res;
+ }
+
/* decode luma plane */
if ((res = decode_plane(ctx, avctx, ctx->planes, ctx->y_data_ptr, ctx->y_data_size, 40)))
return res;
@@ -1067,15 +1105,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
if ((res = decode_plane(ctx, avctx, &ctx->planes[2], ctx->v_data_ptr, ctx->v_data_size, 10)))
return res;
- if (ctx->frame.data[0])
- avctx->release_buffer(avctx, &ctx->frame);
-
- ctx->frame.reference = 0;
- if ((res = ff_get_buffer(avctx, &ctx->frame)) < 0) {
- av_log(ctx->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
- return res;
- }
-
output_plane(&ctx->planes[0], ctx->buf_sel,
ctx->frame.data[0], ctx->frame.linesize[0],
avctx->height);
@@ -1113,6 +1142,6 @@ AVCodec ff_indeo3_decoder = {
.init = decode_init,
.close = decode_close,
.decode = decode_frame,
- .capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"),
+ .capabilities = CODEC_CAP_DR1,
};