diff options
author | Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com> | 2016-10-27 22:34:48 +0200 |
---|---|---|
committer | Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com> | 2016-10-28 01:53:52 +0200 |
commit | 940b8908b94404a65f9f55e33efb4ccc6c81383c (patch) | |
tree | 39e89955e0ed0a80463589d217c9f9cab14186df /libavformat | |
parent | bf14393635559640f10001fa6af46130cb35fa31 (diff) | |
download | ffmpeg-940b8908b94404a65f9f55e33efb4ccc6c81383c.tar.gz |
apng: use side data to pass extradata to muxer
This fixes creating apng files, which is broken since commit
5ef19590802f000299e418143fc2301e3f43affe.
Reviewed-by: James Almer <jamrial@gmail.com>
Signed-off-by: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/apngenc.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/libavformat/apngenc.c b/libavformat/apngenc.c index e25df2eb5e..e5e8aa998f 100644 --- a/libavformat/apngenc.c +++ b/libavformat/apngenc.c @@ -44,6 +44,9 @@ typedef struct APNGMuxContext { AVRational prev_delay; int framerate_warned; + + uint8_t *extra_data; + int extra_data_size; } APNGMuxContext; static uint8_t *apng_find_chunk(uint32_t tag, uint8_t *buf, size_t length) @@ -101,15 +104,27 @@ static int apng_write_header(AVFormatContext *format_context) return 0; } -static void flush_packet(AVFormatContext *format_context, AVPacket *packet) +static int flush_packet(AVFormatContext *format_context, AVPacket *packet) { APNGMuxContext *apng = format_context->priv_data; AVIOContext *io_context = format_context->pb; AVStream *codec_stream = format_context->streams[0]; - AVCodecParameters *codec_par = codec_stream->codecpar; + uint8_t *side_data = NULL; + int side_data_size = 0; av_assert0(apng->prev_packet); + side_data = av_packet_get_side_data(apng->prev_packet, AV_PKT_DATA_NEW_EXTRADATA, &side_data_size); + + if (side_data_size) { + av_freep(&apng->extra_data); + apng->extra_data = av_mallocz(side_data_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!apng->extra_data) + return AVERROR(ENOMEM); + apng->extra_data_size = side_data_size; + memcpy(apng->extra_data, side_data, apng->extra_data_size); + } + if (apng->frame_number == 0 && !packet) { uint8_t *existing_acTL_chunk; uint8_t *existing_fcTL_chunk; @@ -117,13 +132,13 @@ static void flush_packet(AVFormatContext *format_context, AVPacket *packet) av_log(format_context, AV_LOG_INFO, "Only a single frame so saving as a normal PNG.\n"); // Write normal PNG headers without acTL chunk - existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), codec_par->extradata, codec_par->extradata_size); + existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), apng->extra_data, apng->extra_data_size); if (existing_acTL_chunk) { uint8_t *chunk_after_acTL = existing_acTL_chunk + AV_RB32(existing_acTL_chunk) + 12; - avio_write(io_context, codec_par->extradata, existing_acTL_chunk - codec_par->extradata); - avio_write(io_context, chunk_after_acTL, codec_par->extradata + codec_par->extradata_size - chunk_after_acTL); + avio_write(io_context, apng->extra_data, existing_acTL_chunk - apng->extra_data); + avio_write(io_context, chunk_after_acTL, apng->extra_data + apng->extra_data_size - chunk_after_acTL); } else { - avio_write(io_context, codec_par->extradata, codec_par->extradata_size); + avio_write(io_context, apng->extra_data, apng->extra_data_size); } // Write frame data without fcTL chunk @@ -142,9 +157,9 @@ static void flush_packet(AVFormatContext *format_context, AVPacket *packet) uint8_t *existing_acTL_chunk; // Write normal PNG headers - avio_write(io_context, codec_par->extradata, codec_par->extradata_size); + avio_write(io_context, apng->extra_data, apng->extra_data_size); - existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), codec_par->extradata, codec_par->extradata_size); + existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), apng->extra_data, apng->extra_data_size); if (!existing_acTL_chunk) { uint8_t buf[8]; // Write animation control header @@ -195,11 +210,13 @@ static void flush_packet(AVFormatContext *format_context, AVPacket *packet) av_packet_unref(apng->prev_packet); if (packet) av_copy_packet(apng->prev_packet, packet); + return 0; } static int apng_write_packet(AVFormatContext *format_context, AVPacket *packet) { APNGMuxContext *apng = format_context->priv_data; + int ret; if (!apng->prev_packet) { apng->prev_packet = av_malloc(sizeof(*apng->prev_packet)); @@ -208,7 +225,9 @@ static int apng_write_packet(AVFormatContext *format_context, AVPacket *packet) av_copy_packet(apng->prev_packet, packet); } else { - flush_packet(format_context, packet); + ret = flush_packet(format_context, packet); + if (ret < 0) + return ret; } return 0; @@ -219,10 +238,13 @@ static int apng_write_trailer(AVFormatContext *format_context) APNGMuxContext *apng = format_context->priv_data; AVIOContext *io_context = format_context->pb; uint8_t buf[8]; + int ret; if (apng->prev_packet) { - flush_packet(format_context, NULL); + ret = flush_packet(format_context, NULL); av_freep(&apng->prev_packet); + if (ret < 0) + return ret; } apng_write_chunk(io_context, MKBETAG('I', 'E', 'N', 'D'), NULL, 0); @@ -235,6 +257,9 @@ static int apng_write_trailer(AVFormatContext *format_context) apng_write_chunk(io_context, MKBETAG('a', 'c', 'T', 'L'), buf, 8); } + av_freep(&apng->extra_data); + apng->extra_data = 0; + return 0; } |