diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
| commit | f7813a5324be39d13ab536c245d15dfc602a7849 (patch) | |
| tree | fad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/libavcodec/indeo3.c | |
| parent | b7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff) | |
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavcodec/indeo3.c')
| -rw-r--r-- | ffmpeg/libavcodec/indeo3.c | 190 |
1 files changed, 98 insertions, 92 deletions
diff --git a/ffmpeg/libavcodec/indeo3.c b/ffmpeg/libavcodec/indeo3.c index a8b6e64..aa9c30a 100644 --- a/ffmpeg/libavcodec/indeo3.c +++ b/ffmpeg/libavcodec/indeo3.c @@ -148,6 +148,20 @@ 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, int luma_width, int luma_height) { @@ -188,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); @@ -202,22 +221,6 @@ static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx, return 0; } - -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; - } -} - - /** * Copy pixels of the cell(x + mv_x, y + mv_y) from the previous frame into * the cell(x, y) in the current frame. @@ -226,7 +229,7 @@ static av_cold void free_frame_buffers(Indeo3DecodeContext *ctx) * @param plane pointer to the plane descriptor * @param cell pointer to the cell descriptor */ -static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell) +static int copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell) { int h, w, mv_x, mv_y, offset, offset_dst; uint8_t *src, *dst; @@ -239,6 +242,16 @@ static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell) 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 || + ((cell->ypos + cell->height) << 2) + mv_y > plane->height || + ((cell->xpos + cell->width) << 2) + mv_x > plane->width) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Motion vectors point out of the frame.\n"); + return AVERROR_INVALIDDATA; + } + offset = offset_dst + mv_y * plane->pitch + mv_x; src = plane->pixels[ctx->buf_sel ^ 1] + offset; @@ -248,33 +261,33 @@ static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell) /* copy using 16xH blocks */ if (!((cell->xpos << 2) & 15) && w >= 4) { for (; w >= 4; src += 16, dst += 16, w -= 4) - ctx->hdsp.put_no_rnd_pixels_tab[0][0](dst, src, plane->pitch, h); + ctx->hdsp.put_pixels_tab[0][0](dst, src, plane->pitch, h); } /* copy using 8xH blocks */ if (!((cell->xpos << 2) & 7) && w >= 2) { - ctx->hdsp.put_no_rnd_pixels_tab[1][0](dst, src, plane->pitch, h); + ctx->hdsp.put_pixels_tab[1][0](dst, src, plane->pitch, h); w -= 2; src += 8; dst += 8; - } - - if (w >= 1) { - copy_block4(dst, src, plane->pitch, plane->pitch, h); + } else if (w >= 1) { + ctx->hdsp.put_pixels_tab[2][0](dst, src, plane->pitch, h); w--; src += 4; dst += 4; } } + + return 0; } /* Average 4/8 pixels at once without rounding using SWAR */ #define AVG_32(dst, src, ref) \ - AV_WN32A(dst, ((AV_RN32A(src) + AV_RN32A(ref)) >> 1) & 0x7F7F7F7FUL) + AV_WN32A(dst, ((AV_RN32(src) + AV_RN32(ref)) >> 1) & 0x7F7F7F7FUL) #define AVG_64(dst, src, ref) \ - AV_WN64A(dst, ((AV_RN64A(src) + AV_RN64A(ref)) >> 1) & 0x7F7F7F7F7F7F7F7FULL) + AV_WN64A(dst, ((AV_RN64(src) + AV_RN64(ref)) >> 1) & 0x7F7F7F7F7F7F7F7FULL) /* @@ -333,7 +346,7 @@ if (*data_ptr >= last_ptr) \ copy_block4(dst, ref, row_offset, row_offset, 4 << v_zoom) #define RLE_BLOCK_COPY_8 \ - pix64 = AV_RN64A(ref);\ + pix64 = AV_RN64(ref);\ if (is_first_row) {/* special prediction case: top line of a cell */\ pix64 = replicate64(pix64);\ fill_64(dst + row_offset, pix64, 7, row_offset);\ @@ -345,7 +358,7 @@ if (*data_ptr >= last_ptr) \ copy_block4(dst, ref, row_offset, row_offset, num_lines << v_zoom) #define RLE_LINES_COPY_M10 \ - pix64 = AV_RN64A(ref);\ + pix64 = AV_RN64(ref);\ if (is_top_of_cell) {\ pix64 = replicate64(pix64);\ fill_64(dst + row_offset, pix64, (num_lines << 1) - 1, row_offset);\ @@ -355,12 +368,12 @@ if (*data_ptr >= last_ptr) \ #define APPLY_DELTA_4 \ AV_WN16A(dst + line_offset ,\ - (AV_RN16A(ref ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ + (AV_RN16(ref ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ AV_WN16A(dst + line_offset + 2,\ - (AV_RN16A(ref + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ + (AV_RN16(ref + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ if (mode >= 3) {\ if (is_top_of_cell && !cell->ypos) {\ - AV_COPY32(dst, dst + row_offset);\ + AV_COPY32U(dst, dst + row_offset);\ } else {\ AVG_32(dst, ref, dst + row_offset);\ }\ @@ -370,20 +383,20 @@ if (*data_ptr >= last_ptr) \ /* apply two 32-bit VQ deltas to next even line */\ if (is_top_of_cell) { \ AV_WN32A(dst + row_offset , \ - (replicate32(AV_RN32A(ref )) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + (replicate32(AV_RN32(ref )) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ AV_WN32A(dst + row_offset + 4, \ - (replicate32(AV_RN32A(ref + 4)) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + (replicate32(AV_RN32(ref + 4)) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ } else { \ AV_WN32A(dst + row_offset , \ - (AV_RN32A(ref ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + (AV_RN32(ref ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ AV_WN32A(dst + row_offset + 4, \ - (AV_RN32A(ref + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + (AV_RN32(ref + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ } \ /* odd lines are not coded but rather interpolated/replicated */\ /* first line of the cell on the top of image? - replicate */\ /* otherwise - interpolate */\ if (is_top_of_cell && !cell->ypos) {\ - AV_COPY64(dst, dst + row_offset);\ + AV_COPY64U(dst, dst + row_offset);\ } else \ AVG_64(dst, ref, dst + row_offset); @@ -391,22 +404,22 @@ if (*data_ptr >= last_ptr) \ #define APPLY_DELTA_1011_INTER \ if (mode == 10) { \ AV_WN32A(dst , \ - (AV_RN32A(dst ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + (AV_RN32(dst ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ AV_WN32A(dst + 4 , \ - (AV_RN32A(dst + 4 ) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + (AV_RN32(dst + 4 ) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ AV_WN32A(dst + row_offset , \ - (AV_RN32A(dst + row_offset ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + (AV_RN32(dst + row_offset ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ AV_WN32A(dst + row_offset + 4, \ - (AV_RN32A(dst + row_offset + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + (AV_RN32(dst + row_offset + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ } else { \ AV_WN16A(dst , \ - (AV_RN16A(dst ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ + (AV_RN16(dst ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ AV_WN16A(dst + 2 , \ - (AV_RN16A(dst + 2 ) + delta_tab->deltas[dyad2]) & 0x7F7F);\ + (AV_RN16(dst + 2 ) + delta_tab->deltas[dyad2]) & 0x7F7F);\ AV_WN16A(dst + row_offset , \ - (AV_RN16A(dst + row_offset ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ + (AV_RN16(dst + row_offset ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ AV_WN16A(dst + row_offset + 2, \ - (AV_RN16A(dst + row_offset + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ + (AV_RN16(dst + row_offset + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ } @@ -587,29 +600,29 @@ static int decode_cell(Indeo3DecodeContext *ctx, AVCodecContext *avctx, 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; } else if (mode >= 10) { /* for mode 10 and 11 INTER first copy the predicted cell into the current one */ /* so we don't need to do data copying for each RLE code later */ - copy_cell(ctx, plane, cell); + int ret = copy_cell(ctx, plane, cell); + if (ret < 0) + return ret; } else { /* set the pointer to the reference pixels for modes 0-4 INTER */ mv_y = cell->mv_ptr[0]; mv_x = cell->mv_ptr[1]; + + /* -1 because there is an extra line on top for prediction */ + if ((cell->ypos << 2) + mv_y < -1 || (cell->xpos << 2) + mv_x < 0 || + ((cell->ypos + cell->height) << 2) + mv_y > plane->height || + ((cell->xpos + cell->width) << 2) + mv_x > plane->width) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Motion vectors point out of the frame.\n"); + return AVERROR_INVALIDDATA; + } + offset += mv_y * plane->pitch + mv_x; ref_block = plane->pixels[ctx->buf_sel ^ 1] + offset; } @@ -743,8 +756,7 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, const int depth, const int strip_width) { Cell curr_cell; - int bytes_used; - int mv_x, mv_y; + int bytes_used, ret; if (depth <= 0) { av_log(avctx, AV_LOG_ERROR, "Stack overflow (corrupted binary tree)!\n"); @@ -796,18 +808,8 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, 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; + ret = copy_cell(ctx, plane, &curr_cell); + return ret; } break; case INTER_DATA: @@ -894,17 +896,20 @@ static int decode_plane(Indeo3DecodeContext *ctx, AVCodecContext *avctx, static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, const uint8_t *buf, int buf_size) { - const uint8_t *buf_ptr = buf, *bs_hdr; + 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]; uint16_t height, width; int i, j; + bytestream2_init(&gb, buf, buf_size); + /* parse and check the OS header */ - frame_num = bytestream_get_le32(&buf_ptr); - word2 = bytestream_get_le32(&buf_ptr); - check_sum = bytestream_get_le32(&buf_ptr); - data_size = bytestream_get_le32(&buf_ptr); + frame_num = bytestream2_get_le32(&gb); + word2 = bytestream2_get_le32(&gb); + check_sum = bytestream2_get_le32(&gb); + data_size = bytestream2_get_le32(&gb); if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) { av_log(avctx, AV_LOG_ERROR, "OS header checksum mismatch!\n"); @@ -912,29 +917,27 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, } /* parse the bitstream header */ - bs_hdr = buf_ptr; - buf_size -= 16; + bs_hdr = gb.buffer; - if (bytestream_get_le16(&buf_ptr) != 32) { + if (bytestream2_get_le16(&gb) != 32) { av_log(avctx, AV_LOG_ERROR, "Unsupported codec version!\n"); return AVERROR_INVALIDDATA; } ctx->frame_num = frame_num; - ctx->frame_flags = bytestream_get_le16(&buf_ptr); - ctx->data_size = (bytestream_get_le32(&buf_ptr) + 7) >> 3; - ctx->cb_offset = *buf_ptr++; + ctx->frame_flags = bytestream2_get_le16(&gb); + ctx->data_size = (bytestream2_get_le32(&gb) + 7) >> 3; + ctx->cb_offset = bytestream2_get_byte(&gb); if (ctx->data_size == 16) return 4; - if (ctx->data_size > buf_size) - ctx->data_size = buf_size; + ctx->data_size = FFMIN(ctx->data_size, buf_size - 16); - buf_ptr += 3; // skip reserved byte and checksum + bytestream2_skip(&gb, 3); // skip reserved byte and checksum /* check frame dimensions */ - height = bytestream_get_le16(&buf_ptr); - width = bytestream_get_le16(&buf_ptr); + height = bytestream2_get_le16(&gb); + width = bytestream2_get_le16(&gb); if (av_image_check_size(width, height, 0, avctx)) return AVERROR_INVALIDDATA; @@ -953,12 +956,14 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, free_frame_buffers(ctx); if ((res = allocate_frame_buffers(ctx, avctx, width, height)) < 0) return res; - avcodec_set_dimensions(avctx, width, height); + if ((res = ff_set_dimensions(avctx, width, height)) < 0) + return res; } - y_offset = bytestream_get_le32(&buf_ptr); - v_offset = bytestream_get_le32(&buf_ptr); - u_offset = bytestream_get_le32(&buf_ptr); + y_offset = bytestream2_get_le32(&gb); + v_offset = bytestream2_get_le32(&gb); + u_offset = bytestream2_get_le32(&gb); + bytestream2_skip(&gb, 4); /* unfortunately there is no common order of planes in the buffer */ /* so we use that sorting algo for determining planes data sizes */ @@ -977,6 +982,7 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, 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 || + 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"); return AVERROR_INVALIDDATA; @@ -985,7 +991,7 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, ctx->y_data_ptr = bs_hdr + y_offset; ctx->v_data_ptr = bs_hdr + v_offset; ctx->u_data_ptr = bs_hdr + u_offset; - ctx->alt_quant = buf_ptr + sizeof(uint32_t); + ctx->alt_quant = gb.buffer; if (ctx->data_size == 16) { av_log(avctx, AV_LOG_DEBUG, "Sync frame encountered!\n"); @@ -1127,12 +1133,12 @@ static av_cold int decode_close(AVCodecContext *avctx) AVCodec ff_indeo3_decoder = { .name = "indeo3", + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_INDEO3, .priv_data_size = sizeof(Indeo3DecodeContext), .init = decode_init, .close = decode_close, .decode = decode_frame, - .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"), .capabilities = CODEC_CAP_DR1, }; |
