diff options
Diffstat (limited to 'libavcodec/indeo3.c')
-rw-r--r-- | libavcodec/indeo3.c | 123 |
1 files changed, 66 insertions, 57 deletions
diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index 22a072d..71d478c 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 */ @@ -31,10 +31,10 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" - #include "avcodec.h" -#include "bitstream.h" +#include "copy_block.h" #include "bytestream.h" +#include "get_bits.h" #include "hpeldsp.h" #include "internal.h" @@ -84,7 +84,7 @@ typedef struct Indeo3DecodeContext { AVCodecContext *avctx; HpelDSPContext hdsp; - BitstreamContext bc; + GetBitContext gb; int need_resync; int skip_bits; const uint8_t *next_cell_data; @@ -94,7 +94,7 @@ typedef struct Indeo3DecodeContext { int16_t width, height; uint32_t frame_num; ///< current frame number (zero-based) - uint32_t data_size; ///< size of the frame data in bytes + int data_size; ///< size of the frame data in bytes uint16_t frame_flags; ///< frame properties uint8_t cb_offset; ///< needed for selecting VQ tables uint8_t buf_sel; ///< active frame buffer: 0 - primary, 1 -secondary @@ -148,16 +148,27 @@ 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_size, chroma_size; ptrdiff_t luma_pitch, chroma_pitch; - 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) { @@ -166,6 +177,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); @@ -189,6 +203,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); @@ -203,19 +222,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. @@ -232,8 +238,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 || @@ -335,7 +344,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);\ @@ -347,7 +356,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);\ @@ -590,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; @@ -644,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; @@ -726,8 +736,8 @@ enum { ctx->need_resync = 1 #define RESYNC_BITSTREAM \ - if (ctx->need_resync && !(bitstream_tell(&ctx->bc) & 7)) { \ - bitstream_skip(&ctx->bc, ctx->skip_bits); \ + if (ctx->need_resync && !(get_bits_count(&ctx->gb) & 7)) { \ + skip_bits_long(&ctx->gb, ctx->skip_bits); \ ctx->skip_bits = 0; \ ctx->need_resync = 0; \ } @@ -772,9 +782,9 @@ 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 = bitstream_read(&ctx->bc, 2)) { + switch (code = get_bits(&ctx->gb, 2)) { case H_SPLIT: case V_SPLIT: if (parse_bintree(ctx, avctx, plane, code, &curr_cell, depth - 1, strip_width)) @@ -786,7 +796,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, curr_cell.tree = 1; /* enter the VQ tree */ } else { /* VQ tree NULL code */ RESYNC_BITSTREAM; - code = bitstream_read(&ctx->bc, 2); + code = get_bits(&ctx->gb, 2); if (code >= 2) { av_log(avctx, AV_LOG_ERROR, "Invalid VQ_NULL code: %d\n", code); return AVERROR_INVALIDDATA; @@ -797,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,7 +817,11 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, unsigned mv_idx; /* get motion vector index and setup the pointer to the mv set */ if (!ctx->need_resync) - ctx->next_cell_data = &ctx->bc.buffer[(bitstream_tell(&ctx->bc) + 7) >> 3]; + 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"); @@ -817,7 +832,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, UPDATE_BITPOS(8); } else { /* VQ tree DATA code */ if (!ctx->need_resync) - ctx->next_cell_data = &ctx->bc.buffer[(bitstream_tell(&ctx->bc) + 7) >> 3]; + ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3]; CHECK_CELL bytes_used = decode_cell(ctx, avctx, plane, &curr_cell, @@ -832,6 +847,8 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, break; } }//while + + return AVERROR_INVALIDDATA; } @@ -844,24 +861,24 @@ 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; ctx->mc_vectors = num_vectors ? data : 0; /* init the bitreader */ - bitstream_init8(&ctx->bc, &data[num_vectors * 2], data_size - num_vectors * 2); + init_get_bits(&ctx->gb, &data[num_vectors * 2], (data_size - num_vectors * 2) << 3); 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; @@ -882,7 +899,8 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, GetByteContext gb; const uint8_t *bs_hdr; uint32_t frame_num, word2, check_sum, data_size; - uint32_t y_offset, u_offset, v_offset, starts[3], ends[3]; + int y_offset, u_offset, v_offset; + uint32_t starts[3], ends[3]; uint16_t height, width; int i, j; @@ -936,12 +954,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; if ((res = ff_set_dimensions(avctx, width, height)) < 0) return res; @@ -968,7 +982,8 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, ctx->y_data_size = ends[0] - starts[0]; ctx->v_data_size = ends[1] - starts[1]; ctx->u_data_size = ends[2] - starts[2]; - if (FFMAX3(y_offset, v_offset, u_offset) >= ctx->data_size - 16 || + if (FFMIN3(y_offset, v_offset, u_offset) < 0 || + FFMAX3(y_offset, v_offset, u_offset) >= ctx->data_size - 16 || FFMIN3(y_offset, v_offset, u_offset) < gb.buffer - bs_hdr + 16 || FFMIN3(ctx->y_data_size, ctx->v_data_size, ctx->u_data_size) <= 0) { av_log(avctx, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n"); @@ -1039,17 +1054,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 +1096,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 +1110,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); |