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]

Reply via email to