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]
