summaryrefslogtreecommitdiff
path: root/libavformat/apngenc.c
diff options
context:
space:
mode:
authorAndreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>2016-10-27 22:34:48 +0200
committerAndreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>2016-10-28 01:53:52 +0200
commit940b8908b94404a65f9f55e33efb4ccc6c81383c (patch)
tree39e89955e0ed0a80463589d217c9f9cab14186df /libavformat/apngenc.c
parentbf14393635559640f10001fa6af46130cb35fa31 (diff)
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/apngenc.c')
-rw-r--r--libavformat/apngenc.c45
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;
}