1- From 763304129a1fb2e347c870b1250b90a696ee4317 Mon Sep 17 00:00:00 2001
1+ From 014b594a77161a7b4ffb5d63846547bb176fe6ba Mon Sep 17 00:00:00 2001
22From: Ingo Oppermann <
[email protected] >
3- Date: Mon, 20 Jan 2025 17:32:20 +0100
4- Subject: [PATCH v3 ] hls (7.1.0 )
3+ Date: Wed, 22 Oct 2025 17:28:57 +0200
4+ Subject: [PATCH v2 ] hls (7.1.1 )
55
66---
7- README.HLS.md | 48 +++++++ ++++++++++++++++++++
8- libavformat/hlsenc.c | 79 + +++++++++++++++++++++++++++++++++++++++++--
9- 2 files changed, 125 insertions(+), 2 deletions(-)
7+ README.HLS.md | 48 ++++++++++++++++++++
8+ libavformat/hlsenc.c | 104 +++++++++++++++++++++++++++++++++++++++++--
9+ 2 files changed, 149 insertions(+), 3 deletions(-)
1010 create mode 100644 README.HLS.md
1111
1212diff --git a/README.HLS.md b/README.HLS.md
@@ -64,18 +64,26 @@ index 00000000..5462338b
6464+
6565+ In the command, the `-var_stream_map` option had the value `v:0,a:0 v:1,a:1`.
6666diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
67- index 1e932b7b..11a3f0dd 100644
67+ index 081d91f7..14fa5480 100644
6868--- a/libavformat/hlsenc.c
6969+++ b/libavformat/hlsenc.c
70- @@ -125,6 +125,7 @@ typedef struct VariantStream {
70+ @@ -109,6 +109,7 @@ typedef enum HLSFlags {
71+ HLS_PERIODIC_REKEY = (1 << 12),
72+ HLS_INDEPENDENT_SEGMENTS = (1 << 13),
73+ HLS_I_FRAMES_ONLY = (1 << 14),
74+ + HLS_ADJUST_SEQUENCE = (1 << 15),
75+ } HLSFlags;
76+
77+ typedef enum {
78+ @@ -125,6 +126,7 @@ typedef struct VariantStream {
7179 AVIOContext *out;
7280 AVIOContext *out_single_file;
7381 int packets_written;
7482+ uint64_t bytes_written;
7583 int init_range_length;
7684 uint8_t *temp_buffer;
7785 uint8_t *init_buffer;
78- @@ -139,6 +140 ,8 @@ typedef struct VariantStream {
86+ @@ -139,6 +141 ,8 @@ typedef struct VariantStream {
7987 double dpp; // duration per packet
8088 int64_t start_pts;
8189 int64_t end_pts;
@@ -84,14 +92,26 @@ index 1e932b7b..11a3f0dd 100644
8492 int64_t video_lastpos;
8593 int64_t video_keyframe_pos;
8694 int64_t video_keyframe_size;
87- @@ -1507,6 +1510,16 @@ static int create_master_playlist(AVFormatContext *s,
95+ @@ -1503,12 +1507,28 @@ static int create_master_playlist(AVFormatContext *s,
96+ if (final) {
97+ bandwidth = vs->max_bitrate;
98+ avg_bandwidth = vs->avg_bitrate;
99+ + if (avg_bandwidth < 0) {
100+ + avg_bandwidth = 0;
101+ + }
102+ } else {
103+ bandwidth = 0;
104+ if (vid_st)
88105 bandwidth += get_stream_bit_rate(vid_st);
89106 if (aud_st)
90107 bandwidth += get_stream_bit_rate(aud_st);
91108+
92109+ if (bandwidth == 0) {
93110+ // Estimate bandwidth
94111+ bandwidth = (int)round((double)vs->bytes_written / (av_q2d(AV_TIME_BASE_Q) * (vs->scaled_cur_pts - vs->scaled_start_pts)) * 8);
112+ + if (bandwidth < 0) {
113+ + bandwidth = 0;
114+ + }
95115+
96116+ // Reset counters
97117+ vs->bytes_written = 0;
@@ -101,7 +121,33 @@ index 1e932b7b..11a3f0dd 100644
101121 bandwidth += bandwidth / 10;
102122 }
103123
104- @@ -2475,6 +2488,19 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
124+ @@ -2439,7 +2459,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
125+ HLSContext *hls = s->priv_data;
126+ AVFormatContext *oc = NULL;
127+ AVStream *st = s->streams[pkt->stream_index];
128+ - int64_t end_pts = 0;
129+ + int64_t end_pts = 0, max_sequence = 0;
130+ int is_ref_pkt = 1;
131+ int ret = 0, can_split = 1, i, j;
132+ int stream_index = 0;
133+ @@ -2449,6 +2469,16 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
134+ VariantStream *vs = NULL;
135+ char *old_filename = NULL;
136+
137+ + if (hls->flags & HLS_ADJUST_SEQUENCE) {
138+ + for (i = 0; i < hls->nb_varstreams; i++) {
139+ + vs = &hls->var_streams[i];
140+ +
141+ + if (vs->sequence > max_sequence) {
142+ + max_sequence = vs->sequence;
143+ + }
144+ + }
145+ + }
146+ +
147+ for (i = 0; i < hls->nb_varstreams; i++) {
148+ int subtitle_streams = 0;
149+ vs = &hls->var_streams[i];
150+ @@ -2477,6 +2507,19 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
105151 return AVERROR(ENOMEM);
106152 }
107153
@@ -121,7 +167,7 @@ index 1e932b7b..11a3f0dd 100644
121167 end_pts = hls->recording_time * vs->number;
122168
123169 if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
124- @@ -2523 ,8 +2549 ,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
170+ @@ -2525 ,8 +2568 ,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
125171 }
126172
127173 can_split = can_split && (pkt->pts - vs->end_pts > 0);
@@ -132,15 +178,27 @@ index 1e932b7b..11a3f0dd 100644
132178 int64_t new_start_pos;
133179 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
134180 double cur_duration;
135- @@ -2700,6 +2726,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
181+ @@ -2643,6 +2686,11 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
182+
183+ cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
184+ ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size);
185+ + if ((hls->flags & HLS_ADJUST_SEQUENCE) && vs->sequence < max_sequence) {
186+ + av_log(s, AV_LOG_WARNING, "fixing sequence number of variant %s.\n", vs->m3u8_name);
187+ + vs->sequence = max_sequence + 1;
188+ + vs->discontinuity = 1;
189+ + }
190+ vs->end_pts = pkt->pts;
191+ vs->duration = 0;
192+ if (ret < 0) {
193+ @@ -2702,6 +2750,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
136194 }
137195
138196 vs->packets_written++;
139197+ vs->bytes_written += (uint64_t)pkt->size;
140198 if (oc->pb) {
141199 ret = ff_write_chained(oc, stream_index, pkt, s, 0);
142200 vs->video_keyframe_size += pkt->size;
143- @@ -2888 ,6 +2915 ,49 @@ failed:
201+ @@ -2890 ,6 +2939 ,49 @@ failed:
144202 return 0;
145203 }
146204
@@ -190,7 +248,7 @@ index 1e932b7b..11a3f0dd 100644
190248
191249 static int hls_init(AVFormatContext *s)
192250 {
193- @@ -2995 ,6 +3065 ,8 @@ static int hls_init(AVFormatContext *s)
251+ @@ -2997 ,6 +3089 ,8 @@ static int hls_init(AVFormatContext *s)
194252 vs->sequence = hls->start_sequence;
195253 vs->start_pts = AV_NOPTS_VALUE;
196254 vs->end_pts = AV_NOPTS_VALUE;
@@ -199,7 +257,7 @@ index 1e932b7b..11a3f0dd 100644
199257 vs->current_segment_final_filename_fmt[0] = '\0';
200258 vs->initial_prog_date_time = initial_program_date_time;
201259
202- @@ -3137 ,6 +3209 ,9 @@ static int hls_init(AVFormatContext *s)
260+ @@ -3139 ,6 +3233 ,9 @@ static int hls_init(AVFormatContext *s)
203261 vs->number++;
204262 }
205263
@@ -209,8 +267,16 @@ index 1e932b7b..11a3f0dd 100644
209267 return ret;
210268 }
211269
270+ @@ -3183,6 +3280,7 @@ static const AVOption options[] = {
271+ {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, .unit = "flags"},
272+ {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, .unit = "flags"},
273+ {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, .unit = "flags"},
274+ + {"adjust_sequence", "adjust sequence numbers of variants if they diverge", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_ADJUST_SEQUENCE }, 0, UINT_MAX, E, .unit = "flags"},
275+ {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
276+ {"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
277+ {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, .unit = "pl_type" },
212278
213- base-commit: e1601d14100f6c7d088eba676d9555118ca94931
279+ base-commit: c526666f8869a5fffb04fbfeb862cde13338b001
214280- -
215- 2.39.5 (Apple Git-154 )
281+ 2.50.1 (Apple Git-155 )
216282
0 commit comments