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]
