In order to support multiple IDAT of fdAT chunks following an fcTL one, transmit all the chunks between two fcTL ones (or between fcTL and IEND one). --- libavformat/apngdec.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/libavformat/apngdec.c b/libavformat/apngdec.c index 1e0f1c7..756cdd1 100644 --- a/libavformat/apngdec.c +++ b/libavformat/apngdec.c @@ -325,8 +325,6 @@ static int apng_read_packet(AVFormatContext *s, AVPacket *pkt) * and needed next: * 4 (length) * 4 (tag (must be fdAT or IDAT)) - * - * TODO: support multiple fdAT following an fcTL */ /* if num_play is not 1, then the seekback is already guaranteed */ if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 46)) < 0) @@ -350,15 +348,35 @@ static int apng_read_packet(AVFormatContext *s, AVPacket *pkt) tag != MKTAG('I', 'D', 'A', 'T')) return AVERROR_INVALIDDATA; - if ((ret = avio_seek(pb, -46, SEEK_CUR)) < 0) - return ret; - size = 38 /* fcTL */ + 8 /* len, tag */ + len + 4 /* crc */; if (size > INT_MAX) return AVERROR(EINVAL); - if ((ret = av_get_packet(pb, pkt, size)) < 0) + if ((ret = avio_seek(pb, -46, SEEK_CUR)) < 0 || + (ret = av_append_packet(pb, pkt, size)) < 0) + return ret; + + if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0) return ret; + + len = avio_rb32(pb); + tag = avio_rl32(pb); + while (tag && + tag != MKTAG('f', 'c', 'T', 'L') && + tag != MKTAG('I', 'E', 'N', 'D')) { + if (len > 0x7fffffff) + return AVERROR_INVALIDDATA; + if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 || + (ret = av_append_packet(pb, pkt, len + 12)) < 0) + return ret; + if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0) + return ret; + len = avio_rb32(pb); + tag = avio_rl32(pb); + } + if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0) + return ret; + if (ctx->is_key_frame) pkt->flags |= AV_PKT_FLAG_KEY; return ret; -- 2.2.0.rc2.23.gca0107e _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel