This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

The following commit(s) were added to refs/heads/master by this push:
     new 468a743af1 avformat/dashenc: add options for live MPD timing
468a743af1 is described below

commit 468a743af1653a08f47081aa0a18dc6dacff543a
Author:     Jerome Berclaz <[email protected]>
AuthorDate: Thu May 21 08:40:19 2026 -0700
Commit:     michaelni <[email protected]>
CommitDate: Fri May 29 03:25:53 2026 +0000

    avformat/dashenc: add options for live MPD timing
---
 doc/muxers.texi                | 10 ++++++++++
 libavformat/dashenc.c          | 21 ++++++++++++++++++---
 tests/Makefile                 |  1 +
 tests/fate/dashenc.mak         | 28 ++++++++++++++++++++++++++++
 tests/ref/fate/dash-mpd-timing |  2 ++
 5 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 26199ad836..b2c02fb906 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 1b9c6a601f..a0417dc73e 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -71,6 +71,8 @@ enum {
 
 #define MPD_PROFILE_DASH 1
 #define MPD_PROFILE_DVB  2
+#define DASH_MAX_AVAILABILITY_START_TIME_MS (INT64_MAX / 1000)
+#define DASH_MAX_SUGGESTED_PRESENTATION_DELAY ((int64_t)INT_MAX * AV_TIME_BASE 
+ AV_TIME_BASE - 1)
 
 typedef struct Segment {
     char file[1024];
@@ -200,6 +202,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 +1050,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());
@@ -1982,9 +1992,12 @@ static int dash_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 
     if (!c->availability_start_time[0]) {
         int64_t start_time_us = av_gettime();
+        int64_t mpd_start_time_us = c->availability_start_time_ms ?
+                                    c->availability_start_time_ms * 1000 :
+                                    start_time_us;
         c->start_time_s = start_time_us / 1000000;
         format_date(c->availability_start_time,
-                    sizeof(c->availability_start_time), start_time_us);
+                    sizeof(c->availability_start_time), mpd_start_time_us);
     }
 
     if (!os->packets_written)
@@ -2266,7 +2279,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, DASH_MAX_AVAILABILITY_START_TIME_MS, 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, 
DASH_MAX_SUGGESTED_PRESENTATION_DELAY, 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},
diff --git a/tests/Makefile b/tests/Makefile
index 26b29c72d2..585d0bd3c7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -175,6 +175,7 @@ include $(SRC_PATH)/tests/fate/checkasm.mak
 # Must be included after lavf-container.mak
 include $(SRC_PATH)/tests/fate/concatdec.mak
 include $(SRC_PATH)/tests/fate/cover-art.mak
+include $(SRC_PATH)/tests/fate/dashenc.mak
 include $(SRC_PATH)/tests/fate/dca.mak
 include $(SRC_PATH)/tests/fate/demux.mak
 include $(SRC_PATH)/tests/fate/dfa.mak
diff --git a/tests/fate/dashenc.mak b/tests/fate/dashenc.mak
new file mode 100644
index 0000000000..df9571f0b4
--- /dev/null
+++ b/tests/fate/dashenc.mak
@@ -0,0 +1,28 @@
+tests/data/dash_mpd_timing.mpd: TAG = GEN
+tests/data/dash_mpd_timing.mpd: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data
+       $(RM) $(TARGET_PATH)/tests/data/dash_mpd_timing*
+       $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin -loglevel error -re \
+       -f lavfi -i "testsrc2=size=128x72:rate=1" -map 0:v \
+       -c:v mpeg4 -g 1 -streaming 1 -window_size 5 \
+       -availability_start_time_ms 1700000000123 -suggested_presentation_delay 
2s \
+       -f dash $(TARGET_PATH)/tests/data/dash_mpd_timing.mpd & \
+       pid=$$!; \
+       i=0; \
+       while ! test -s $(TARGET_PATH)/tests/data/dash_mpd_timing.mpd && test 
$$i -lt 100; do \
+           sleep 0.1; \
+           i=$$((i + 1)); \
+       done; \
+       test -s $(TARGET_PATH)/tests/data/dash_mpd_timing.mpd; \
+       cp $(TARGET_PATH)/tests/data/dash_mpd_timing.mpd 
$(TARGET_PATH)/tests/data/dash_mpd_timing.live.mpd; \
+       kill $$pid 2>/dev/null || true; \
+       wait $$pid 2>/dev/null || true; \
+       cp $(TARGET_PATH)/tests/data/dash_mpd_timing.live.mpd 
$(TARGET_PATH)/tests/data/dash_mpd_timing.mpd; \
+       test -s $(TARGET_PATH)/tests/data/dash_mpd_timing.mpd
+
+FATE_DASHENC_LAVFI-$(call ALLYES, TESTSRC2_FILTER LAVFI_INDEV MPEG4_ENCODER 
DASH_MUXER MP4_MUXER FILE_PROTOCOL) += fate-dash-mpd-timing
+fate-dash-mpd-timing: tests/data/dash_mpd_timing.mpd
+fate-dash-mpd-timing: CMD = sed -n -e /suggestedPresentationDelay=/p -e 
/availabilityStartTime=/p $(TARGET_PATH)/tests/data/dash_mpd_timing.mpd
+fate-dash-mpd-timing: CMP = diff
+
+FATE_FFMPEG += $(FATE_DASHENC_LAVFI-yes)
+fate-dashenc: $(FATE_DASHENC_LAVFI-yes)
diff --git a/tests/ref/fate/dash-mpd-timing b/tests/ref/fate/dash-mpd-timing
new file mode 100644
index 0000000000..b725ba9182
--- /dev/null
+++ b/tests/ref/fate/dash-mpd-timing
@@ -0,0 +1,2 @@
+       suggestedPresentationDelay="PT2.0S"
+       availabilityStartTime="2023-11-14T22:13:20.123Z"

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to