diff options
Diffstat (limited to 'libavcodec/indeo3.c')
-rw-r--r-- | libavcodec/indeo3.c | 99 |
1 files changed, 53 insertions, 46 deletions
diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index a9c02b2889..aa9c30aca9 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 "bytestream.h" #include "get_bits.h" #include "hpeldsp.h" @@ -147,15 +148,26 @@ static av_cold void build_requant_tab(void) } +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]); + ctx->planes[p].pixels[0] = ctx->planes[p].pixels[1] = 0; + } +} + + 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 +176,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); @@ -187,6 +202,11 @@ static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx, ctx->planes[p].buffers[0] = av_malloc(!p ? luma_size : chroma_size); ctx->planes[p].buffers[1] = av_malloc(!p ? luma_size : chroma_size); + if (!ctx->planes[p].buffers[0] || !ctx->planes[p].buffers[1]) { + free_frame_buffers(ctx); + return AVERROR(ENOMEM); + } + /* fill the INTRA prediction lines with the middle pixel value = 64 */ memset(ctx->planes[p].buffers[0], 0x40, ctx->planes[p].pitch); memset(ctx->planes[p].buffers[1], 0x40, ctx->planes[p].pitch); @@ -201,19 +221,6 @@ static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx, return 0; } - -static av_cold void free_frame_buffers(Indeo3DecodeContext *ctx) -{ - int p; - - for (p = 0; p < 3; p++) { - av_freep(&ctx->planes[p].buffers[0]); - av_freep(&ctx->planes[p].buffers[1]); - ctx->planes[p].pixels[0] = ctx->planes[p].pixels[1] = 0; - } -} - - /** * Copy pixels of the cell(x + mv_x, y + mv_y) from the previous frame into * the cell(x, y) in the current frame. @@ -230,8 +237,11 @@ static int 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; /* -1 because there is an extra line on top for prediction */ if ((cell->ypos << 2) + mv_y < -1 || (cell->xpos << 2) + mv_x < 0 || @@ -333,7 +343,7 @@ if (*data_ptr >= last_ptr) \ #define RLE_BLOCK_COPY \ if (cell->mv_ptr || !skip_flag) \ - ctx->hdsp.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_RN64(ref);\ @@ -345,7 +355,7 @@ if (*data_ptr >= last_ptr) \ fill_64(dst, pix64, 8, row_offset) #define RLE_LINES_COPY \ - ctx->hdsp.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_RN64(ref);\ @@ -589,6 +599,7 @@ 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) { /* use previous line as reference for INTRA cells */ ref_block = block - plane->pitch; @@ -643,7 +654,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; @@ -771,7 +782,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: @@ -796,6 +807,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, CHECK_CELL if (!curr_cell.mv_ptr) return AVERROR_INVALIDDATA; + ret = copy_cell(ctx, plane, &curr_cell); return ret; } @@ -806,6 +818,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"); @@ -832,7 +848,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, } }//while - return 0; + return AVERROR_INVALIDDATA; } @@ -845,13 +861,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; @@ -862,7 +878,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; @@ -937,14 +953,11 @@ 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; - ff_set_dimensions(avctx, width, height); + if ((res = ff_set_dimensions(avctx, width, height)) < 0) + return res; } y_offset = bytestream2_get_le32(&gb); @@ -1039,17 +1052,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_hpeldsp_init(&ctx->hdsp, avctx->flags); - allocate_frame_buffers(ctx, avctx); - - return 0; + return allocate_frame_buffers(ctx, avctx, avctx->width, avctx->height); } @@ -1085,6 +1094,9 @@ 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) + return res; + /* decode luma plane */ if ((res = decode_plane(ctx, avctx, ctx->planes, ctx->y_data_ptr, ctx->y_data_size, 40))) return res; @@ -1096,11 +1108,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); |