PR #22502 opened by toots
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22502
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22502.patch


>From ec47d319e853bb3e6cec884b9bfaee7f9f79fbd9 Mon Sep 17 00:00:00 2001
From: Romain Beauxis <[email protected]>
Date: Sat, 14 Mar 2026 11:19:20 -0500
Subject: [PATCH 1/3] tests/api/api-file-seek-test.c: Add utility to test
 avformat_seek_file

---
 tests/Makefile                 |   1 +
 tests/api/Makefile             |   1 +
 tests/api/api-file-seek-test.c | 114 +++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+)
 create mode 100644 tests/api/api-file-seek-test.c

diff --git a/tests/Makefile b/tests/Makefile
index 4b3fa6a54a..74354eb46f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -256,6 +256,7 @@ include $(SRC_PATH)/tests/fate/vorbis.mak
 include $(SRC_PATH)/tests/fate/vpx.mak
 include $(SRC_PATH)/tests/fate/vqf.mak
 include $(SRC_PATH)/tests/fate/vvc.mak
+include $(SRC_PATH)/tests/fate/wav.mak
 include $(SRC_PATH)/tests/fate/wavpack.mak
 include $(SRC_PATH)/tests/fate/webm-dash-manifest.mak
 include $(SRC_PATH)/tests/fate/wma.mak
diff --git a/tests/api/Makefile b/tests/api/Makefile
index 899aeb1f54..79d9262984 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -2,6 +2,7 @@ APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek api-dump-stream-meta
+APITESTPROGS-$(CONFIG_WAV_DEMUXER) += api-file-seek
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
 APITESTPROGS-$(HAVE_THREADS) += api-threadmessage
 APITESTPROGS += $(APITESTPROGS-yes)
diff --git a/tests/api/api-file-seek-test.c b/tests/api/api-file-seek-test.c
new file mode 100644
index 0000000000..b4d22ca73b
--- /dev/null
+++ b/tests/api/api-file-seek-test.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2026 Romain Beauxis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * File seek test: open a file, seek to a timestamp using avformat_seek_file,
+ * read one packet and print its pts and CRC.
+ *
+ * Usage: api-file-seek-test <file> <seek_ts> [audio|video]
+ */
+
+#include "libavutil/adler32.h"
+#include "libavformat/avformat.h"
+
+int main(int argc, char **argv)
+{
+    enum AVMediaType media_type = AVMEDIA_TYPE_AUDIO;
+    AVFormatContext *fmt_ctx = NULL;
+    AVPacket *pkt = NULL;
+    int stream_idx;
+    int64_t seek_ts;
+    int result;
+
+    if (argc < 3) {
+        av_log(NULL, AV_LOG_ERROR,
+               "Usage: %s <file> <seek_ts> [audio|video]\n", argv[0]);
+        return 1;
+    }
+
+    seek_ts = strtoll(argv[2], NULL, 10);
+
+    if (argc >= 4) {
+        if (!strcmp(argv[3], "video"))
+            media_type = AVMEDIA_TYPE_VIDEO;
+        else if (strcmp(argv[3], "audio")) {
+            av_log(NULL, AV_LOG_ERROR,
+                   "Unknown media type '%s'\n", argv[3]);
+            return 1;
+        }
+    }
+
+    result = avformat_open_input(&fmt_ctx, argv[1], NULL, NULL);
+    if (result < 0) {
+        av_log(NULL, AV_LOG_ERROR, "Can't open file\n");
+        return 1;
+    }
+
+    result = avformat_find_stream_info(fmt_ctx, NULL);
+    if (result < 0) {
+        av_log(NULL, AV_LOG_ERROR, "Can't get stream info\n");
+        goto end;
+    }
+
+    stream_idx = av_find_best_stream(fmt_ctx, media_type, -1, -1, NULL, 0);
+    if (stream_idx < 0) {
+        av_log(NULL, AV_LOG_ERROR, "Can't find %s stream\n",
+               av_get_media_type_string(media_type));
+        result = stream_idx;
+        goto end;
+    }
+
+    pkt = av_packet_alloc();
+    if (!pkt) {
+        result = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    result = avformat_seek_file(fmt_ctx, stream_idx,
+                                INT64_MIN, seek_ts, seek_ts, 0);
+    if (result < 0) {
+        av_log(NULL, AV_LOG_ERROR,
+               "Seek to %"PRId64" failed\n", seek_ts);
+        goto end;
+    }
+
+    while ((result = av_read_frame(fmt_ctx, pkt)) >= 0) {
+        if (pkt->stream_index != stream_idx) {
+            av_packet_unref(pkt);
+            continue;
+        }
+
+        printf("pts=%"PRId64" crc=0x%08"PRIx32"\n", pkt->pts,
+               av_adler32_update(0, pkt->data, pkt->size));
+        av_packet_unref(pkt);
+        break;
+    }
+
+    if (result == AVERROR_EOF)
+        av_log(NULL, AV_LOG_ERROR,
+               "No packet read after seeking to %"PRId64"\n", seek_ts);
+
+end:
+    av_packet_free(&pkt);
+    avformat_close_input(&fmt_ctx);
+    return result < 0 ? 1 : 0;
+}
-- 
2.52.0


>From 1785cfb39018b087f4fdf2b9d211809547d51ba1 Mon Sep 17 00:00:00 2001
From: Romain Beauxis <[email protected]>
Date: Sat, 14 Mar 2026 11:20:34 -0500
Subject: [PATCH 2/3] libavformat/riffdec.c: Correct invalid bit_rate when
 possible.

---
 libavformat/riffdec.c               | 17 +++++++++++++++++
 tests/fate/wav.mak                  |  7 +++++++
 tests/ref/fate/wav-bad-avg-byterate |  1 +
 3 files changed, 25 insertions(+)
 create mode 100644 tests/fate/wav.mak
 create mode 100644 tests/ref/fate/wav-bad-avg-byterate

diff --git a/libavformat/riffdec.c b/libavformat/riffdec.c
index 30835d5f36..e06dc6be96 100644
--- a/libavformat/riffdec.c
+++ b/libavformat/riffdec.c
@@ -198,6 +198,23 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
                "Invalid sample rate: %d\n", par->sample_rate);
         return AVERROR_INVALIDDATA;
     }
