[PR] add_mov_peek_fragment_end_into_FFOutputFormat (PR #24215)

stevenliu via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <[email protected]>
PR #24215 opened by stevenliu
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24215
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24215.patch

# Add regular muxer function pointers into FFOutputFormat

If the parent muxer wants to get the segment duration info from the child muxer,
it can just call this function.



>From 5cde9aaa1a0557160dc581d8a07d2073a214cc69 Mon Sep 17 00:00:00 2001
From: Steven Liu <[email protected]>
Date: Thu, 20 Aug 2026 17:57:02 +0800
Subject: [PATCH 1/2] avformat/mux: Add regular muxer function pointers for
 peek fragment end

Signed-off-by: Steven Liu <[email protected]>
---
 libavformat/movenc.c |  8 ++++++++
 libavformat/mux.h    | 15 +++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 367caecee9..36c407976c 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -9433,6 +9433,7 @@ const FFOutputFormat ff_mov_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE | AVFMT_VARIABLE_FPS,
@@ -9455,6 +9456,7 @@ const FFOutputFormat ff_tgp_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
@@ -9477,6 +9479,7 @@ const FFOutputFormat ff_mp4_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE | AVFMT_VARIABLE_FPS,
@@ -9498,6 +9501,7 @@ const FFOutputFormat ff_psp_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
@@ -9518,6 +9522,7 @@ const FFOutputFormat ff_tg2_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
@@ -9539,6 +9544,7 @@ const FFOutputFormat ff_ipod_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
@@ -9560,6 +9566,7 @@ const FFOutputFormat ff_ismv_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE,
@@ -9582,6 +9589,7 @@ const FFOutputFormat ff_f4v_muxer = {
     .init              = mov_init,
     .write_header      = mov_write_header,
     .write_packet      = mov_write_packet,
+    .peek_fragment_end = mov_peek_fragment_end,
     .write_trailer     = mov_write_trailer,
     .deinit            = mov_free,
     .p.flags           = AVFMT_GLOBALHEADER,
diff --git a/libavformat/mux.h b/libavformat/mux.h
index 0b69109174..c575e6d212 100644
--- a/libavformat/mux.h
+++ b/libavformat/mux.h
@@ -82,6 +82,21 @@ typedef struct FFOutputFormat {
      * data.
      */
     int (*write_packet)(AVFormatContext *, AVPacket *pkt);
+    /**
+     * Optional. Notify the muxer of the next packet to be written to
+     * stream_index, before the muxer is asked to flush (via a NULL packet
+     * to write_packet). This allows the muxer to finalize the current
+     * fragment using the exact timing of the next sample instead of
+     * relying on the duration of the last written packet.
+     *
+     * The packet is only peeked at: the muxer must not modify it and must
+     * not write it to the output. pkt->dts/pts are expressed in
+     * src_time_base.
+     *
+     * @return 1 if the hint was used, 0 if it was ignored, < 0 on error
+     */
+    int (*peek_fragment_end)(AVFormatContext *s, int stream_index,
+                             const AVPacket *pkt, AVRational src_time_base);
     int (*write_trailer)(AVFormatContext *);
     /**
      * A format-specific function for interleavement.
-- 
2.52.0


>From 231743ef77a69f0a7a2d53af8af78e7f8e51dbac Mon Sep 17 00:00:00 2001
From: Steven Liu <[email protected]>
Date: Thu, 20 Aug 2026 17:59:58 +0800
Subject: [PATCH 2/2] avformat/movenc: use peek_fragment_end instead of
 ff_mov_set_fragment_end_hint

As: wbs's and JEEB's better suggestion, patching it with a crude hack like
ff_mov_set_fragment_end_hint directly would violate the existing muxer layering.
The elegant solution is to extend FFOutputFormat with standard muxer function pointers,
which preserves the layering architecture.

Signed-off-by: Steven Liu <[email protected]>
---
 libavformat/hlsenc.c | 13 +++++--------
 libavformat/movenc.c |  2 +-
 libavformat/movenc.h |  3 ---
 3 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 4726a4a708..5b313edf00 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -53,9 +53,6 @@
 #include "hlsplaylist.h"
 #include "internal.h"
 #include "mux.h"
-#if CONFIG_MP4_MUXER
-#include "movenc.h"
-#endif
 #include "os_support.h"
 #include "url.h"
 
@@ -2523,11 +2520,11 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
         int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
         double cur_duration;
 
-#if CONFIG_MP4_MUXER
-        if (hls->segment_type == SEGMENT_TYPE_FMP4 && is_ref_pkt &&
-            pkt->dts != AV_NOPTS_VALUE)
-            ff_mov_set_fragment_end_hint(oc, stream_index, pkt, st->time_base);
-#endif
+        if (hls->segment_type == SEGMENT_TYPE_FMP4 && is_ref_pkt) {
+            const FFOutputFormat *fmt = ffofmt(oc->oformat);
+            if (fmt->peek_fragment_end)
+                fmt->peek_fragment_end(oc, stream_index, pkt, st->time_base);
+        }
         av_write_frame(oc, NULL); /* Flush any buffered data */
         new_start_pos = avio_tell(oc->pb);
         vs->size = new_start_pos - vs->start_pos;
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 36c407976c..d6a1523d1b 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -6948,7 +6948,7 @@ static int check_pkt(AVFormatContext *s, MOVTrack *trk, AVPacket *pkt)
     return 0;
 }
 
-int ff_mov_set_fragment_end_hint(AVFormatContext *s, int stream_index,
+static int mov_peek_fragment_end(AVFormatContext *s, int stream_index,
                                  const AVPacket *pkt, AVRational src_time_base)
 {
     MOVMuxContext *mov = s->priv_data;
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index c375659c93..5d1e7099b4 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -303,9 +303,6 @@ typedef struct MOVMuxContext {
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
 
-int ff_mov_set_fragment_end_hint(AVFormatContext *s, int stream_index,
-                                 const AVPacket *pkt, AVRational src_time_base);
-
 int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index);
 int ff_mov_add_hinted_packet(AVFormatContext *s, AVPacket *pkt,
                              int track_index, int sample,
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.