From: Ingo Oppermann <ingo@datarhei.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: Re: [FFmpeg-devel] [PATCH v1] avformat/hlsenc: add hls_min_time to enforce minimal segment duration Date: Wed, 29 Jan 2025 14:47:11 +0100 Message-ID: <30A7C76B-9B51-4BB4-86AD-363F027B12DD@datarhei.com> (raw) In-Reply-To: <CADxeRwm9=M=omrXAYrEW-x+hoa_aJtjgS0=SMY=ui5w6KsjgjQ@mail.gmail.com> On 29 Jan 2025, at 14:09, Steven Liu <lingjiujianke@gmail.com> wrote: > > > > Ingo Oppermann <ingo@datarhei.com>于2025年1月29日 周三17:54写道: > Hi Ingo, > > Great job, thanks for your valuable patch, > The current implementation of the hls_time might produce segments > with shorter duration in some cases. With the hls_min_time option > a minimal segment duration will be enforced. > > Instead of changing the current behaviour of hls_time which might > break existing workflows, the new option hls_min_time will override > hls_time and enforce a minimal segment duration. > > I think the ‘enforce’ unnecessary, because this should support as split by time or split by keyframe. Is this your implementing direction? If split by keyframe the option name should modify to a new name. Apologies I did not catch my computers back to my Inner-Mongolia home Chinese new year Hollidays, will back to Peking maybe after 6 days, so response maybe have some delayed. Thanks for your thoughts. The implementation direction is to split by keyframe. It is actually fixing what hls_time should already do. "enforce" might suggest something different. I guess "guarantee" would be more suitable. > > > hls_time is supposed to define the minimum length of a segment, > however this is not respected in all cases when a stream has variable > GOP sizes. > > Imagine a stream starts with a key frame every 10 seconds for > e.g. 30 seconds. After that, key frames will come every second. This > will result in segments that are first 10 seconds (as expected), then > 1 second for some time (not as expected) and later 2 seconds (as > expected). > > How to reproduce: > ffmpeg -t 30 -f lavfi -i testsrc2 -codec:v libx264 -g 250 part1.mp4 > ffmpeg -t 30 -f lavfi -i testsrc2 -codec:v libx264 -g 25 part2.mp4 > echo "file part1.mp4\nfile part2.mp4" > list.txt > ffmpeg -f concat -i list.txt -codec copy \ > -f hls -hls_time 2 -hls_list_size 0 parts.m3u8 > cat parts.m3u8 > > Signed-off-by: Ingo Oppermann <ingo@datarhei.com> > --- > doc/muxers.texi | 7 +++++++ > libavformat/hlsenc.c | 27 ++++++++++++++++++++------- > 2 files changed, 27 insertions(+), 7 deletions(-) > > diff --git a/doc/muxers.texi b/doc/muxers.texi > index 04b7f20b7e..e058a8f8c0 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -1929,6 +1929,13 @@ Set the target segment length. Default value is 2. > see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}. > Segment will be cut on the next key frame after this time has passed. > > +@item hls_min_time @var{duration} > +Set the minimum target segment length. Default value is 0. > + > +@var{duration} must be a time duration specification, > +see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}. > +Segment will be at least this long and will be cut at the following key frame. If set, it will override @option{hls_time}. > + > @item hls_list_size @var{size} > Set the maximum number of playlist entries. If set to 0 the list file > will contain all the segments. Default value is 5. > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c > index 6148685f40..5fc215fdce 100644 > --- a/libavformat/hlsenc.c > +++ b/libavformat/hlsenc.c > @@ -204,6 +204,7 @@ typedef struct HLSContext { > uint32_t start_sequence_source_type; // enum StartSequenceSourceType > > int64_t time; // Set by a private option. > + int64_t min_time; // Set by a private option. > int64_t init_time; // Set by a private option. > int max_nb_segments; // Set by a private option. > int hls_delete_threshold; // Set by a private option. > @@ -2474,7 +2475,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) > HLSContext *hls = s->priv_data; > AVFormatContext *oc = NULL; > AVStream *st = s->streams[pkt->stream_index]; > - int64_t end_pts = 0; > + int64_t end_pts = 0, current_pts; > int is_ref_pkt = 1; > int ret = 0, can_split = 1, i, j; > int stream_index = 0; > @@ -2515,11 +2516,16 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) > end_pts = hls->recording_time * vs->number; > > if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) { > - /* reset end_pts, hls->recording_time at end of the init hls list */ > - int64_t init_list_dur = hls->init_time * vs->nb_entries; > - int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time; > - hls->recording_time = hls->time; > - end_pts = init_list_dur + after_init_list_dur ; > + if (hls->min_time > 0) { > + hls->recording_time = hls->min_time; > + hls->init_time = 0; > + } else { > + /* reset end_pts, hls->recording_time at end of the init hls list */ > + int64_t init_list_dur = hls->init_time * vs->nb_entries; > + int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time; > + hls->recording_time = hls->time; > + end_pts = init_list_dur + after_init_list_dur; > + } > } > > if (vs->start_pts == AV_NOPTS_VALUE) { > @@ -2559,8 +2565,14 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) > } > } > > + current_pts = pkt->pts - vs->start_pts; > + if (hls->min_time > 0 && hls->init_time == 0) { > + current_pts = pkt->pts - vs->end_pts; > + end_pts = hls->min_time; > + } > + > can_split = can_split && (pkt->pts - vs->end_pts > 0); > - if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base, > + if (vs->packets_written && can_split && av_compare_ts(current_pts, st->time_base, > end_pts, AV_TIME_BASE_Q) >= 0) { > int64_t new_start_pos; > int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); > @@ -3182,6 +3194,7 @@ static int hls_init(AVFormatContext *s) > static const AVOption options[] = { > {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E}, > {"hls_time", "set segment length", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64 = 2000000}, 0, INT64_MAX, E}, > + {"hls_min_time", "set minimum segment length", OFFSET(min_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E}, > {"hls_init_time", "set segment length at init list", OFFSET(init_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E}, > {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E}, > {"hls_delete_threshold", "set number of unreferenced segments to keep before deleting", OFFSET(hls_delete_threshold), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, E}, > > base-commit: 3380c0d27df1e07f009e114da98fb8033c2ce33d > -- > 2.39.5 (Apple Git-154) > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". > > Thanks > Steven _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
prev parent reply other threads:[~2025-01-29 13:47 UTC|newest] Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-01-29 9:54 Ingo Oppermann 2025-01-29 13:09 ` Steven Liu 2025-01-29 13:47 ` Ingo Oppermann [this message]
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=30A7C76B-9B51-4BB4-86AD-363F027B12DD@datarhei.com \ --to=ingo@datarhei.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git