[FFmpeg-devel] [PATCH] avformat/apngdec: transmit all the chunks between consecutive fcTL ones.

Benoit Fouet benoit.fouet at free.fr
Mon Nov 24 16:11:09 CET 2014


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



More information about the ffmpeg-devel mailing list