PR #23043 opened by jberclaz URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23043 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23043.patch
Allow callers to set a deterministic `availabilityStartTime` and override `suggestedPresentationDelay` for dynamic DASH manifests. This is useful for live workflows that need stable MPD timing across encoder restarts or externally controlled live latency. **Verified with:** - `git diff --check forgejo-upstream/master..HEAD` - tools/patcheck - `make libavformat/dashenc.o` - `make -j$(nproc) ffmpeg` **Smoke-tested dynamic DASH output with:** - `availability_start_time_ms=1700000000000` - `suggested_presentation_delay=42` **Result:** - `availabilityStartTime="2023-11-14T22:13:20.000Z"` - `suggestedPresentationDelay="PT42.0S"` >From caaadb8545730464a76a3f577a50c6473122163d Mon Sep 17 00:00:00 2001 From: Jerome Berclaz <[email protected]> Date: Thu, 7 May 2026 12:47:24 -0700 Subject: [PATCH] avformat/dashenc: add options for live MPD timing Allow callers to set a deterministic availabilityStartTime and override suggestedPresentationDelay for dynamic DASH manifests. This is useful for live workflows that need stable MPD timing across encoder restarts or externally controlled live latency. Signed-off-by: Jerome Berclaz <[email protected]> --- doc/muxers.texi | 10 ++++++++++ libavformat/dashenc.c | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index d9e475dbf7..0c7039a8f5 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1330,11 +1330,21 @@ element. Imply that the @option{single_file} option is set to @var{true}. In the template, @code{$ext$} is replaced with the file name extension specific for the segment format. +@item availability_start_time_ms @var{milliseconds} +Set the MPD @code{availabilityStartTime} attribute as Unix epoch time in +milliseconds. If set to @code{0}, the wall clock is used when the first +packet is written. This is useful for live outputs that need a stable +availability start time across restarts. + @item streaming @var{bool} Enable or disable chunk streaming mode of output. In chunk streaming mode, each frame will be a @code{moof} fragment which forms a chunk. This is disabled by default. +@item suggested_presentation_delay @var{duration} +Set the MPD @code{suggestedPresentationDelay} attribute. If set to +@code{0}, the last segment duration is used. + @item target_latency @var{target_latency} Set an intended target latency in seconds for serving (fractional value can be set). Applicable only when the @option{streaming} and diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index da7725fc3f..5c46314213 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -200,6 +200,8 @@ typedef struct DASHContext { AVRational min_playback_rate; AVRational max_playback_rate; int64_t update_period; + int64_t availability_start_time_ms; + int64_t suggested_presentation_delay; } DASHContext; static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, @@ -1046,8 +1048,14 @@ static int write_manifest(AVFormatContext *s, int final) if (c->update_period) update_period = c->update_period; avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period); - if (!c->ldash) - avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE); + if (!c->ldash) { + if (c->suggested_presentation_delay) { + avio_printf(out, "\tsuggestedPresentationDelay=\""); + write_time(out, c->suggested_presentation_delay); + avio_printf(out, "\"\n"); + } else + avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE); + } if (c->availability_start_time[0]) avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time); format_date(now_str, sizeof(now_str), av_gettime()); @@ -1981,7 +1989,9 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) os->last_pts = pkt->pts; if (!c->availability_start_time[0]) { - int64_t start_time_us = av_gettime(); + int64_t start_time_us = c->availability_start_time_ms ? + c->availability_start_time_ms * 1000 : + av_gettime(); c->start_time_s = start_time_us / 1000000; format_date(c->availability_start_time, sizeof(c->availability_start_time), start_time_us); @@ -2266,7 +2276,9 @@ static const AVOption options[] = { { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E }, { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, + { "availability_start_time_ms", "set MPD availabilityStartTime as epoch milliseconds", OFFSET(availability_start_time_ms), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, E }, { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { "suggested_presentation_delay", "set MPD suggestedPresentationDelay", OFFSET(suggested_presentation_delay), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, E }, { "target_latency", "Set desired target latency for Low-latency dash", OFFSET(target_latency), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E }, { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E }, { "update_period", "Set the mpd update interval", OFFSET(update_period), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E}, -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
