diff options
Diffstat (limited to 'libavcodec/indeo3.c')
-rw-r--r-- | libavcodec/indeo3.c | 97 |
1 files changed, 63 insertions, 34 deletions
diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index e519361aa2..fd302a76da 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 */ @@ -32,6 +32,7 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "copy_block.h" #include "dsputil.h" #include "bytestream.h" #include "get_bits.h" @@ -148,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) { @@ -164,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); @@ -206,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]); @@ -230,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; @@ -253,7 +260,7 @@ static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell) } if (w >= 1) { - ctx->dsp.put_no_rnd_pixels_tab[2][0](dst, src, plane->pitch, h); + copy_block4(dst, src, plane->pitch, plane->pitch, h); w--; src += 4; dst += 4; @@ -323,7 +330,7 @@ if (*data_ptr >= last_ptr) \ #define RLE_BLOCK_COPY \ if (cell->mv_ptr || !skip_flag) \ - ctx->dsp.put_pixels_tab[2][0](dst, ref, row_offset, 4 << v_zoom) + copy_block4(dst, ref, row_offset, row_offset, 4 << v_zoom) #define RLE_BLOCK_COPY_8 \ pix64 = AV_RN64A(ref);\ @@ -335,7 +342,7 @@ if (*data_ptr >= last_ptr) \ fill_64(dst, pix64, 8, row_offset) #define RLE_LINES_COPY \ - ctx->dsp.put_pixels_tab[2][0](dst, ref, row_offset, num_lines << v_zoom) + copy_block4(dst, ref, row_offset, row_offset, num_lines << v_zoom) #define RLE_LINES_COPY_M10 \ pix64 = AV_RN64A(ref);\ @@ -579,6 +586,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 +641,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; @@ -724,6 +744,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"); @@ -749,7 +770,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: @@ -774,6 +795,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; } @@ -784,6 +816,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"); @@ -810,7 +846,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, } }//while - return 0; + return AVERROR_INVALIDDATA; } @@ -823,13 +859,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; @@ -840,7 +876,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; @@ -877,6 +913,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"); @@ -913,12 +950,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); } @@ -1013,17 +1046,13 @@ 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; 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); } @@ -1059,6 +1088,11 @@ 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 ((res = ff_get_buffer(avctx, frame, 0)) < 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; @@ -1070,11 +1104,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 ((res = ff_get_buffer(avctx, frame, 0)) < 0) { - av_log(ctx->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return res; - } - output_plane(&ctx->planes[0], ctx->buf_sel, frame->data[0], frame->linesize[0], avctx->height); @@ -1106,6 +1135,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, }; |