1 diff -u a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
2 --- a/libavformat/mpegtsenc.c 2020-06-15 12:54:24.000000000 -0600
3 +++ b/libavformat/mpegtsenc.c 2020-10-15 12:16:07.300442476 -0600
5 int64_t sdt_period; /* SDT period in PCR time base */
6 int64_t pat_period; /* PAT/PMT 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;
28 static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
30 - return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
32 + int64_t pos = avio_tell(pb) + 11;
33 + return ts->pcr + (ts->mux_rate == 1 ? (pos - ts->pcr_pos) * 8 :
34 + av_rescale(pos - ts->pcr_pos, 8 * PCR_TIME_BASE, ts->mux_rate));
37 static void write_packet(AVFormatContext *s, const uint8_t *packet)
39 MpegTSWrite *ts = s->priv_data;
41 - int64_t pcr = get_pcr(s->priv_data, s->pb);
42 - uint32_t tp_extra_header = pcr % 0x3fffffff;
43 + uint32_t tp_extra_header = get_pcr(ts, s->pb) % 0x3fffffff;
44 tp_extra_header = AV_RB32(&tp_extra_header);
45 avio_write(s->pb, (unsigned char *) &tp_extra_header,
46 sizeof(tp_extra_header));
49 ts_st->pcr_period = 1;
52 - // output a PCR as soon as possible
53 - ts_st->last_pcr = ts->first_pcr - ts_st->pcr_period;
56 static void select_pcr_streams(AVFormatContext *s)
59 if (s->max_delay < 0) /* Not set by the caller */
61 + ts->delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
63 // round up to a whole number of TS packets
64 ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14;
66 /* MPEG pid values < 16 are reserved. Applications which set st->id in
67 * this range are assigned a calculated pid. */
69 - if (ts->m2ts_mode) {
70 + if (ts->start_pid >= 0)
71 + ts_st->pid = ts->start_pid + i;
72 + else if (ts->m2ts_mode) {
73 switch (st->codecpar->codec_type) {
74 case AVMEDIA_TYPE_VIDEO:
75 ts_st->pid = ts->m2ts_video_pid++;
77 av_log(s, AV_LOG_ERROR, "Cannot automatically assign PID for stream %d\n", st->index);
78 return AVERROR(EINVAL);
81 - ts_st->pid = ts->start_pid + i;
84 + ts_st->pid = START_PID + i;
88 @@ -1109,8 +1111,12 @@
90 ts->last_pat_ts = AV_NOPTS_VALUE;
91 ts->last_sdt_ts = AV_NOPTS_VALUE;
92 - ts->pat_period = av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE);
93 - ts->sdt_period = av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE);
94 + ts->pat_period = ts->pat_period_us < 0 ? -1 :
95 + av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE);
96 + ts->sdt_period = ts->sdt_period_us < 0 ? -1 :
97 + av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE);
101 if (ts->mux_rate == 1)
102 av_log(s, AV_LOG_VERBOSE, "muxrate VBR, ");
103 @@ -1118,34 +1124,37 @@
104 av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate);
105 av_log(s, AV_LOG_VERBOSE,
106 "sdt every %"PRId64" ms, pat/pmt every %"PRId64" ms\n",
107 - av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE),
108 - av_rescale(ts->pat_period, 1000, PCR_TIME_BASE));
109 + ts->sdt_period < 0 ? -1 : av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE),
110 + ts->pat_period < 0 ? -1 : av_rescale(ts->pat_period, 1000, PCR_TIME_BASE));
115 /* send SDT, PAT and PMT tables regularly */
116 -static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int64_t pcr)
117 +static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt)
119 MpegTSWrite *ts = s->priv_data;
122 - if ((pcr != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
123 - (pcr != AV_NOPTS_VALUE && pcr - ts->last_sdt_ts >= ts->sdt_period) ||
126 - if (pcr != AV_NOPTS_VALUE)
127 - ts->last_sdt_ts = FFMAX(pcr, ts->last_sdt_ts);
128 - mpegts_write_sdt(s);
130 - if ((pcr != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
131 - (pcr != AV_NOPTS_VALUE && pcr - ts->last_pat_ts >= ts->pat_period) ||
133 - if (pcr != AV_NOPTS_VALUE)
134 - ts->last_pat_ts = FFMAX(pcr, ts->last_pat_ts);
135 - mpegts_write_pat(s);
136 - for (i = 0; i < ts->nb_services; i++)
137 - mpegts_write_pmt(s, ts->services[i]);
138 + if (ts->sdt_period >= 0) {
139 + int64_t pcr = get_pcr(ts, s->pb);
140 + if (ts->last_sdt_ts == AV_NOPTS_VALUE || pcr >= ts->last_sdt_ts + ts->sdt_period)
143 + ts->last_sdt_ts = pcr;
144 + mpegts_write_sdt(s);
147 + if (ts->pat_period >= 0) {
148 + int64_t pcr = get_pcr(ts, s->pb);
149 + if (ts->last_pat_ts == AV_NOPTS_VALUE || pcr >= ts->last_pat_ts + ts->pat_period)
152 + ts->last_pat_ts = pcr;
153 + mpegts_write_pat(s);
154 + for (i = 0; i < ts->nb_services; i++)
155 + mpegts_write_pmt(s, ts->services[i]);
160 @@ -1182,25 +1191,29 @@
161 static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
163 MpegTSWrite *ts = s->priv_data;
164 - MpegTSWriteStream *ts_st = st->priv_data;
165 + int64_t pcr = get_pcr(ts, s->pb);
166 + MpegTSWriteStream *ts_st = st ? st->priv_data : 0;
167 + uint32_t pcr_pid = ts_st ? ts_st->pid : ts->pcr_stream_pid;
169 uint8_t buf[TS_PACKET_SIZE];
173 - *q++ = ts_st->pid >> 8;
175 - *q++ = 0x20 | ts_st->cc; /* Adaptation only */
176 + *q++ = pcr_pid >> 8;
178 + uint32_t flags = 0x20; /* Adaptation only */
179 /* Continuity Count field does not increment (see 13818-1 section 2.4.3.3) */
180 + if(ts_st) flags |= ts_st->cc;
182 *q++ = TS_PACKET_SIZE - 5; /* Adaptation Field Length */
183 *q++ = 0x10; /* Adaptation flags: PCR present */
184 - if (ts_st->discontinuity) {
185 + if (ts_st && ts_st->discontinuity) {
187 ts_st->discontinuity = 0;
190 /* PCR coded into 6 bytes */
191 - q += write_pcr_bits(q, get_pcr(ts, s->pb));
192 + q += write_pcr_bits(q, pcr);
195 memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
196 @@ -1268,9 +1281,9 @@
198 int val, is_start, len, header_len, write_pcr, is_dvb_subtitle, is_dvb_teletext, flags;
199 int afc_len, stuffing_len;
200 - int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
201 int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
205 av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
206 if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
207 @@ -1285,20 +1298,19 @@
210 while (payload_size > 0) {
211 - int64_t pcr = AV_NOPTS_VALUE;
212 - if (ts->mux_rate > 1)
213 - pcr = get_pcr(ts, s->pb);
214 - else if (dts != AV_NOPTS_VALUE)
215 - pcr = (dts - delay) * 300;
217 - retransmit_si_info(s, force_pat, force_sdt, pcr);
220 + // add 11, pcr references the last byte of program clock reference base
221 + ts->pcr_pos = avio_tell(s->pb) + 11;
222 + pcr = ts->pcr = ts->mux_rate != 1 ?
223 + av_rescale(ts->pcr_pos, 8 * PCR_TIME_BASE, ts->mux_rate) :
224 + (dts == AV_NOPTS_VALUE ? 0 : (dts - ts->delay) * 300);
225 + if (force_pat || force_sdt) {
226 + retransmit_si_info(s, force_pat, force_sdt);
227 + force_pat = force_sdt = 0;
231 if (ts->mux_rate > 1) {
232 /* Send PCR packets for all PCR streams if needed */
233 - pcr = get_pcr(ts, s->pb);
234 if (pcr >= ts->next_pcr) {
235 int64_t next_pcr = INT64_MAX;
236 for (int i = 0; i < s->nb_streams; i++) {
237 @@ -1308,36 +1320,43 @@
238 AVStream *st2 = s->streams[st2_index];
239 MpegTSWriteStream *ts_st2 = st2->priv_data;
240 if (ts_st2->pcr_period) {
241 - if (pcr - ts_st2->last_pcr >= ts_st2->pcr_period) {
242 - ts_st2->last_pcr = FFMAX(pcr - ts_st2->pcr_period, ts_st2->last_pcr + ts_st2->pcr_period);
243 + if (pcr >= ts_st2->pcr_timer) {
244 + ts_st2->pcr_timer = pcr + ts_st2->pcr_period;
246 mpegts_insert_pcr_only(s, st2);
247 - pcr = get_pcr(ts, s->pb);
252 - next_pcr = FFMIN(next_pcr, ts_st2->last_pcr + ts_st2->pcr_period);
253 + next_pcr = FFMIN(next_pcr, ts_st2->pcr_timer);
256 ts->next_pcr = next_pcr;
258 - if (dts != AV_NOPTS_VALUE && (dts - pcr / 300) > delay) {
259 - /* pcr insert gets priority over null packet insert */
261 - mpegts_insert_pcr_only(s, st);
263 - mpegts_insert_null_packet(s);
264 - /* recalculate write_pcr and possibly retransmit si_info */
267 - } else if (ts_st->pcr_period && pcr != AV_NOPTS_VALUE) {
268 - if (pcr - ts_st->last_pcr >= ts_st->pcr_period && is_start) {
269 - ts_st->last_pcr = FFMAX(pcr - ts_st->pcr_period, ts_st->last_pcr + ts_st->pcr_period);
271 + else if (ts_st->pcr_period) {
272 + if (pcr >= ts_st->pcr_timer) {
273 + ts_st->pcr_timer = pcr + ts_st->pcr_period;
278 + if (write_pcr && ts->pcr_stream_pid >= 0) {
279 + mpegts_insert_pcr_only(s, 0);
283 + if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
284 + (dts - pcr / 300) > ts->delay) {
285 + /* pcr insert gets priority over null packet insert */
287 + mpegts_insert_pcr_only(s, st);
289 + mpegts_insert_null_packet(s);
290 + /* recalculate write_pcr and possibly retransimit si_info */
294 /* prepare packet header */
297 @@ -1365,7 +1384,6 @@
299 set_af_flag(buf, 0x10);
300 q = get_ts_payload_start(buf);
301 - // add 11, pcr references the last byte of program clock reference base
302 if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
303 av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
304 extend_af(buf, write_pcr_bits(q, pcr));
305 @@ -1643,8 +1661,8 @@
306 uint8_t *data = NULL;
307 MpegTSWrite *ts = s->priv_data;
308 MpegTSWriteStream *ts_st = st->priv_data;
309 - const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2;
310 - const int64_t max_audio_delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) / 2;
311 + const int64_t delay_ticks2 = ts->delay * 2;
312 + const int64_t max_audio_delay = ts->delay / 2;
313 int64_t dts = pkt->dts, pts = pkt->pts;
314 int opus_samples = 0;
316 @@ -1659,9 +1677,9 @@
318 if (ts->copyts < 1) {
319 if (pts != AV_NOPTS_VALUE)
321 + pts += delay_ticks2;
322 if (dts != AV_NOPTS_VALUE)
324 + dts += delay_ticks2;
327 if (ts_st->first_pts_check && pts == AV_NOPTS_VALUE) {
328 @@ -1998,8 +2016,10 @@
329 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" },
330 { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
331 OFFSET(pmt_start_pid), AV_OPT_TYPE_INT, { .i64 = 0x1000 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC },
332 + { "mpegts_pcr_stream_pid", "create seperate PCR stream on this pid.",
333 + offsetof(MpegTSWrite, pcr_stream_pid), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 0x1f00, ENC },
334 { "mpegts_start_pid", "Set the first pid.",
335 - OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = 0x0100 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC },
336 + OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, LAST_OTHER_PID, ENC },
337 { "mpegts_m2ts_mode", "Enable m2ts mode.", OFFSET(m2ts_mode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC },
338 { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC },
339 { "pes_payload_size", "Minimum PES packet payload in bytes",
340 @@ -2021,10 +2041,10 @@
341 OFFSET(omit_video_pes_length), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC },
342 { "pcr_period", "PCR retransmission time in milliseconds",
343 OFFSET(pcr_period_ms), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC },
344 - { "pat_period", "PAT/PMT retransmission time limit in seconds",
345 + { "pat_period", "PAT/PMT retransmission time limit in ms, -1 no pat",
346 OFFSET(pat_period_us), AV_OPT_TYPE_DURATION, { .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
347 - { "sdt_period", "SDT retransmission time limit in seconds",
348 - OFFSET(sdt_period_us), AV_OPT_TYPE_DURATION, { .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
349 + { "sdt_period", "SDT retransmission time limit in ms, -1 no sdt",
350 + OFFSET(sdt_period_us), AV_OPT_TYPE_INT64, { .i64 = SDT_RETRANS_TIME * 1000LL }, -1, INT64_MAX, ENC },
354 diff -u a/libavformat/mpegts.h b/libavformat/mpegts.h
355 --- a/libavformat/mpegts.h 2020-10-15 12:32:22.417967898 -0600
356 +++ b/libavformat/mpegts.h 2020-10-15 12:32:46.463055553 -0600
358 /* PID from 0x1FFC to 0x1FFE may be assigned as needed to PMT, elementary
359 * streams and other data tables */
360 #define NULL_PID 0x1FFF /* Null packet (used for fixed bandwidth padding) */
361 +#define START_PID 0x0400
364 #define M2TS_PMT_PID 0x0100