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/flashsv.c | |
| parent | b7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff) | |
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavcodec/flashsv.c')
| -rw-r--r-- | ffmpeg/libavcodec/flashsv.c | 161 |
1 files changed, 94 insertions, 67 deletions
diff --git a/ffmpeg/libavcodec/flashsv.c b/ffmpeg/libavcodec/flashsv.c index 9982b5e..8791a2d 100644 --- a/ffmpeg/libavcodec/flashsv.c +++ b/ffmpeg/libavcodec/flashsv.c @@ -50,7 +50,7 @@ typedef struct BlockInfo { typedef struct FlashSVContext { AVCodecContext *avctx; - AVFrame frame; + AVFrame *frame; int image_width, image_height; int block_width, block_height; uint8_t *tmpblock; @@ -69,16 +69,17 @@ typedef struct FlashSVContext { int diff_start, diff_height; } FlashSVContext; - -static int decode_hybrid(const uint8_t *sptr, uint8_t *dptr, int dx, int dy, +static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t *dptr, int dx, int dy, int h, int w, int stride, const uint32_t *pal) { int x, y; const uint8_t *orig_src = sptr; - for (y = dx+h; y > dx; y--) { + for (y = dx + h; y > dx; y--) { uint8_t *dst = dptr + (y * stride) + dy * 3; for (x = 0; x < w; x++) { + if (sptr >= sptr_end) + return AVERROR_INVALIDDATA; if (*sptr & 0x80) { /* 15-bit color */ unsigned c = AV_RB16(sptr) & ~0x8000; @@ -100,6 +101,19 @@ static int decode_hybrid(const uint8_t *sptr, uint8_t *dptr, int dx, int dy, return sptr - orig_src; } +static av_cold int flashsv_decode_end(AVCodecContext *avctx) +{ + FlashSVContext *s = avctx->priv_data; + inflateEnd(&s->zstream); + /* release the frame if needed */ + av_frame_free(&s->frame); + + /* free the tmpblock */ + av_freep(&s->tmpblock); + + return 0; +} + static av_cold int flashsv_decode_init(AVCodecContext *avctx) { FlashSVContext *s = avctx->priv_data; @@ -115,12 +129,16 @@ static av_cold int flashsv_decode_init(AVCodecContext *avctx) return 1; } avctx->pix_fmt = AV_PIX_FMT_BGR24; - avcodec_get_frame_defaults(&s->frame); + + s->frame = av_frame_alloc(); + if (!s->frame) { + flashsv_decode_end(avctx); + return AVERROR(ENOMEM); + } return 0; } - static int flashsv2_prime(FlashSVContext *s, uint8_t *src, int size) { z_stream zs; @@ -198,25 +216,33 @@ static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt, } if (s->is_keyframe) { - s->blocks[blk_idx].pos = s->keyframedata + (get_bits_count(gb) / 8); - s->blocks[blk_idx].size = block_size; + s->blocks[blk_idx].pos = s->keyframedata + (get_bits_count(gb) / 8); + s->blocks[blk_idx].size = block_size; } + + y_pos += s->diff_start; + if (!s->color_depth) { /* Flash Screen Video stores the image upside down, so copy * lines to destination in reverse order. */ for (k = 1; k <= s->diff_height; k++) { - memcpy(s->frame.data[0] + x_pos * 3 + - (s->image_height - y_pos - s->diff_start - k) * s->frame.linesize[0], + memcpy(s->frame->data[0] + x_pos * 3 + + (s->image_height - y_pos - k) * s->frame->linesize[0], line, width * 3); /* advance source pointer to next line */ line += width * 3; } } else { /* hybrid 15-bit/palette mode */ - decode_hybrid(s->tmpblock, s->frame.data[0], - s->image_height - (y_pos + 1 + s->diff_start + s->diff_height), + ret = decode_hybrid(s->tmpblock, s->zstream.next_out, + s->frame->data[0], + s->image_height - (y_pos + 1 + s->diff_height), x_pos, s->diff_height, width, - s->frame.linesize[0], s->pal); + s->frame->linesize[0], s->pal); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "decode_hybrid failed\n"); + return ret; + } } skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */ return 0; @@ -241,8 +267,8 @@ static int calc_deflate_block_size(int tmpblock_size) static int flashsv_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - int buf_size = avpkt->size; - FlashSVContext *s = avctx->priv_data; + int buf_size = avpkt->size; + FlashSVContext *s = avctx->priv_data; int h_blocks, v_blocks, h_part, v_part, i, j, ret; GetBitContext gb; int last_blockwidth = s->block_width; @@ -254,13 +280,14 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, if (buf_size < 4) return -1; - init_get_bits(&gb, avpkt->data, buf_size * 8); + if ((ret = init_get_bits8(&gb, avpkt->data, buf_size)) < 0) + return ret; /* start to parse the bitstream */ - s->block_width = 16 * (get_bits(&gb, 4) + 1); - s->image_width = get_bits(&gb, 12); - s->block_height = 16 * (get_bits(&gb, 4) + 1); - s->image_height = get_bits(&gb, 12); + s->block_width = 16 * (get_bits(&gb, 4) + 1); + s->image_width = get_bits(&gb, 12); + s->block_height = 16 * (get_bits(&gb, 4) + 1); + s->image_height = get_bits(&gb, 12); if ( last_blockwidth != s->block_width || last_blockheight!= s->block_height) @@ -287,23 +314,25 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, /* the block size could change between frames, make sure the buffer * is large enough, if not, get a larger one */ if (s->block_size < s->block_width * s->block_height) { - int tmpblock_size = 3 * s->block_width * s->block_height; + int tmpblock_size = 3 * s->block_width * s->block_height, err; - s->tmpblock = av_realloc(s->tmpblock, tmpblock_size); - if (!s->tmpblock) { - av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); - return AVERROR(ENOMEM); + if ((err = av_reallocp(&s->tmpblock, tmpblock_size)) < 0) { + s->block_size = 0; + av_log(avctx, AV_LOG_ERROR, + "Cannot allocate decompression buffer.\n"); + return err; } if (s->ver == 2) { s->deflate_block_size = calc_deflate_block_size(tmpblock_size); if (s->deflate_block_size <= 0) { - av_log(avctx, AV_LOG_ERROR, "Can't determine deflate buffer size.\n"); + av_log(avctx, AV_LOG_ERROR, + "Cannot determine deflate buffer size.\n"); return -1; } - s->deflate_block = av_realloc(s->deflate_block, s->deflate_block_size); - if (!s->deflate_block) { - av_log(avctx, AV_LOG_ERROR, "Can't allocate deflate buffer.\n"); - return AVERROR(ENOMEM); + if ((err = av_reallocp(&s->deflate_block, s->deflate_block_size)) < 0) { + s->block_size = 0; + av_log(avctx, AV_LOG_ERROR, "Cannot allocate deflate buffer.\n"); + return err; } } } @@ -311,7 +340,8 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, /* initialize the image size once */ if (avctx->width == 0 && avctx->height == 0) { - avcodec_set_dimensions(avctx, s->image_width, s->image_height); + if ((ret = ff_set_dimensions(avctx, s->image_width, s->image_height)) < 0) + return ret; } /* check for changes of image width and image height */ @@ -326,18 +356,20 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, /* we care for keyframes only in Screen Video v2 */ s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2); if (s->is_keyframe) { - s->keyframedata = av_realloc(s->keyframedata, avpkt->size); + int err; + if ((err = av_reallocp(&s->keyframedata, avpkt->size)) < 0) + return err; memcpy(s->keyframedata, avpkt->data, avpkt->size); } if(s->ver == 2 && !s->blocks) - s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) - * sizeof(s->blocks[0])); + s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) * + sizeof(s->blocks[0])); av_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", s->image_width, s->image_height, s->block_width, s->block_height, h_blocks, v_blocks, h_part, v_part); - if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) return ret; /* loop over all block columns */ @@ -362,7 +394,7 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, s->diff_height = cur_blk_height; if (8 * size > get_bits_left(&gb)) { - av_frame_unref(&s->frame); + av_frame_unref(s->frame); return AVERROR_INVALIDDATA; } @@ -375,18 +407,25 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, if (s->color_depth != 0 && s->color_depth != 2) { av_log(avctx, AV_LOG_ERROR, - "%dx%d invalid color depth %d\n", i, j, s->color_depth); + "%dx%d invalid color depth %d\n", + i, j, s->color_depth); return AVERROR_INVALIDDATA; } if (has_diff) { if (!s->keyframe) { av_log(avctx, AV_LOG_ERROR, - "inter frame without keyframe\n"); + "Inter frame without keyframe\n"); return AVERROR_INVALIDDATA; } s->diff_start = get_bits(&gb, 8); s->diff_height = get_bits(&gb, 8); + if (s->diff_start + s->diff_height > cur_blk_height) { + av_log(avctx, AV_LOG_ERROR, + "Block parameters invalid: %d + %d > %d\n", + s->diff_start, s->diff_height, cur_blk_height); + return AVERROR_INVALIDDATA; + } av_log(avctx, AV_LOG_DEBUG, "%dx%d diff start %d height %d\n", i, j, s->diff_start, s->diff_height); @@ -399,14 +438,15 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, if (s->zlibprime_curr) { int col = get_bits(&gb, 8); int row = get_bits(&gb, 8); - av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n", i, j, col, row); + av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n", + i, j, col, row); size -= 2; avpriv_request_sample(avctx, "zlibprime_curr"); return AVERROR_PATCHWELCOME; } if (!s->blocks && (s->zlibprime_curr || s->zlibprime_prev)) { - av_log(avctx, AV_LOG_ERROR, "no data available for zlib " - "priming\n"); + av_log(avctx, AV_LOG_ERROR, + "no data available for zlib priming\n"); return AVERROR_INVALIDDATA; } size--; // account for flags byte @@ -414,12 +454,13 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, if (has_diff) { int k; - int off = (s->image_height - y_pos - 1) * s->frame.linesize[0]; + int off = (s->image_height - y_pos - 1) * s->frame->linesize[0]; - for (k = 0; k < cur_blk_height; k++) - memcpy(s->frame.data[0] + off - k*s->frame.linesize[0] + x_pos*3, - s->keyframe + off - k*s->frame.linesize[0] + x_pos*3, + for (k = 0; k < cur_blk_height; k++) { + int x = off - k * s->frame->linesize[0] + x_pos * 3; + memcpy(s->frame->data[0] + x, s->keyframe + x, cur_blk_width * 3); + } } /* skip unchanged blocks, which have size 0 */ @@ -435,16 +476,17 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, } if (s->is_keyframe && s->ver == 2) { if (!s->keyframe) { - s->keyframe = av_malloc(s->frame.linesize[0] * avctx->height); + s->keyframe = av_malloc(s->frame->linesize[0] * avctx->height); if (!s->keyframe) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n"); return AVERROR(ENOMEM); } } - memcpy(s->keyframe, s->frame.data[0], s->frame.linesize[0] * avctx->height); + memcpy(s->keyframe, s->frame->data[0], + s->frame->linesize[0] * avctx->height); } - if ((ret = av_frame_ref(data, &s->frame)) < 0) + if ((ret = av_frame_ref(data, s->frame)) < 0) return ret; *got_frame = 1; @@ -457,24 +499,10 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } - -static av_cold int flashsv_decode_end(AVCodecContext *avctx) -{ - FlashSVContext *s = avctx->priv_data; - inflateEnd(&s->zstream); - /* release the frame if needed */ - av_frame_unref(&s->frame); - - /* free the tmpblock */ - av_free(s->tmpblock); - - return 0; -} - - #if CONFIG_FLASHSV_DECODER AVCodec ff_flashsv_decoder = { .name = "flashsv", + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_FLASHSV, .priv_data_size = sizeof(FlashSVContext), @@ -482,8 +510,7 @@ AVCodec ff_flashsv_decoder = { .close = flashsv_decode_end, .decode = flashsv_decode_frame, .capabilities = CODEC_CAP_DR1, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, - .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, }; #endif /* CONFIG_FLASHSV_DECODER */ @@ -538,6 +565,7 @@ static av_cold int flashsv2_decode_end(AVCodecContext *avctx) AVCodec ff_flashsv2_decoder = { .name = "flashsv2", + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_FLASHSV2, .priv_data_size = sizeof(FlashSVContext), @@ -545,7 +573,6 @@ AVCodec ff_flashsv2_decoder = { .close = flashsv2_decode_end, .decode = flashsv_decode_frame, .capabilities = CODEC_CAP_DR1, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, - .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"), + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, }; #endif /* CONFIG_FLASHSV2_DECODER */ |
