[FFmpeg-devel] [PATCH 3/6] avformat/argo_brp: handle the case where the BASF block isn't the first

Zane van Iperen zane at zanevaniperen.com
Sat Sep 26 05:39:00 EEST 2020


Signed-off-by: Zane van Iperen <zane at zanevaniperen.com>
---
 libavformat/argo_brp.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/libavformat/argo_brp.c b/libavformat/argo_brp.c
index 613f04aef2..d3aab92af0 100644
--- a/libavformat/argo_brp.c
+++ b/libavformat/argo_brp.c
@@ -32,6 +32,7 @@
 #define BRP_BLOCK_HEADER_SIZE   12
 #define BRP_STREAM_HEADER_SIZE  20
 #define BRP_MAX_STREAMS         32 /* Soft cap, but even this is overkill. */
+#define BRP_BASF_LOOKAHEAD      10 /* How many blocks to search for the first BASF one. */
 #define BVID_HEADER_SIZE        16
 #define MASK_HEADER_SIZE        12
 #define BRP_MIN_BUFFER_SIZE     FFMAX3(FFMAX3(BRP_FILE_HEADER_SIZE,    \
@@ -269,16 +270,13 @@ static int argo_brp_read_header(AVFormatContext *s)
         }
     }
 
-    /*
-     * This is nasty. BASF streams have their chunk header in each block,
-     * so the first one needs to be read to get the stream info. It should
-     * always be the first one.
-     */
+    /* Try to find the first BASF chunk. */
     if (brp->basf.index >= 0) {
         AVStream *st = s->streams[brp->basf.index];
         ArgoBRPStreamHeader *hdr = brp->streams + brp->basf.index;
         ArgoBRPBlockHeader blk;
         int64_t offset;
+        int i;
 
         av_assert0(st->codecpar->codec_id == AV_CODEC_ID_ADPCM_ARGO);
         av_assert0(brp->streams[brp->basf.index].extradata_size == ASF_FILE_HEADER_SIZE);
@@ -288,6 +286,9 @@ static int argo_brp_read_header(AVFormatContext *s)
 
         offset = ret;
 
+        av_log(s, AV_LOG_TRACE, "Searching %d blocks for BASF...", BRP_BASF_LOOKAHEAD);
+
+        for (i = 0; i < BRP_BASF_LOOKAHEAD; i++) {
         if ((ret = avio_read(pb, buf, BRP_BLOCK_HEADER_SIZE)) < 0)
             return ret;
         else if (ret != BRP_BLOCK_HEADER_SIZE)
@@ -297,11 +298,21 @@ static int argo_brp_read_header(AVFormatContext *s)
         blk.start_ms  = AV_RL32(buf + 4);
         blk.size      = AV_RL32(buf + 8);
 
-        if (blk.stream_id != brp->basf.index) {
-            avpriv_request_sample(s, "first block not BASF");
-            return AVERROR_PATCHWELCOME;
+            if (blk.stream_id == brp->basf.index || blk.stream_id == -1)
+                break;
+
+            if ((ret = avio_skip(pb, blk.size)) < 0)
+                return ret;
+        }
+
+        if (i == BRP_BASF_LOOKAHEAD || blk.stream_id == -1) {
+            /* Don't error here, as there may still be a valid video stream. */
+            av_log(s, AV_LOG_TRACE, "not found\n");
+            goto done;
         }
 
+        av_log(s, AV_LOG_TRACE, "found at index %d\n", i);
+
         if (blk.size < ASF_CHUNK_HEADER_SIZE)
             return AVERROR_INVALIDDATA;
 
@@ -319,6 +330,7 @@ static int argo_brp_read_header(AVFormatContext *s)
         st->start_time = av_rescale_rnd(blk.start_ms, st->codecpar->sample_rate, 1000, AV_ROUND_UP);
         st->duration   = av_rescale_rnd(hdr->duration_ms, st->codecpar->sample_rate, 1000, AV_ROUND_UP);
 
+done:
         if ((ret = avio_seek(s->pb, offset, SEEK_SET)) < 0)
             return ret;
     }
-- 
2.25.4




More information about the ffmpeg-devel mailing list