+
+    /* nAvgBytesPerSec is only used for seeking and is fully redundant for
+     * uncompressed PCM (block_align == channels * bytes_per_sample), so
+     * recompute it from the structural fields rather than trusting the header.
+     * For compressed formats that invariant doesn't hold, so leave it as-is. 
*/
+    if (channels > 0 && par->bits_per_coded_sample > 0 && par->block_align > 0 
&&
+        par->block_align == channels * (par->bits_per_coded_sample / 8)) {
+        uint64_t expected_bitrate = (uint64_t)par->sample_rate * 
par->block_align * 8;
+        if (par->bit_rate != expected_bitrate) {
+            av_log(s, AV_LOG_WARNING,
+                   "nAvgBytesPerSec %"PRIu64" inconsistent with other fields"
+                   " (expected %"PRIu64"), overriding.\n",
+                   par->bit_rate / 8, expected_bitrate / 8);
+            par->bit_rate = expected_bitrate;
+        }
+    }
+
     if (par->codec_id == AV_CODEC_ID_AAC_LATM) {
         /* Channels and sample_rate values are those prior to applying SBR
          * and/or PS. */
diff --git a/tests/fate/wav.mak b/tests/fate/wav.mak
new file mode 100644
index 0000000000..503b971f2a
--- /dev/null
+++ b/tests/fate/wav.mak
@@ -0,0 +1,7 @@
+FATE_WAV_SAMPLES-$(CONFIG_WAV_DEMUXER) += fate-wav-bad-avg-byterate
+fate-wav-bad-avg-byterate: $(APITESTSDIR)/api-file-seek-test$(EXESUF)
+fate-wav-bad-avg-byterate: CMD = run 
$(APITESTSDIR)/api-file-seek-test$(EXESUF) 
$(TARGET_SAMPLES)/wav/wrong-avg-byterate.wav 500 audio
+
+FATE-yes += $(FATE_WAV_SAMPLES-yes)
+
+fate-wav: $(FATE_WAV_SAMPLES-yes)
diff --git a/tests/ref/fate/wav-bad-avg-byterate 
b/tests/ref/fate/wav-bad-avg-byterate
new file mode 100644
index 0000000000..597ffd1811
--- /dev/null
+++ b/tests/ref/fate/wav-bad-avg-byterate
@@ -0,0 +1 @@
+pts=500 crc=0x6277fd02
-- 
2.52.0


>From 6afa9665081536efce574a5dacdbab2b658be043 Mon Sep 17 00:00:00 2001
From: Romain Beauxis <[email protected]>
Date: Sat, 14 Mar 2026 11:23:46 -0500
Subject: [PATCH 3/3] FOR CI ONLY!

---
 tests/fate/wav.mak | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/fate/wav.mak b/tests/fate/wav.mak
index 503b971f2a..9d2ee717d8 100644
--- a/tests/fate/wav.mak
+++ b/tests/fate/wav.mak
@@ -1,7 +1,11 @@
 FATE_WAV_SAMPLES-$(CONFIG_WAV_DEMUXER) += fate-wav-bad-avg-byterate
+fate-wav-bad-avg-byterate: $(TARGET_SAMPLES)/wav/wrong-avg-byterate.wav
 fate-wav-bad-avg-byterate: $(APITESTSDIR)/api-file-seek-test$(EXESUF)
 fate-wav-bad-avg-byterate: CMD = run 
$(APITESTSDIR)/api-file-seek-test$(EXESUF) 
$(TARGET_SAMPLES)/wav/wrong-avg-byterate.wav 500 audio
 
+$(TARGET_SAMPLES)/wav/wrong-avg-byterate.wav:
+       wget -q 
"https://www.dropbox.com/scl/fi/1vzsz3caj22jinb38pwmv/wrong-avg-byterate.wav?rlkey=5gpzlwiu5dfc1wkmjvbxb0lj7&dl=1";
 -O $@
+
 FATE-yes += $(FATE_WAV_SAMPLES-yes)
 
 fate-wav: $(FATE_WAV_SAMPLES-yes)
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to