[FFmpeg-devel] [PATCH 1/1] avformat/demux: Add durationprobesize AVOption
Stefano Sabatini
stefasab at gmail.com
Wed Feb 7 01:52:07 EET 2024
On date Tuesday 2024-02-06 11:52:09 +0100, Nicolas Gaullier wrote:
> Yet another probesize used to get the last pts (and thus the duration)
> of mpegts/ps files. It is aimed at users interested in better durations probing
> for itself, or because using avformat_find_stream_info indirectly and requiring
> exact values: for concatdec for exemple, especially if streamcopying above it.
nit: exemple typo
> The current code does not behave well with high bitrates and high video buffering
> (physical gap between the last video packet and the last audio packet).
>
> Default behaviour is unchanged: 250k up to 250k << 6 (step by step)
> Setting this new option has two effects:
> - override the maximum probesize (currently 250k << 6)
> - reduce the number of steps to 1 instead of 6, this is to avoid detecting
> the audio "too early" and failing to reach a video packet. Here, even if audio
> duration is found but not the video duration, there will be a retry, so at the
> end the full user-overriden probesize will be used.
>
> Signed-off-by: Nicolas Gaullier <nicolas.gaullier at cji.paris>
> ---
> libavformat/avformat.h | 8 ++++++++
> libavformat/demux.c | 13 ++++++++-----
> libavformat/options_table.h | 1 +
> 3 files changed, 17 insertions(+), 5 deletions(-)
please add missing user doc in doc/formats.texi (you might reuse the
hightlight above to explain why this is needed), also the new field
requires an entry in doc/APIChanges
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 5d0fe82250..533f5a963d 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -1823,6 +1823,14 @@ typedef struct AVFormatContext {
> * Freed by libavformat in avformat_free_context().
> */
> AVStreamGroup **stream_groups;
> +
> + /**
> + * Maximum number of bytes read at the end of input in order to determine the
> + * stream durations. Used by avformat_find_stream_info() for MPEG-TS/PS.
let's clarify this: is there any reason why this should not be used
with other formats? If this the case, probably a private option would
be best. If not, probably we should amend the doxy as it suggests it
is only useful with MPEG TS/PS.
> + *
> + * Demuxing only, set by the caller before avformat_open_input().
> + */
> + int64_t duration_probesize;
> } AVFormatContext;
>
> /**
> diff --git a/libavformat/demux.c b/libavformat/demux.c
> index 6f640b92b1..798b44c979 100644
> --- a/libavformat/demux.c
> +++ b/libavformat/demux.c
> @@ -1740,8 +1740,9 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
> "Estimating duration from bitrate, this may be inaccurate\n");
> }
>
> -#define DURATION_MAX_READ_SIZE 250000LL
> -#define DURATION_MAX_RETRY 6
> +#define DURATION_MAX_READ_SIZE_DEFAULT 250000LL
> +#define DURATION_MAX_RETRY_DEFAULT 6
> +#define DURATION_MAX_RETRY_USER 1
>
> /* only usable for MPEG-PS streams */
> static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
> @@ -1749,6 +1750,8 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
> FFFormatContext *const si = ffformatcontext(ic);
> AVPacket *const pkt = si->pkt;
> int num, den, read_size, ret;
> + int64_t duration_max_read_size = ic->duration_probesize ? ic->duration_probesize >> DURATION_MAX_RETRY_USER : DURATION_MAX_READ_SIZE_DEFAULT;
> + int duration_max_retry = ic->duration_probesize ? DURATION_MAX_RETRY_USER : DURATION_MAX_RETRY_DEFAULT;
> int found_duration = 0;
> int is_end;
> int64_t filesize, offset, duration;
> @@ -1784,7 +1787,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
> filesize = ic->pb ? avio_size(ic->pb) : 0;
> do {
> is_end = found_duration;
> - offset = filesize - (DURATION_MAX_READ_SIZE << retry);
> + offset = filesize - (duration_max_read_size << retry);
> if (offset < 0)
> offset = 0;
>
> @@ -1793,7 +1796,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
> for (;;) {
> AVStream *st;
> FFStream *sti;
> - if (read_size >= DURATION_MAX_READ_SIZE << (FFMAX(retry - 1, 0)))
> + if (read_size >= duration_max_read_size << (FFMAX(retry - 1, 0)))
> break;
>
> do {
> @@ -1847,7 +1850,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
> }
> } while (!is_end &&
> offset &&
> - ++retry <= DURATION_MAX_RETRY);
> + ++retry <= duration_max_retry);
>
> av_opt_set_int(ic, "skip_changes", 0, AV_OPT_SEARCH_CHILDREN);
>
> diff --git a/libavformat/options_table.h b/libavformat/options_table.h
> index 91708de453..c2bdb484a7 100644
> --- a/libavformat/options_table.h
> +++ b/libavformat/options_table.h
> @@ -108,6 +108,7 @@ static const AVOption avformat_options[] = {
> {"max_streams", "maximum number of streams", OFFSET(max_streams), AV_OPT_TYPE_INT, { .i64 = 1000 }, 0, INT_MAX, D },
> {"skip_estimate_duration_from_pts", "skip duration calculation in estimate_timings_from_pts", OFFSET(skip_estimate_duration_from_pts), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D},
> {"max_probe_packets", "Maximum number of packets to probe a codec", OFFSET(max_probe_packets), AV_OPT_TYPE_INT, { .i64 = 2500 }, 0, INT_MAX, D },
> +{"durationprobesize", "maximum number of bytes to probe the stream durations", OFFSET(duration_probesize), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D},
duration_probesize? ... to probe the stream duration (why the plural?)
More information about the ffmpeg-devel
mailing list