PR #25842 opened by Romain Beauxis (toots) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25842 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25842.patch
Since 843e83ed2d, every seek moves back by the audio pre-roll, so a seek on video lands one keyframe earlier. That suits a caller that decodes, but a caller that copies the packets keeps the extra GOP, as with a concat `inpoint`. This series adds `AVSEEK_FLAG_PREROLL`, and a `seek2preroll` option like `seek2any`, for callers that decode. Without it, a seek lands where it asked again, and only the priming is discarded. The pre-roll tests opt in when the flag is added, concat stops applying the pre-roll twice, and ffplay sets the option last. The first commit adds a test with the current output, and the later commits update it. For 9.1 we revert the pre-roll commits instead. Fixes #25672. >From 9101d923808468df531b9757f79b490c0064bd3f Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sat, 7 Nov 2026 09:32:45 -0600 Subject: [PATCH 1/4] tests/fate/preroll: check a concat inpoint on a video keyframe An inpoint on a keyframe of a Matroska file with AAC must start the cut on that keyframe. The reference shows the current behaviour, which starts on the keyframe before. --- tests/fate/preroll.mak | 4 ++++ tests/ref/fate/preroll-aac-concat-inpoint | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 tests/ref/fate/preroll-aac-concat-inpoint diff --git a/tests/fate/preroll.mak b/tests/fate/preroll.mak index 243b9d07317..8af2aeb9b71 100644 --- a/tests/fate/preroll.mak +++ b/tests/fate/preroll.mak @@ -66,6 +66,10 @@ FATE_PREROLL_SEEK-$(call ALLYES, CONCAT_DEMUXER MOV_DEMUXER AAC_DECODER FILE_PRO fate-preroll-aac-concat-seek: tests/data/samples/gapless/102400samples_qt-lc-aac.m4a fate-preroll-aac-concat-seek: CMD = seek_concat $(SRC_PATH)/tests/preroll.ffconcat ../samples/gapless_102400samples_qt-lc-aac.m4a -seekback 530000 -frames 3 -duration 3 +# An inpoint on a video keyframe: the cut starts at that keyframe. +FATE_PREROLL_FFPROBE-$(call ALLYES, CONCAT_DEMUXER MATROSKA_DEMUXER H264_DECODER AAC_DECODER FILE_PROTOCOL PIPE_PROTOCOL) += fate-preroll-aac-concat-inpoint +fate-preroll-aac-concat-inpoint: CMD = printf "ffconcat version 1.0\nfile file:%s\ninpoint 3\n" $(TARGET_SAMPLES)/mkv/test7_cut.mkv | run ffprobe$(PROGSSUF)$(EXESUF) -protocol_whitelist pipe,file -safe 0 -f concat -i pipe: -read_intervals %+\#4 -show_entries packet=stream_index,pts,flags:packet_side_data=skip_samples -print_format compact + # A seek close to the start of a stream whose start time is unknown. FATE_PREROLL_SEEK-$(call DEMDEC, AAC, AAC) += fate-preroll-aac-adts-seek-start fate-preroll-aac-adts-seek-start: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/aac/id3v2.aac -seekback 10000 -frames 2 -duration 3 diff --git a/tests/ref/fate/preroll-aac-concat-inpoint b/tests/ref/fate/preroll-aac-concat-inpoint new file mode 100644 index 00000000000..e9f9d75572a --- /dev/null +++ b/tests/ref/fate/preroll-aac-concat-inpoint @@ -0,0 +1,4 @@ +packet|stream_index=0|pts=-1000|flags=K__ +packet|stream_index=1|pts=-986|flags=K__|side_datum/skip_samples:skip_samples=1024 +packet|stream_index=1|pts=-965|flags=K__ +packet|stream_index=1|pts=-944|flags=K__ -- 2.54.0 >From 87e905ae49627b9cf34c617c2a3c7963b598c879 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sat, 7 Nov 2026 11:40:09 -0600 Subject: [PATCH 2/4] avformat: add AVSEEK_FLAG_PREROLL A caller that decodes after a seek needs the audio pre-roll before the target, while a caller that copies the packets needs the seek to land where it asked. Add AVSEEK_FLAG_PREROLL, and the seek2preroll option to set it on every seek, for the caller to say so. The pre-roll tests set it, as the pre-roll is still left after every seek. --- doc/APIchanges | 4 ++++ libavformat/avformat.h | 8 ++++++++ libavformat/options_table.h | 1 + libavformat/seek.c | 2 ++ libavformat/version.h | 2 +- tests/fate/preroll.mak | 23 ++++++++++++----------- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 36f95c8df2b..76398921963 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2026-06-23. API changes, most recent first: +2026-11-xx - xxxxxxxxxx - lavf 63.19.100 - avformat.h + Add AVSEEK_FLAG_PREROLL and AVFormatContext.seek2preroll, for + avformat_seek_file() to leave the audio pre-roll before the target. + 2026-11-xx - xxxxxxxxxx - lavc 63.26.100 - defs.h Add AV_PROFILE_CAVS_JIZHUN and AV_PROFILE_CAVS_BROADCASTING. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 679d15676c5..9f6d475f7db 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2056,6 +2056,13 @@ typedef struct AVFormatContext { * - demuxing: Set by user */ int recursion_limit; + + /** + * Add AVSEEK_FLAG_PREROLL to every avformat_seek_file(). + * - encoding: unused + * - decoding: Set by user + */ + int seek2preroll; } AVFormatContext; /** @@ -2731,6 +2738,7 @@ void avformat_close_input(AVFormatContext **s); #define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes #define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes #define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number +#define AVSEEK_FLAG_PREROLL 16 ///< leave the audio pre-roll before the target, see avformat_seek_file() /** * @addtogroup lavf_encoding diff --git a/libavformat/options_table.h b/libavformat/options_table.h index 537870c5c99..541645bf98f 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -56,6 +56,7 @@ static const AVOption avformat_options[] = { {"legacy_id3v2_comm_keys", "also export id3v2 COMM descriptors as bare metadata keys", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_LEGACY_ID3V2_COMM_KEYS }, 0, 0, D|AV_OPT_FLAG_DEPRECATED, .unit = "fflags" }, #endif {"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D}, +{"seek2preroll", "leave the audio pre-roll before the target of a seek, for decoding", OFFSET(seek2preroll), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D}, {"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, (double)INT64_MAX, D}, {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D}, diff --git a/libavformat/seek.c b/libavformat/seek.c index 4a09d013353..93d63387e95 100644 --- a/libavformat/seek.c +++ b/libavformat/seek.c @@ -767,6 +767,8 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, if (s->seek2any > 0) flags |= AVSEEK_FLAG_ANY; + if (s->seek2preroll > 0) + flags |= AVSEEK_FLAG_PREROLL; flags &= ~AVSEEK_FLAG_BACKWARD; if (!(flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))) { diff --git a/libavformat/version.h b/libavformat/version.h index 6a80f3ac4e6..e063e12b983 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 18 +#define LIBAVFORMAT_VERSION_MINOR 19 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/tests/fate/preroll.mak b/tests/fate/preroll.mak index 8af2aeb9b71..9fde7ed40ee 100644 --- a/tests/fate/preroll.mak +++ b/tests/fate/preroll.mak @@ -8,16 +8,17 @@ # bit-exact across platforms. PREROLL_SEEK_TS = 0.53 +PREROLL_OPT = -seek2preroll 1 # 1: test name, 2: demuxer, 3: decoder, 4: sample define FATE_PREROLL_TEST FATE_PREROLL_FFPROBE-$(call DEMDEC, $(2), $(3)) += fate-preroll-$(1)-declared fate-preroll-$(1)-landing fate-preroll-$(1)-declared: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -select_streams a:0 -show_entries stream=codec_name,sample_rate,initial_padding,seek_preroll -print_format compact $(TARGET_SAMPLES)/$(4) -fate-preroll-$(1)-landing: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -select_streams a:0 -read_intervals $(PREROLL_SEEK_TS)%+\#3 -show_entries packet=pts,dts,duration -print_format compact $(TARGET_SAMPLES)/$(4) +fate-preroll-$(1)-landing: CMD = run ffprobe$(PROGSSUF)$(EXESUF) $(PREROLL_OPT) -select_streams a:0 -read_intervals $(PREROLL_SEEK_TS)%+\#3 -show_entries packet=pts,dts,duration -print_format compact $(TARGET_SAMPLES)/$(4) FATE_PREROLL_FFMPEG-$(call FRAMECRC, $(2), $(3), PCM_S16LE_ENCODER ARESAMPLE_FILTER VOLUME_FILTER) += fate-preroll-$(1)-decode -fate-preroll-$(1)-decode: CMD = framecrc -ss $(PREROLL_SEEK_TS) -t 0.15 -i $(TARGET_SAMPLES)/$(4) -map 0:a:0 -af volume=0,aresample -c:a pcm_s16le +fate-preroll-$(1)-decode: CMD = framecrc $(PREROLL_OPT) -ss $(PREROLL_SEEK_TS) -t 0.15 -i $(TARGET_SAMPLES)/$(4) -map 0:a:0 -af volume=0,aresample -c:a pcm_s16le FATE_PREROLL_FFMPEG-$(call FRAMECRC, $(2), $(3), PCM_S16LE_ENCODER ARESAMPLE_FILTER VOLUME_FILTER) += fate-preroll-$(1)-decode-noaccurate -fate-preroll-$(1)-decode-noaccurate: CMD = framecrc -noaccurate_seek -ss $(PREROLL_SEEK_TS) -t 0.15 -i $(TARGET_SAMPLES)/$(4) -map 0:a:0 -af volume=0,aresample -c:a pcm_s16le +fate-preroll-$(1)-decode-noaccurate: CMD = framecrc $(PREROLL_OPT) -noaccurate_seek -ss $(PREROLL_SEEK_TS) -t 0.15 -i $(TARGET_SAMPLES)/$(4) -map 0:a:0 -af volume=0,aresample -c:a pcm_s16le endef $(eval $(call FATE_PREROLL_TEST,aac-mov,MOV,AAC,gapless/102400samples_qt-lc-aac.m4a)) @@ -37,34 +38,34 @@ $(eval $(call FATE_PREROLL_TEST,mp3-itunes,MP3,MP3FLOAT,gapless/gapless-itunes.m # A seek that lands inside the priming, which here spans the first three # packets: the rest of the priming, or the pre-roll if longer, is skipped. FATE_PREROLL_FFMPEG-$(call FRAMECRC, CAF, AAC, PCM_S16LE_ENCODER ARESAMPLE_FILTER VOLUME_FILTER) += fate-preroll-aac-caf-decode-in-priming -fate-preroll-aac-caf-decode-in-priming: CMD = framecrc -noaccurate_seek -ss 0.01 -t 0.1 -i $(TARGET_SAMPLES)/caf/aac.caf -af volume=0,aresample -c:a pcm_s16le +fate-preroll-aac-caf-decode-in-priming: CMD = framecrc $(PREROLL_OPT) -noaccurate_seek -ss 0.01 -t 0.1 -i $(TARGET_SAMPLES)/caf/aac.caf -af volume=0,aresample -c:a pcm_s16le # A forward seek, as ffplay does: the range starts before the target and is # open at the end. FATE_PREROLL_SEEK-$(call DEMDEC, MOV, AAC) += fate-preroll-aac-mov-seek-forward -fate-preroll-aac-mov-seek-forward: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/gapless/102400samples_qt-lc-aac.m4a -seekforw 530000 -seekmin 400000 -frames 2 -duration 3 +fate-preroll-aac-mov-seek-forward: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/gapless/102400samples_qt-lc-aac.m4a -seekforw 530000 -seekmin 400000 -frames 2 -duration 3 $(PREROLL_OPT) # A seek past the end lands on the last packet, which carries the padding # to discard at the end of the stream. FATE_PREROLL_FFPROBE-$(call DEMDEC, CAF, AAC) += fate-preroll-aac-caf-landing-end -fate-preroll-aac-caf-landing-end: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -select_streams a:0 -read_intervals 5.45%+\#2 -show_entries packet=pts,duration:packet_side_data=skip_samples,discard_padding -print_format compact $(TARGET_SAMPLES)/caf/aac.caf +fate-preroll-aac-caf-landing-end: CMD = run ffprobe$(PROGSSUF)$(EXESUF) $(PREROLL_OPT) -select_streams a:0 -read_intervals 5.45%+\#2 -show_entries packet=pts,duration:packet_side_data=skip_samples,discard_padding -print_format compact $(TARGET_SAMPLES)/caf/aac.caf FATE_PREROLL_FFPROBE-$(call DEMDEC, MATROSKA, OPUS) += fate-preroll-opus-mkv-landing-end -fate-preroll-opus-mkv-landing-end: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -select_streams a:0 -read_intervals 1.1%+\#2 -show_entries packet=pts,duration:packet_side_data=skip_samples,discard_padding -print_format compact $(TARGET_SAMPLES)/mkv/codec_delay_opus.mkv +fate-preroll-opus-mkv-landing-end: CMD = run ffprobe$(PROGSSUF)$(EXESUF) $(PREROLL_OPT) -select_streams a:0 -read_intervals 1.1%+\#2 -show_entries packet=pts,duration:packet_side_data=skip_samples,discard_padding -print_format compact $(TARGET_SAMPLES)/mkv/codec_delay_opus.mkv # A seek on the video stream, just after a keyframe: the audio pre-roll # still needs room. FATE_PREROLL_SEEK-$(call DEMDEC, MOV, AAC H264) += fate-preroll-aac-mov-seek-video -fate-preroll-aac-mov-seek-video: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -stream_id 0 -seekback 182000 -frames 4 -duration 3 +fate-preroll-aac-mov-seek-video: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -stream_id 0 -seekback 182000 -frames 4 -duration 3 $(PREROLL_OPT) # A seek on the stream that starts later, close enough to its start that # the seek targets it: the other stream is already past its own start. FATE_PREROLL_SEEK-$(call ALLYES, MOV_DEMUXER MOV_MUXER AAC_DECODER FILE_PROTOCOL) += fate-preroll-aac-mov-seek-staggered -fate-preroll-aac-mov-seek-staggered: CMD = seek_staggered $(TARGET_SAMPLES)/gapless/102400samples_qt-lc-aac.m4a 1 -stream_id 1 -seekback 42500 -frames 4 -duration 3 +fate-preroll-aac-mov-seek-staggered: CMD = seek_staggered $(TARGET_SAMPLES)/gapless/102400samples_qt-lc-aac.m4a 1 -stream_id 1 -seekback 42500 -frames 4 -duration 3 $(PREROLL_OPT) # A seek through the concat demuxer, which seeks in the file it reads. FATE_PREROLL_SEEK-$(call ALLYES, CONCAT_DEMUXER MOV_DEMUXER AAC_DECODER FILE_PROTOCOL) += fate-preroll-aac-concat-seek fate-preroll-aac-concat-seek: tests/data/samples/gapless/102400samples_qt-lc-aac.m4a -fate-preroll-aac-concat-seek: CMD = seek_concat $(SRC_PATH)/tests/preroll.ffconcat ../samples/gapless_102400samples_qt-lc-aac.m4a -seekback 530000 -frames 3 -duration 3 +fate-preroll-aac-concat-seek: CMD = seek_concat $(SRC_PATH)/tests/preroll.ffconcat ../samples/gapless_102400samples_qt-lc-aac.m4a -seekback 530000 -frames 3 -duration 3 $(PREROLL_OPT) # An inpoint on a video keyframe: the cut starts at that keyframe. FATE_PREROLL_FFPROBE-$(call ALLYES, CONCAT_DEMUXER MATROSKA_DEMUXER H264_DECODER AAC_DECODER FILE_PROTOCOL PIPE_PROTOCOL) += fate-preroll-aac-concat-inpoint @@ -72,7 +73,7 @@ fate-preroll-aac-concat-inpoint: CMD = printf "ffconcat version 1.0\nfile file:% # A seek close to the start of a stream whose start time is unknown. FATE_PREROLL_SEEK-$(call DEMDEC, AAC, AAC) += fate-preroll-aac-adts-seek-start -fate-preroll-aac-adts-seek-start: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/aac/id3v2.aac -seekback 10000 -frames 2 -duration 3 +fate-preroll-aac-adts-seek-start: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/aac/id3v2.aac -seekback 10000 -frames 2 -duration 3 $(PREROLL_OPT) $(FATE_PREROLL_SEEK-yes): libavformat/tests/seek$(EXESUF) -- 2.54.0 >From 6a631e1af0c3e7e981da5bf6479325e3b07eadef Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sat, 7 Nov 2026 11:49:40 -0600 Subject: [PATCH 3/4] avformat/seek: leave the audio pre-roll only with AVSEEK_FLAG_PREROLL Moving the target back by the audio pre-roll lands a seek on the video stream one keyframe earlier, which a caller that copies the packets keeps, as with a concat inpoint (#25672). Move the target back and discard the pre-roll only with the flag, and never pass it to the demuxer, so that a demuxer seeking through another one, as concat does, does not move the target back twice. --- doc/APIchanges | 4 +++ libavformat/avformat.h | 26 ++++++++------ libavformat/demux.c | 3 +- libavformat/internal.h | 12 +++++-- libavformat/seek.c | 13 +++++-- libavformat/version.h | 2 +- .../fate/aac-seek-landing-frame-length-short | 2 +- tests/ref/fate/aac-seek-landing-sbr | 4 +-- .../fate/mov-aac-2048-priming-seek-landing | 2 +- tests/ref/fate/preroll-aac-concat-inpoint | 8 ++--- tests/ref/fate/preroll-aac-concat-seek | 36 +++++++++---------- tests/ref/seek/mkv-codec-delay | 26 +++++++------- 12 files changed, 80 insertions(+), 58 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 76398921963..06597c172e5 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2026-06-23. API changes, most recent first: +2026-11-xx - xxxxxxxxxx - lavf 63.19.101 - avformat.h + avformat_seek_file() leaves the audio pre-roll before the target, and + discards it after the seek, only with AVSEEK_FLAG_PREROLL. + 2026-11-xx - xxxxxxxxxx - lavf 63.19.100 - avformat.h Add AVSEEK_FLAG_PREROLL and AVFormatContext.seek2preroll, for avformat_seek_file() to leave the audio pre-roll before the target. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 9f6d475f7db..a90081d3bda 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2571,21 +2571,25 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, * keyframes (this may not be supported by all demuxers). * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored. * - * A seek by timestamp moves ts back by the largest + * If flags contain AVSEEK_FLAG_PREROLL, or AVFormatContext.seek2preroll is + * set, a seek by timestamp moves ts back by the largest * AVCodecParameters.seek_preroll of the audio streams that are not discarded, * whatever stream_index is, so that the decoders get their declared pre-roll - * before ts. The target stays within min_ts and after the start of the - * stream, so less room may be left. max_ts moves back as much, unless it is - * INT64_MAX. If that seek fails, the seek is done to ts. This also applies to - * av_seek_frame() with a demuxer that only implements this function. + * before ts. This is meant for a caller that decodes: the seek may land one + * keyframe earlier, which a caller that copies the packets would keep. The + * target stays within min_ts and after the start of the stream, so less room + * may be left. max_ts moves back as much, unless it is INT64_MAX. If that + * seek fails, the seek is done to ts. This also applies to av_seek_frame() + * with a demuxer that only implements this function. * * The first packet read after a seek from an audio stream carries - * AV_PKT_DATA_SKIP_SAMPLES side data to discard the larger of the rest of the - * priming (AVCodecParameters.initial_padding) and the seek pre-roll. The - * discard supplies the stream's declared pre-roll; recovery beyond that - * allowance depends on the codec and bitstream. Only the priming is discarded - * on the first packet of the stream, and no pre-roll after the priming of a - * stream whose start the seek targets. + * AV_PKT_DATA_SKIP_SAMPLES side data to discard the rest of the priming + * (AVCodecParameters.initial_padding) if the seek landed inside it. With + * AVSEEK_FLAG_PREROLL, it discards at least the seek pre-roll. The discard + * supplies the stream's declared pre-roll; recovery beyond that allowance + * depends on the codec and bitstream. Only the priming is discarded on the + * first packet of the stream, and no pre-roll after the priming of a stream + * whose start the seek targets. * * @param s media file handle * @param stream_index index of the stream which is used as time base reference diff --git a/libavformat/demux.c b/libavformat/demux.c index 1468726b096..581a5c24959 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -1583,7 +1583,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (first) { if (par->initial_padding > 0) skip = par->initial_padding; - } else if (!(sti->seek_to_start && pkt->pts != AV_NOPTS_VALUE && !in_priming)) { + } else if (sti->seek_preroll && + !(sti->seek_to_start && pkt->pts != AV_NOPTS_VALUE && !in_priming)) { // Past the first packet, the decoder also misses what // came before. skip = FFMAX(skip, par->seek_preroll); diff --git a/libavformat/internal.h b/libavformat/internal.h index 4db9db85ce5..a175828718d 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -245,12 +245,18 @@ typedef struct FFStream { /** * Set by a seek, cleared on the next packet of the stream, which gets in - * skip_samples the rest of the priming if it is inside it, and unless it - * is the first packet of the stream, at least the seek pre-roll of the - * codec. After the priming, a seek to the start of the stream gets none. + * skip_samples the rest of the priming if it is inside it, and when + * seek_preroll is set and it is not the first packet of the stream, at + * least the seek pre-roll of the codec. After the priming, a seek to the + * start of the stream gets none. */ int seek_discard; + /** + * Set with seek_discard when the seek had AVSEEK_FLAG_PREROLL. + */ + int seek_preroll; + /** * Set with seek_discard when the target of the seek is at or before the * start of this stream. diff --git a/libavformat/seek.c b/libavformat/seek.c index 93d63387e95..4c1c832e382 100644 --- a/libavformat/seek.c +++ b/libavformat/seek.c @@ -656,7 +656,8 @@ int av_seek_frame(AVFormatContext *s, int stream_index, flags & ~AVSEEK_FLAG_BACKWARD); } - ret = seek_frame_internal(s, stream_index, timestamp, flags); + ret = seek_frame_internal(s, stream_index, timestamp, + flags & ~AVSEEK_FLAG_PREROLL); if (ret >= 0) ret = avformat_queue_attached_pictures(s); @@ -712,6 +713,7 @@ static void request_seek_discard(AVFormatContext *s, int stream_index, FFStream *const sti = ffstream(st); sti->seek_discard = 1; + sti->seek_preroll = !!(flags & AVSEEK_FLAG_PREROLL); sti->seek_to_start = !(flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME)) && st->start_time != AV_NOPTS_VALUE && av_compare_ts(ts, time_base, st->start_time, @@ -758,6 +760,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) { int64_t target = ts, target_max = max_ts; + int preroll_flag; int ret; if (min_ts > ts || max_ts < ts) @@ -770,8 +773,12 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, if (s->seek2preroll > 0) flags |= AVSEEK_FLAG_PREROLL; flags &= ~AVSEEK_FLAG_BACKWARD; + preroll_flag = flags & AVSEEK_FLAG_PREROLL; + // A demuxer that seeks through another one, as concat does, must not + // move the target back a second time. + flags &= ~AVSEEK_FLAG_PREROLL; - if (!(flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))) { + if (preroll_flag && !(flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))) { int64_t preroll = seek_preroll(s, stream_index); int64_t start = stream_index >= 0 ? s->streams[stream_index]->start_time : s->start_time; @@ -795,7 +802,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, ret = seek_file(s, stream_index, min_ts, ts, max_ts, flags); } if (ret >= 0) - request_seek_discard(s, stream_index, target, flags); + request_seek_discard(s, stream_index, target, flags | preroll_flag); return ret; } diff --git a/libavformat/version.h b/libavformat/version.h index e063e12b983..bbb2fc7d871 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFORMAT_VERSION_MINOR 19 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/tests/ref/fate/aac-seek-landing-frame-length-short b/tests/ref/fate/aac-seek-landing-frame-length-short index ecb9fe031fb..fd28ed6ee4b 100644 --- a/tests/ref/fate/aac-seek-landing-frame-length-short +++ b/tests/ref/fate/aac-seek-landing-frame-length-short @@ -1,3 +1,3 @@ -packet|pts=157440|dts=157440|duration=960 packet|pts=158400|dts=158400|duration=960 packet|pts=159360|dts=159360|duration=960 +packet|pts=160320|dts=160320|duration=960 diff --git a/tests/ref/fate/aac-seek-landing-sbr b/tests/ref/fate/aac-seek-landing-sbr index 1e8fc110a40..7f3e2ebc8d8 100644 --- a/tests/ref/fate/aac-seek-landing-sbr +++ b/tests/ref/fate/aac-seek-landing-sbr @@ -1,3 +1,3 @@ -packet|pts=244736|dts=244736|duration=1024 -packet|pts=245760|dts=245760|duration=1024 packet|pts=246784|dts=246784|duration=1024 +packet|pts=247808|dts=247808|duration=1024 +packet|pts=248832|dts=248832|duration=1024 diff --git a/tests/ref/fate/mov-aac-2048-priming-seek-landing b/tests/ref/fate/mov-aac-2048-priming-seek-landing index ff6091c3271..17292a119ae 100644 --- a/tests/ref/fate/mov-aac-2048-priming-seek-landing +++ b/tests/ref/fate/mov-aac-2048-priming-seek-landing @@ -1,3 +1,3 @@ -packet|pts=100352|dts=100352|duration=1024 packet|pts=101376|dts=101376|duration=1024 packet|pts=102400|dts=102400|duration=1024 +packet|pts=103424|dts=103424|duration=1024 diff --git a/tests/ref/fate/preroll-aac-concat-inpoint b/tests/ref/fate/preroll-aac-concat-inpoint index e9f9d75572a..7aeb9236d30 100644 --- a/tests/ref/fate/preroll-aac-concat-inpoint +++ b/tests/ref/fate/preroll-aac-concat-inpoint @@ -1,4 +1,4 @@ -packet|stream_index=0|pts=-1000|flags=K__ -packet|stream_index=1|pts=-986|flags=K__|side_datum/skip_samples:skip_samples=1024 -packet|stream_index=1|pts=-965|flags=K__ -packet|stream_index=1|pts=-944|flags=K__ +packet|stream_index=0|pts=0|flags=K__ +packet|stream_index=1|pts=38|flags=K__ +packet|stream_index=1|pts=59|flags=K__ +packet|stream_index=1|pts=80|flags=K__ diff --git a/tests/ref/fate/preroll-aac-concat-seek b/tests/ref/fate/preroll-aac-concat-seek index 895a3c46eab..0bdc1329cb4 100644 --- a/tests/ref/fate/preroll-aac-concat-seek +++ b/tests/ref/fate/preroll-aac-concat-seek @@ -1,6 +1,6 @@ -ret: 0 st: 0 flags:1 dts: 0.462948 pts: 0.462948 pos: 2363 size: 26 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 0.486168 pts: 0.486168 pos: 2389 size: 27 +ret: 0 st: 0 flags:1 dts: 0.486168 pts: 0.486168 pos: 2389 size: 27 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 0.509388 pts: 0.509388 pos: 2416 size: 27 +ret: 0 st: 0 flags:1 dts: 0.532608 pts: 0.532608 pos: 2443 size: 28 ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts:-0.047891 pts:-0.047891 pos: 1366 size: 6 skip:2112 discard:0 ret: 0 st: 0 flags:1 dts:-0.024671 pts:-0.024671 pos: 1372 size: 251 @@ -14,17 +14,17 @@ ret: 0 st: 0 flags:1 dts: 0.811247 pts: 0.811247 pos: 2774 size: 27 ret: 0 st: 0 flags:1 dts: 0.834467 pts: 0.834467 pos: 2801 size: 28 ret: 0 st: 0 flags:1 dts: 0.857687 pts: 0.857687 pos: 2829 size: 28 ret: 0 st: 0 flags:1 ts: 1.682494 -ret: 0 st: 0 flags:1 dts: 1.623946 pts: 1.623946 pos: 3903 size: 39 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 1.647166 pts: 1.647166 pos: 3942 size: 42 +ret: 0 st: 0 flags:1 dts: 1.647166 pts: 1.647166 pos: 3942 size: 42 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.670385 pts: 1.670385 pos: 3984 size: 41 +ret: 0 st: 0 flags:1 dts: 1.693605 pts: 1.693605 pos: 4025 size: 41 ret: 0 st:-1 flags:0 ts:-0.423332 ret: 0 st: 0 flags:1 dts:-0.047891 pts:-0.047891 pos: 1366 size: 6 skip:2112 discard:0 ret: 0 st: 0 flags:1 dts:-0.024671 pts:-0.024671 pos: 1372 size: 251 ret: 0 st: 0 flags:1 dts:-0.001451 pts:-0.001451 pos: 1623 size: 168 ret: 0 st:-1 flags:1 ts: 0.470835 -ret: 0 st: 0 flags:1 dts: 0.416508 pts: 0.416508 pos: 2309 size: 27 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 0.439728 pts: 0.439728 pos: 2336 size: 27 +ret: 0 st: 0 flags:1 dts: 0.439728 pts: 0.439728 pos: 2336 size: 27 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 0.462948 pts: 0.462948 pos: 2363 size: 26 +ret: 0 st: 0 flags:1 dts: 0.486168 pts: 0.486168 pos: 2389 size: 27 ret: 0 st: 0 flags:0 ts: 1.365011 ret: 0 st: 0 flags:1 dts: 1.368526 pts: 1.368526 pos: 3465 size: 30 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.391746 pts: 1.391746 pos: 3495 size: 39 @@ -38,9 +38,9 @@ ret: 0 st: 0 flags:1 dts: 0.161088 pts: 0.161088 pos: 2014 size: 27 ret: 0 st: 0 flags:1 dts: 0.184308 pts: 0.184308 pos: 2041 size: 27 ret: 0 st: 0 flags:1 dts: 0.207528 pts: 0.207528 pos: 2068 size: 27 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 0.997007 pts: 0.997007 pos: 2996 size: 28 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 1.020227 pts: 1.020227 pos: 3024 size: 28 +ret: 0 st: 0 flags:1 dts: 1.020227 pts: 1.020227 pos: 3024 size: 28 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.043447 pts: 1.043447 pos: 3052 size: 27 +ret: 0 st: 0 flags:1 dts: 1.066667 pts: 1.066667 pos: 3079 size: 28 ret: 0 st: 0 flags:0 ts: 1.941678 ret: 0 st: 0 flags:1 dts: 1.949025 pts: 1.949025 pos: 4474 size: 41 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.972245 pts: 1.972245 pos: 4515 size: 39 @@ -54,17 +54,17 @@ ret: 0 st: 0 flags:1 dts: 0.741587 pts: 0.741587 pos: 2691 size: 28 ret: 0 st: 0 flags:1 dts: 0.764807 pts: 0.764807 pos: 2719 size: 28 ret: 0 st: 0 flags:1 dts: 0.788027 pts: 0.788027 pos: 2747 size: 27 ret: 0 st:-1 flags:1 ts: 1.624171 -ret: 0 st: 0 flags:1 dts: 1.577506 pts: 1.577506 pos: 3821 size: 41 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 1.600726 pts: 1.600726 pos: 3862 size: 41 +ret: 0 st: 0 flags:1 dts: 1.600726 pts: 1.600726 pos: 3862 size: 41 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.623946 pts: 1.623946 pos: 3903 size: 39 +ret: 0 st: 0 flags:1 dts: 1.647166 pts: 1.647166 pos: 3942 size: 42 ret: 0 st: 0 flags:0 ts:-0.481655 ret: 0 st: 0 flags:1 dts:-0.047891 pts:-0.047891 pos: 1366 size: 6 skip:2112 discard:0 ret: 0 st: 0 flags:1 dts:-0.024671 pts:-0.024671 pos: 1372 size: 251 ret: 0 st: 0 flags:1 dts:-0.001451 pts:-0.001451 pos: 1623 size: 168 ret: 0 st: 0 flags:1 ts: 0.412494 -ret: 0 st: 0 flags:1 dts: 0.346848 pts: 0.346848 pos: 2229 size: 26 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 0.370068 pts: 0.370068 pos: 2255 size: 27 +ret: 0 st: 0 flags:1 dts: 0.370068 pts: 0.370068 pos: 2255 size: 27 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 0.393288 pts: 0.393288 pos: 2282 size: 27 +ret: 0 st: 0 flags:1 dts: 0.416508 pts: 0.416508 pos: 2309 size: 27 ret: 0 st:-1 flags:0 ts: 1.306672 ret: 0 st: 0 flags:1 dts: 1.322086 pts: 1.322086 pos: 3405 size: 30 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.345306 pts: 1.345306 pos: 3435 size: 30 @@ -78,9 +78,9 @@ ret: 0 st: 0 flags:1 dts: 0.114649 pts: 0.114649 pos: 1961 size: 26 ret: 0 st: 0 flags:1 dts: 0.137868 pts: 0.137868 pos: 1987 size: 27 ret: 0 st: 0 flags:1 dts: 0.161088 pts: 0.161088 pos: 2014 size: 27 ret: 0 st: 0 flags:1 ts: 0.989184 -ret: 0 st: 0 flags:1 dts: 0.927347 pts: 0.927347 pos: 2913 size: 27 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 0.950567 pts: 0.950567 pos: 2940 size: 28 +ret: 0 st: 0 flags:1 dts: 0.950567 pts: 0.950567 pos: 2940 size: 28 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 0.973787 pts: 0.973787 pos: 2968 size: 28 +ret: 0 st: 0 flags:1 dts: 0.997007 pts: 0.997007 pos: 2996 size: 28 ret: 0 st:-1 flags:0 ts: 1.883340 ret: 0 st: 0 flags:1 dts: 1.902585 pts: 1.902585 pos: 4392 size: 41 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.925805 pts: 1.925805 pos: 4433 size: 41 @@ -94,14 +94,14 @@ ret: 0 st: 0 flags:1 dts: 0.671927 pts: 0.671927 pos: 2609 size: 27 ret: 0 st: 0 flags:1 dts: 0.695147 pts: 0.695147 pos: 2636 size: 27 ret: 0 st: 0 flags:1 dts: 0.718367 pts: 0.718367 pos: 2663 size: 28 ret: 0 st: 0 flags:1 ts: 1.565850 -ret: 0 st: 0 flags:1 dts: 1.507846 pts: 1.507846 pos: 3699 size: 39 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 1.531066 pts: 1.531066 pos: 3738 size: 42 +ret: 0 st: 0 flags:1 dts: 1.531066 pts: 1.531066 pos: 3738 size: 42 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 1.554286 pts: 1.554286 pos: 3780 size: 41 +ret: 0 st: 0 flags:1 dts: 1.577506 pts: 1.577506 pos: 3821 size: 41 ret: 0 st:-1 flags:0 ts:-0.539992 ret: 0 st: 0 flags:1 dts:-0.047891 pts:-0.047891 pos: 1366 size: 6 skip:2112 discard:0 ret: 0 st: 0 flags:1 dts:-0.024671 pts:-0.024671 pos: 1372 size: 251 ret: 0 st: 0 flags:1 dts:-0.001451 pts:-0.001451 pos: 1623 size: 168 ret: 0 st:-1 flags:1 ts: 0.354175 -ret: 0 st: 0 flags:1 dts: 0.300408 pts: 0.300408 pos: 2175 size: 27 skip:1024 discard:0 -ret: 0 st: 0 flags:1 dts: 0.323628 pts: 0.323628 pos: 2202 size: 27 +ret: 0 st: 0 flags:1 dts: 0.323628 pts: 0.323628 pos: 2202 size: 27 skip:1024 discard:0 ret: 0 st: 0 flags:1 dts: 0.346848 pts: 0.346848 pos: 2229 size: 26 +ret: 0 st: 0 flags:1 dts: 0.370068 pts: 0.370068 pos: 2255 size: 27 diff --git a/tests/ref/seek/mkv-codec-delay b/tests/ref/seek/mkv-codec-delay index f2281552908..779298347fd 100644 --- a/tests/ref/seek/mkv-codec-delay +++ b/tests/ref/seek/mkv-codec-delay @@ -2,47 +2,47 @@ ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:3840 discard:706 +ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:0 discard:706 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.794000 pts: 0.794000 pos: 7358 size: 154 skip:3840 discard:0 +ret: 0 st: 0 flags:1 dts: 0.794000 pts: 0.794000 pos: 7358 size: 154 ret: 0 st: 0 flags:1 ts:-0.317000 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 ret:-1 st:-1 flags:0 ts: 2.576668 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:3840 discard:706 +ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:0 discard:706 ret: 0 st: 0 flags:0 ts: 0.365000 -ret: 0 st: 0 flags:1 dts: 0.374000 pts: 0.374000 pos: 3963 size: 150 skip:3840 discard:0 +ret: 0 st: 0 flags:1 dts: 0.374000 pts: 0.374000 pos: 3963 size: 150 ret: 0 st: 0 flags:1 ts:-0.741000 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 ret:-1 st:-1 flags:0 ts: 2.153336 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 0.954000 pts: 0.954000 pos: 8643 size: 154 skip:3840 discard:0 +ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:0 discard:706 ret: 0 st: 0 flags:0 ts:-0.058000 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 ret: 0 st: 0 flags:1 ts: 2.836000 -ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:3840 discard:706 +ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:0 discard:706 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.534000 pts: 0.534000 pos: 5251 size: 150 skip:3840 discard:0 +ret: 0 st: 0 flags:1 dts: 0.614000 pts: 0.614000 pos: 5903 size: 159 ret: 0 st: 0 flags:0 ts:-0.482000 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:3840 discard:706 +ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:0 discard:706 ret:-1 st:-1 flags:0 ts: 1.306672 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.114000 pts: 0.114000 pos: 1855 size: 158 skip:3840 discard:0 +ret: 0 st: 0 flags:1 dts: 0.194000 pts: 0.194000 pos: 2512 size: 159 ret: 0 st: 0 flags:0 ts:-0.905000 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 ret: 0 st: 0 flags:1 ts: 1.989000 -ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:3840 discard:706 +ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:0 discard:706 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.894000 pts: 0.894000 pos: 8154 size: 155 skip:3840 discard:0 +ret: 0 st: 0 flags:1 dts: 0.894000 pts: 0.894000 pos: 8154 size: 155 ret: 0 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 ret:-1 st: 0 flags:0 ts: 2.672000 ret: 0 st: 0 flags:1 ts: 1.566000 -ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:3840 discard:706 +ret: 0 st: 0 flags:1 dts: 1.014000 pts: 1.014000 pos: 9306 size: 268 skip:0 discard:706 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.474000 pts: 0.474000 pos: 4768 size: 153 skip:3840 discard:0 +ret: 0 st: 0 flags:1 dts: 0.474000 pts: 0.474000 pos: 4768 size: 153 ret: 0 st:-1 flags:1 ts:-0.645825 ret: 0 st: 0 flags:1 dts:-0.007000 pts:-0.007000 pos: 748 size: 320 skip:312 discard:0 -- 2.54.0 >From deefd93a1a5178c7b088ae220ebb1658a5082c22 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sat, 7 Nov 2026 11:49:40 -0600 Subject: [PATCH 4/4] fftools/ffplay: set seek2preroll ffplay decodes everything it reads, so its seeks need the audio pre-roll before the target. --- fftools/ffplay.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index a149ec555c4..3968a1061b9 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3249,6 +3249,7 @@ static int read_thread(void *arg) } ic->interrupt_callback.callback = decode_interrupt_cb; ic->interrupt_callback.opaque = is; + ic->seek2preroll = 1; if ((ret = av_dict_copy(&format_options, format_opts, 0)) < 0) goto fail; if (!av_dict_get(format_options, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) { -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
