diff --git a/libavcodec/flashsv.c b/libavcodec/flashsv.c index 5f0bc0c6df..e284439972 100644 --- a/libavcodec/flashsv.c +++ b/libavcodec/flashsv.c @@ -63,11 +63,10 @@ typedef struct FlashSVContext { AVBufferRef *keyframedata_buf; uint8_t *keyframe; BlockInfo *blocks; - uint8_t *deflate_block; - int deflate_block_size; int color_depth; int zlibprime_curr, zlibprime_prev; int diff_start, diff_height; + uint8_t tmp[UINT16_MAX]; } FlashSVContext; static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t *dptr, int dx, int dy, @@ -141,41 +140,59 @@ static av_cold int flashsv_decode_init(AVCodecContext *avctx) static int flashsv2_prime(FlashSVContext *s, const uint8_t *src, int size) { - z_stream zs; int zret; // Zlib return code + static const uint8_t zlib_header[] = { 0x78, 0x01 }; + uint8_t *data = s->tmpblock; + unsigned remaining; if (!src) return AVERROR_INVALIDDATA; - zs.zalloc = NULL; - zs.zfree = NULL; - zs.opaque = NULL; - s->zstream.next_in = src; s->zstream.avail_in = size; - s->zstream.next_out = s->tmpblock; + s->zstream.next_out = data; s->zstream.avail_out = s->block_size * 3; inflate(&s->zstream, Z_SYNC_FLUSH); - - if (deflateInit(&zs, 0) != Z_OK) - return -1; - zs.next_in = s->tmpblock; - zs.avail_in = s->block_size * 3 - s->zstream.avail_out; - zs.next_out = s->deflate_block; - zs.avail_out = s->deflate_block_size; - deflate(&zs, Z_SYNC_FLUSH); - deflateEnd(&zs); + remaining = s->block_size * 3 - s->zstream.avail_out; if ((zret = inflateReset(&s->zstream)) != Z_OK) { av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); return AVERROR_UNKNOWN; } - s->zstream.next_in = s->deflate_block; - s->zstream.avail_in = s->deflate_block_size - zs.avail_out; - s->zstream.next_out = s->tmpblock; - s->zstream.avail_out = s->block_size * 3; + /* Create input for zlib that is equivalent to encoding the output + * from above and decoding it again (the net result of this is that + * the dictionary of past decoded data is correctly primed and + * the adler32 checksum is correctly initialized). + * This is accomplished by synthetizing blocks of uncompressed data + * out of the output from above. See section 3.2.4 of RFC 1951. */ + s->zstream.next_in = zlib_header; + s->zstream.avail_in = sizeof(zlib_header); inflate(&s->zstream, Z_SYNC_FLUSH); + while (remaining > 0) { + unsigned block_size = FFMIN(UINT16_MAX, remaining); + uint8_t header[5]; + /* Bit 0: Non-last-block, bits 1-2: BTYPE for uncompressed block */ + header[0] = 0; + /* Block size */ + AV_WL16(header + 1, block_size); + /* Block size (one's complement) */ + AV_WL16(header + 3, block_size ^ 0xFFFF); + s->zstream.next_in = header; + s->zstream.avail_in = sizeof(header); + s->zstream.next_out = s->tmp; + s->zstream.avail_out = sizeof(s->tmp); + zret = inflate(&s->zstream, Z_SYNC_FLUSH); + if (zret != Z_OK) + return AVERROR_UNKNOWN; + s->zstream.next_in = data; + s->zstream.avail_in = block_size; + zret = inflate(&s->zstream, Z_SYNC_FLUSH); + if (zret != Z_OK) + return AVERROR_UNKNOWN; + data += block_size; + remaining -= block_size; + } return 0; } @@ -248,22 +265,6 @@ static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, return 0; } -static int calc_deflate_block_size(int tmpblock_size) -{ - z_stream zstream; - int size; - - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - if (deflateInit(&zstream, 0) != Z_OK) - return -1; - size = deflateBound(&zstream, tmpblock_size); - deflateEnd(&zstream); - - return size; -} - static int flashsv_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -322,19 +323,6 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, "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, - "Cannot determine deflate buffer size.\n"); - return -1; - } - 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; - } - } } s->block_size = s->block_width * s->block_height; @@ -570,7 +558,6 @@ static av_cold int flashsv2_decode_end(AVCodecContext *avctx) av_buffer_unref(&s->keyframedata_buf); av_freep(&s->blocks); av_freep(&s->keyframe); - av_freep(&s->deflate_block); flashsv_decode_end(avctx); return 0;