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]

Reply via email to