1 --- a/libavformat/mpegtsenc.c 2023-05-25 11:35:50.216478386 -0600
2 +++ b/libavformat/mpegtsenc.c 2023-05-25 11:36:49.259182848 -0600
4 int64_t pat_period; /* PAT/PMT period in PCR time base */
5 int64_t nit_period; /* NIT period in PCR time base */
10 + int64_t pcr_pos, pcr;
11 + int64_t first_pcr, next_pcr;
14 int mux_rate; ///< set to 1 when VBR
20 int64_t pcr_period; /* PCR period in PCR time base */
25 int opus_queued_samples;
30 -static int64_t get_pcr(const MpegTSWrite *ts)
31 +static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
33 - return av_rescale(ts->total_size + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
35 + int64_t pos = avio_tell(pb) + 11;
36 + return ts->pcr + (ts->mux_rate == 1 ? (pos - ts->pcr_pos) * 8 :
37 + av_rescale(pos - ts->pcr_pos, 8 * PCR_TIME_BASE, ts->mux_rate));
40 static void write_packet(AVFormatContext *s, const uint8_t *packet)
42 MpegTSWrite *ts = s->priv_data;
44 - int64_t pcr = get_pcr(s->priv_data);
45 - uint32_t tp_extra_header = pcr % 0x3fffffff;
46 + uint32_t tp_extra_header = get_pcr(ts, s->pb) % 0x3fffffff;
47 tp_extra_header = AV_RB32(&tp_extra_header);
48 avio_write(s->pb, (unsigned char *) &tp_extra_header,
49 sizeof(tp_extra_header));
52 ts_st->pcr_period = 1;
55 - // output a PCR as soon as possible
56 - ts_st->last_pcr = ts->first_pcr - ts_st->pcr_period;
59 static void select_pcr_streams(AVFormatContext *s)
62 if (s->max_delay < 0) /* Not set by the caller */
64 + ts->delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
66 // round up to a whole number of TS packets
67 ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14;
69 /* MPEG pid values < 16 are reserved. Applications which set st->id in
70 * this range are assigned a calculated pid. */
72 - if (ts->m2ts_mode) {
73 + if (ts->start_pid >= 0)
74 + ts_st->pid = ts->start_pid + i;
75 + else if (ts->m2ts_mode) {
76 switch (st->codecpar->codec_type) {
77 case AVMEDIA_TYPE_VIDEO:
78 ts_st->pid = ts->m2ts_video_pid++;
80 av_log(s, AV_LOG_ERROR, "Cannot automatically assign PID for stream %d\n", st->index);
81 return AVERROR(EINVAL);
84 - ts_st->pid = ts->start_pid + i;
87 + ts_st->pid = START_PID + i;
91 @@ -1267,9 +1269,14 @@
92 ts->last_pat_ts = AV_NOPTS_VALUE;
93 ts->last_sdt_ts = AV_NOPTS_VALUE;
94 ts->last_nit_ts = AV_NOPTS_VALUE;
95 - ts->pat_period = av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE);
96 - ts->sdt_period = av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE);
97 - ts->nit_period = av_rescale(ts->nit_period_us, PCR_TIME_BASE, AV_TIME_BASE);
98 + ts->pat_period = ts->pat_period_us < 0 ? -1 :
99 + av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE);
100 + ts->sdt_period = ts->sdt_period_us < 0 ? -1 :
101 + av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE);
102 + ts->nit_period = ts->nit_period_us < 0 ? -1 :
103 + av_rescale(ts->nit_period_us, PCR_TIME_BASE, AV_TIME_BASE);
107 /* assign provider name */
108 provider = av_dict_get(s->metadata, "service_provider", NULL, 0);
109 @@ -1285,8 +1292,8 @@
110 av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate);
111 av_log(s, AV_LOG_VERBOSE,
112 "sdt every %"PRId64" ms, pat/pmt every %"PRId64" ms",
113 - av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE),
114 - av_rescale(ts->pat_period, 1000, PCR_TIME_BASE));
115 + ts->sdt_period < 0 ? -1 : av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE),
116 + ts->pat_period < 0 ? -1 : av_rescale(ts->pat_period, 1000, PCR_TIME_BASE));
117 if (ts->flags & MPEGTS_FLAG_NIT)
118 av_log(s, AV_LOG_VERBOSE, ", nit every %"PRId64" ms", av_rescale(ts->nit_period, 1000, PCR_TIME_BASE));
119 av_log(s, AV_LOG_VERBOSE, "\n");
120 @@ -1295,36 +1302,40 @@
123 /* send SDT, NIT, PAT and PMT tables regularly */
124 -static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int force_nit, int64_t pcr)
125 +static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int force_nit)
127 MpegTSWrite *ts = s->priv_data;
130 - if ((pcr != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
131 - (pcr != AV_NOPTS_VALUE && pcr - ts->last_sdt_ts >= ts->sdt_period) ||
134 - if (pcr != AV_NOPTS_VALUE)
135 - ts->last_sdt_ts = FFMAX(pcr, ts->last_sdt_ts);
136 - mpegts_write_sdt(s);
138 - if ((pcr != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
139 - (pcr != AV_NOPTS_VALUE && pcr - ts->last_pat_ts >= ts->pat_period) ||
141 - if (pcr != AV_NOPTS_VALUE)
142 - ts->last_pat_ts = FFMAX(pcr, ts->last_pat_ts);
143 - mpegts_write_pat(s);
144 - for (i = 0; i < ts->nb_services; i++)
145 - mpegts_write_pmt(s, ts->services[i]);
147 - if ((pcr != AV_NOPTS_VALUE && ts->last_nit_ts == AV_NOPTS_VALUE) ||
148 - (pcr != AV_NOPTS_VALUE && pcr - ts->last_nit_ts >= ts->nit_period) ||
151 - if (pcr != AV_NOPTS_VALUE)
152 - ts->last_nit_ts = FFMAX(pcr, ts->last_nit_ts);
153 + if (ts->sdt_period >= 0) {
154 + int64_t pcr = get_pcr(ts, s->pb);
155 + if (ts->last_sdt_ts == AV_NOPTS_VALUE || pcr >= ts->last_sdt_ts + ts->sdt_period)
158 + ts->last_sdt_ts = pcr;
159 + mpegts_write_sdt(s);
162 + if (ts->pat_period >= 0) {
163 + int64_t pcr = get_pcr(ts, s->pb);
164 + if (ts->last_pat_ts == AV_NOPTS_VALUE || pcr >= ts->last_pat_ts + ts->pat_period)
167 + ts->last_pat_ts = pcr;
168 + mpegts_write_pat(s);
169 + for (i = 0; i < ts->nb_services; i++)
170 + mpegts_write_pmt(s, ts->services[i]);
173 + if (ts->nit_period >= 0) {
174 + int64_t pcr = get_pcr(ts, s->pb);
175 + if (ts->last_nit_ts == AV_NOPTS_VALUE || pcr >= ts->last_nit_ts + ts->nit_period)
178 + ts->last_nit_ts = pcr;
179 if (ts->flags & MPEGTS_FLAG_NIT)
185 @@ -1361,25 +1372,29 @@
186 static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
188 MpegTSWrite *ts = s->priv_data;
189 - MpegTSWriteStream *ts_st = st->priv_data;
190 + int64_t pcr = get_pcr(ts, s->pb);
191 + MpegTSWriteStream *ts_st = st ? st->priv_data : 0;
192 + uint32_t pcr_pid = ts_st ? ts_st->pid : ts->pcr_stream_pid;
194 uint8_t buf[TS_PACKET_SIZE];
198 - *q++ = ts_st->pid >> 8;
200 - *q++ = 0x20 | ts_st->cc; /* Adaptation only */
201 + *q++ = pcr_pid >> 8;
203 + uint32_t flags = 0x20; /* Adaptation only */
204 /* Continuity Count field does not increment (see 13818-1 section 2.4.3.3) */
205 + if(ts_st) flags |= ts_st->cc;
207 *q++ = TS_PACKET_SIZE - 5; /* Adaptation Field Length */
208 *q++ = 0x10; /* Adaptation flags: PCR present */
209 - if (ts_st->discontinuity) {
210 + if (ts_st && ts_st->discontinuity) {
212 ts_st->discontinuity = 0;
215 /* PCR coded into 6 bytes */
216 - q += write_pcr_bits(q, get_pcr(ts));
217 + q += write_pcr_bits(q, pcr);
220 memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
221 @@ -1479,9 +1494,9 @@
222 int afc_len, stuffing_len;
223 int is_dvb_subtitle = (st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE);
224 int is_dvb_teletext = (st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT);
225 - int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
226 int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
231 av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
232 @@ -1498,21 +1513,19 @@
235 while (payload_size > 0) {
236 - int64_t pcr = AV_NOPTS_VALUE;
237 - if (ts->mux_rate > 1)
239 - else if (dts != AV_NOPTS_VALUE)
240 - pcr = (dts - delay) * 300;
242 - retransmit_si_info(s, force_pat, force_sdt, force_nit, pcr);
246 + // add 11, pcr references the last byte of program clock reference base
247 + ts->pcr_pos = avio_tell(s->pb) + 11;
248 + pcr = ts->pcr = ts->mux_rate != 1 ?
249 + av_rescale(ts->pcr_pos, 8 * PCR_TIME_BASE, ts->mux_rate) :
250 + (dts == AV_NOPTS_VALUE ? 0 : (dts - ts->delay) * 300);
251 + if (force_pat || force_sdt || force_nit) {
252 + retransmit_si_info(s, force_pat, force_sdt, force_nit);
253 + force_pat = force_sdt = force_nit = 0;
257 if (ts->mux_rate > 1) {
258 /* Send PCR packets for all PCR streams if needed */
260 if (pcr >= ts->next_pcr) {
261 int64_t next_pcr = INT64_MAX;
262 for (int i = 0; i < s->nb_streams; i++) {
263 @@ -1522,36 +1535,43 @@
264 AVStream *st2 = s->streams[st2_index];
265 MpegTSWriteStream *ts_st2 = st2->priv_data;
266 if (ts_st2->pcr_period) {
267 - if (pcr - ts_st2->last_pcr >= ts_st2->pcr_period) {
268 - ts_st2->last_pcr = FFMAX(pcr - ts_st2->pcr_period, ts_st2->last_pcr + ts_st2->pcr_period);
270 + if (pcr >= ts_st2->pcr_timer) {
271 + ts_st2->pcr_timer = pcr + ts_st2->pcr_period;
273 mpegts_insert_pcr_only(s, st2);
279 - next_pcr = FFMIN(next_pcr, ts_st2->last_pcr + ts_st2->pcr_period);
280 + next_pcr = FFMIN(next_pcr, ts_st2->pcr_timer);
283 ts->next_pcr = next_pcr;
285 - if (dts != AV_NOPTS_VALUE && (dts - pcr / 300) > delay) {
286 - /* pcr insert gets priority over null packet insert */
288 - mpegts_insert_pcr_only(s, st);
290 - mpegts_insert_null_packet(s);
291 - /* recalculate write_pcr and possibly retransmit si_info */
294 - } else if (ts_st->pcr_period && pcr != AV_NOPTS_VALUE) {
295 - if (pcr - ts_st->last_pcr >= ts_st->pcr_period && is_start) {
296 - ts_st->last_pcr = FFMAX(pcr - ts_st->pcr_period, ts_st->last_pcr + ts_st->pcr_period);
298 + else if (ts_st->pcr_period) {
299 + if (pcr >= ts_st->pcr_timer) {
300 + ts_st->pcr_timer = pcr + ts_st->pcr_period;
305 + if (write_pcr && ts->pcr_stream_pid >= 0) {
306 + mpegts_insert_pcr_only(s, 0);
310 + if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
311 + (dts - pcr / 300) > ts->delay) {
312 + /* pcr insert gets priority over null packet insert */
314 + mpegts_insert_pcr_only(s, st);
316 + mpegts_insert_null_packet(s);
317 + /* recalculate write_pcr and possibly retransimit si_info */
321 /* prepare packet header */
324 @@ -1581,7 +1601,6 @@
326 set_af_flag(buf, 0x10);
327 q = get_ts_payload_start(buf);
328 - // add 11, pcr references the last byte of program clock reference base
329 if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
330 av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
331 extend_af(buf, write_pcr_bits(q, pcr));
332 @@ -1845,8 +1864,8 @@
333 uint8_t *data = NULL;
334 MpegTSWrite *ts = s->priv_data;
335 MpegTSWriteStream *ts_st = st->priv_data;
336 - const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2;
337 - const int64_t max_audio_delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) / 2;
338 + const int64_t delay_ticks2 = ts->delay * 2;
339 + const int64_t max_audio_delay = ts->delay / 2;
340 int64_t dts = pkt->dts, pts = pkt->pts;
341 int opus_samples = 0;
342 size_t side_data_size;
343 @@ -1866,9 +1885,9 @@
345 if (ts->copyts < 1) {
346 if (pts != AV_NOPTS_VALUE)
348 + pts += delay_ticks2;
349 if (dts != AV_NOPTS_VALUE)
351 + dts += delay_ticks2;
354 if (!ts_st->first_timestamp_checked && (pts == AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE)) {
355 @@ -2299,8 +2318,10 @@
356 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" },
357 { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
358 OFFSET(pmt_start_pid), AV_OPT_TYPE_INT, { .i64 = 0x1000 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC },
359 + { "mpegts_pcr_stream_pid", "create seperate PCR stream on this pid.",
360 + OFFSET(pcr_stream_pid), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 0x1f00, ENC },
361 { "mpegts_start_pid", "Set the first pid.",
362 - OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = 0x0100 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC },
363 + OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, LAST_OTHER_PID, ENC },
364 { "mpegts_m2ts_mode", "Enable m2ts mode.", OFFSET(m2ts_mode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC },
365 { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC },
366 { "pes_payload_size", "Minimum PES packet payload in bytes",
367 @@ -2326,10 +2347,10 @@
368 OFFSET(omit_video_pes_length), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC },
369 { "pcr_period", "PCR retransmission time in milliseconds",
370 OFFSET(pcr_period_ms), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC },
371 - { "pat_period", "PAT/PMT retransmission time limit in seconds",
372 + { "pat_period", "PAT/PMT retransmission time limit in ms, -1 no pat",
373 OFFSET(pat_period_us), AV_OPT_TYPE_DURATION, { .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
374 - { "sdt_period", "SDT retransmission time limit in seconds",
375 - OFFSET(sdt_period_us), AV_OPT_TYPE_DURATION, { .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
376 + { "sdt_period", "SDT retransmission time limit in ms, -1 no sdt",
377 + OFFSET(sdt_period_us), AV_OPT_TYPE_INT64, { .i64 = SDT_RETRANS_TIME * 1000LL }, -1, INT64_MAX, ENC },
378 { "nit_period", "NIT retransmission time limit in seconds",
379 OFFSET(nit_period_us), AV_OPT_TYPE_DURATION, { .i64 = NIT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
381 --- a/libavformat/mpegts.h
382 +++ b/libavformat/mpegts.h
384 /* PID from 0x1FFC to 0x1FFE may be assigned as needed to PMT, elementary
385 * streams and other data tables */
386 #define NULL_PID 0x1FFF /* Null packet (used for fixed bandwidth padding) */
387 +#define START_PID 0x0400
390 #define M2TS_PMT_PID 0x0100
391 --- a/libavformat/bluray.c
392 +++ b/libavformat/bluray.c
394 #include "libavutil/opt.h"
396 #define BLURAY_PROTO_PREFIX "bluray:"
397 -#define MIN_PLAYLIST_LENGTH 180 /* 3 min */
398 +#define MIN_PLAYLIST_LENGTH 0
401 const AVClass *class;
403 --- a/doc/muxers.texi
404 +++ b/doc/muxers.texi
405 @@ -1930,7 +1930,8 @@
406 Maximum time in seconds between PAT/PMT tables. Default is @code{0.1}.
408 @item sdt_period @var{duration}
409 -Maximum time in seconds between SDT tables. Default is @code{0.5}.
410 +Maximum time in seconds between SDT tables. Default is @code{0.5}. Regardless
411 +of this setting no SDT is written in m2ts mode.
413 @item nit_period @var{duration}
414 Maximum time in seconds between NIT tables. Default is @code{0.5}.