--- /dev/null
+--- a/libavformat/mpegtsenc.c
++++ b/libavformat/mpegtsenc.c
+@@ -87,9 +87,11 @@
+ int64_t pat_period; /* PAT/PMT period in PCR time base */
+ int64_t nit_period; /* NIT period in PCR time base */
+ int nb_services;
+- int64_t first_pcr;
+ int first_dts_checked;
+- int64_t next_pcr;
++ int64_t pcr_pos, pcr;
++ int64_t first_pcr, next_pcr;
++ int64_t delay;
++ int pcr_stream_pid;
+ int mux_rate; ///< set to 1 when VBR
+ int pes_payload_size;
+ int64_t total_size;
+@@ -256,7 +258,7 @@
+ int data_st_warning;
+
+ int64_t pcr_period; /* PCR period in PCR time base */
+- int64_t last_pcr;
++ int64_t pcr_timer;
+
+ /* For Opus */
+ int opus_queued_samples;
+@@ -954,18 +956,18 @@
+ return 0;
+ }
+
+-static int64_t get_pcr(const MpegTSWrite *ts)
++static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
+ {
+- return av_rescale(ts->total_size + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
+- ts->first_pcr;
++ int64_t pos = avio_tell(pb) + 11;
++ return ts->pcr + (ts->mux_rate == 1 ? (pos - ts->pcr_pos) * 8 :
++ av_rescale(pos - ts->pcr_pos, 8 * PCR_TIME_BASE, ts->mux_rate));
+ }
+
+ static void write_packet(AVFormatContext *s, const uint8_t *packet)
+ {
+ MpegTSWrite *ts = s->priv_data;
+ if (ts->m2ts_mode) {
+- int64_t pcr = get_pcr(s->priv_data);
+- uint32_t tp_extra_header = pcr % 0x3fffffff;
++ uint32_t tp_extra_header = get_pcr(ts, s->pb) % 0x3fffffff;
+ tp_extra_header = AV_RB32(&tp_extra_header);
+ avio_write(s->pb, (unsigned char *) &tp_extra_header,
+ sizeof(tp_extra_header));
+@@ -1051,9 +1053,6 @@
+ else
+ ts_st->pcr_period = 1;
+ }
+-
+- // output a PCR as soon as possible
+- ts_st->last_pcr = ts->first_pcr - ts_st->pcr_period;
+ }
+
+ static void select_pcr_streams(AVFormatContext *s)
+@@ -1116,6 +1115,7 @@
+
+ if (s->max_delay < 0) /* Not set by the caller */
+ s->max_delay = 0;
++ ts->delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
+
+ // round up to a whole number of TS packets
+ ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14;
+@@ -1175,7 +1175,9 @@
+ /* MPEG pid values < 16 are reserved. Applications which set st->id in
+ * this range are assigned a calculated pid. */
+ if (st->id < 16) {
+- if (ts->m2ts_mode) {
++ if (ts->start_pid >= 0)
++ ts_st->pid = ts->start_pid + i;
++ else if (ts->m2ts_mode) {
+ switch (st->codecpar->codec_type) {
+ case AVMEDIA_TYPE_VIDEO:
+ ts_st->pid = ts->m2ts_video_pid++;
+@@ -1202,9 +1204,9 @@
+ av_log(s, AV_LOG_ERROR, "Cannot automatically assign PID for stream %d\n", st->index);
+ return AVERROR(EINVAL);
+ }
+- } else {
+- ts_st->pid = ts->start_pid + i;
+ }
++ else
++ ts_st->pid = START_PID + i;
+ } else {
+ ts_st->pid = st->id;
+ }
+@@ -1272,9 +1274,14 @@
+ ts->last_pat_ts = AV_NOPTS_VALUE;
+ ts->last_sdt_ts = AV_NOPTS_VALUE;
+ ts->last_nit_ts = AV_NOPTS_VALUE;
+- ts->pat_period = av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE);
+- ts->sdt_period = av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE);
+- ts->nit_period = av_rescale(ts->nit_period_us, PCR_TIME_BASE, AV_TIME_BASE);
++ ts->pat_period = ts->pat_period_us < 0 ? -1 :
++ av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE);
++ ts->sdt_period = ts->sdt_period_us < 0 ? -1 :
++ av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE);
++ ts->nit_period = ts->nit_period_us < 0 ? -1 :
++ av_rescale(ts->nit_period_us, PCR_TIME_BASE, AV_TIME_BASE);
++ ts->pcr = 0;
++ ts->pcr_pos = 0;
+
+ /* assign provider name */
+ provider = av_dict_get(s->metadata, "service_provider", NULL, 0);
+@@ -1290,8 +1297,8 @@
+ av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate);
+ av_log(s, AV_LOG_VERBOSE,
+ "sdt every %"PRId64" ms, pat/pmt every %"PRId64" ms",
+- av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE),
+- av_rescale(ts->pat_period, 1000, PCR_TIME_BASE));
++ ts->sdt_period < 0 ? -1 : av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE),
++ ts->pat_period < 0 ? -1 : av_rescale(ts->pat_period, 1000, PCR_TIME_BASE));
+ if (ts->flags & MPEGTS_FLAG_NIT)
+ av_log(s, AV_LOG_VERBOSE, ", nit every %"PRId64" ms", av_rescale(ts->nit_period, 1000, PCR_TIME_BASE));
+ av_log(s, AV_LOG_VERBOSE, "\n");
+@@ -1300,36 +1307,40 @@
+ }
+
+ /* send SDT, NIT, PAT and PMT tables regularly */
+-static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int force_nit, int64_t pcr)
++static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int force_nit)
+ {
+ MpegTSWrite *ts = s->priv_data;
+ int i;
+
+- if ((pcr != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
+- (pcr != AV_NOPTS_VALUE && pcr - ts->last_sdt_ts >= ts->sdt_period) ||
+- force_sdt
+- ) {
+- if (pcr != AV_NOPTS_VALUE)
+- ts->last_sdt_ts = FFMAX(pcr, ts->last_sdt_ts);
+- mpegts_write_sdt(s);
+- }
+- if ((pcr != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
+- (pcr != AV_NOPTS_VALUE && pcr - ts->last_pat_ts >= ts->pat_period) ||
+- force_pat) {
+- if (pcr != AV_NOPTS_VALUE)
+- ts->last_pat_ts = FFMAX(pcr, ts->last_pat_ts);
+- mpegts_write_pat(s);
+- for (i = 0; i < ts->nb_services; i++)
+- mpegts_write_pmt(s, ts->services[i]);
+- }
+- if ((pcr != AV_NOPTS_VALUE && ts->last_nit_ts == AV_NOPTS_VALUE) ||
+- (pcr != AV_NOPTS_VALUE && pcr - ts->last_nit_ts >= ts->nit_period) ||
+- force_nit
+- ) {
+- if (pcr != AV_NOPTS_VALUE)
+- ts->last_nit_ts = FFMAX(pcr, ts->last_nit_ts);
++ if (ts->sdt_period >= 0) {
++ int64_t pcr = get_pcr(ts, s->pb);
++ if (ts->last_sdt_ts == AV_NOPTS_VALUE || pcr >= ts->last_sdt_ts + ts->sdt_period)
++ force_sdt = 1;
++ if (force_sdt) {
++ ts->last_sdt_ts = pcr;
++ mpegts_write_sdt(s);
++ }
++ }
++ if (ts->pat_period >= 0) {
++ int64_t pcr = get_pcr(ts, s->pb);
++ if (ts->last_pat_ts == AV_NOPTS_VALUE || pcr >= ts->last_pat_ts + ts->pat_period)
++ force_pat = 1;
++ if (force_pat) {
++ ts->last_pat_ts = pcr;
++ mpegts_write_pat(s);
++ for (i = 0; i < ts->nb_services; i++)
++ mpegts_write_pmt(s, ts->services[i]);
++ }
++ }
++ if (ts->nit_period >= 0) {
++ int64_t pcr = get_pcr(ts, s->pb);
++ if (ts->last_nit_ts == AV_NOPTS_VALUE || pcr >= ts->last_nit_ts + ts->nit_period)
++ force_nit = 1;
++ if (force_nit) {
++ ts->last_nit_ts = pcr;
+ if (ts->flags & MPEGTS_FLAG_NIT)
+ mpegts_write_nit(s);
++ }
+ }
+ }
+
+@@ -1366,25 +1377,29 @@
+ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
+ {
+ MpegTSWrite *ts = s->priv_data;
+- MpegTSWriteStream *ts_st = st->priv_data;
++ int64_t pcr = get_pcr(ts, s->pb);
++ MpegTSWriteStream *ts_st = st ? st->priv_data : 0;
++ uint32_t pcr_pid = ts_st ? ts_st->pid : ts->pcr_stream_pid;
+ uint8_t *q;
+ uint8_t buf[TS_PACKET_SIZE];
+
+ q = buf;
+ *q++ = 0x47;
+- *q++ = ts_st->pid >> 8;
+- *q++ = ts_st->pid;
+- *q++ = 0x20 | ts_st->cc; /* Adaptation only */
++ *q++ = pcr_pid >> 8;
++ *q++ = pcr_pid;
++ uint32_t flags = 0x20; /* Adaptation only */
+ /* Continuity Count field does not increment (see 13818-1 section 2.4.3.3) */
++ if(ts_st) flags |= ts_st->cc;
++ *q++ = flags;
+ *q++ = TS_PACKET_SIZE - 5; /* Adaptation Field Length */
+ *q++ = 0x10; /* Adaptation flags: PCR present */
+- if (ts_st->discontinuity) {
++ if (ts_st && ts_st->discontinuity) {
+ q[-1] |= 0x80;
+ ts_st->discontinuity = 0;
+ }
+
+ /* PCR coded into 6 bytes */
+- q += write_pcr_bits(q, get_pcr(ts));
++ q += write_pcr_bits(q, pcr);
+
+ /* stuffing bytes */
+ memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
+@@ -1485,9 +1500,9 @@
+ int afc_len, stuffing_len;
+ int is_dvb_subtitle = (st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE);
+ int is_dvb_teletext = (st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT);
+- int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
+ int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
+ int force_sdt = 0;
++ int64_t pcr;
+ int force_nit = 0;
+
+ av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
+@@ -1504,21 +1519,19 @@
+
+ is_start = 1;
+ while (payload_size > 0) {
+- int64_t pcr = AV_NOPTS_VALUE;
+- if (ts->mux_rate > 1)
+- pcr = get_pcr(ts);
+- else if (dts != AV_NOPTS_VALUE)
+- pcr = (dts - delay) * 300;
+-
+- retransmit_si_info(s, force_pat, force_sdt, force_nit, pcr);
+- force_pat = 0;
+- force_sdt = 0;
+- force_nit = 0;
++ // add 11, pcr references the last byte of program clock reference base
++ ts->pcr_pos = avio_tell(s->pb) + 11;
++ pcr = ts->pcr = ts->mux_rate != 1 ?
++ av_rescale(ts->pcr_pos, 8 * PCR_TIME_BASE, ts->mux_rate) :
++ (dts == AV_NOPTS_VALUE ? 0 : (dts - ts->delay) * 300);
++ if (force_pat || force_sdt || force_nit) {
++ retransmit_si_info(s, force_pat, force_sdt, force_nit);
++ force_pat = force_sdt = force_nit = 0;
++ }
+
+ write_pcr = 0;
+ if (ts->mux_rate > 1) {
+ /* Send PCR packets for all PCR streams if needed */
+- pcr = get_pcr(ts);
+ if (pcr >= ts->next_pcr) {
+ int64_t next_pcr = INT64_MAX;
+ for (int i = 0; i < s->nb_streams; i++) {
+@@ -1528,36 +1541,43 @@
+ AVStream *st2 = s->streams[st2_index];
+ MpegTSWriteStream *ts_st2 = st2->priv_data;
+ if (ts_st2->pcr_period) {
+- if (pcr - ts_st2->last_pcr >= ts_st2->pcr_period) {
+- ts_st2->last_pcr = FFMAX(pcr - ts_st2->pcr_period, ts_st2->last_pcr + ts_st2->pcr_period);
+- if (st2 != st) {
++ if (pcr >= ts_st2->pcr_timer) {
++ ts_st2->pcr_timer = pcr + ts_st2->pcr_period;
++ if (st2 != st) {
+ mpegts_insert_pcr_only(s, st2);
+- pcr = get_pcr(ts);
+ } else {
+ write_pcr = 1;
+ }
+ }
+- next_pcr = FFMIN(next_pcr, ts_st2->last_pcr + ts_st2->pcr_period);
++ next_pcr = FFMIN(next_pcr, ts_st2->pcr_timer);
+ }
+ }
+ ts->next_pcr = next_pcr;
+ }
+- if (dts != AV_NOPTS_VALUE && (dts - pcr / 300) > delay) {
+- /* pcr insert gets priority over null packet insert */
+- if (write_pcr)
+- mpegts_insert_pcr_only(s, st);
+- else
+- mpegts_insert_null_packet(s);
+- /* recalculate write_pcr and possibly retransmit si_info */
+- continue;
+- }
+- } else if (ts_st->pcr_period && pcr != AV_NOPTS_VALUE) {
+- if (pcr - ts_st->last_pcr >= ts_st->pcr_period && is_start) {
+- ts_st->last_pcr = FFMAX(pcr - ts_st->pcr_period, ts_st->last_pcr + ts_st->pcr_period);
++ }
++ else if (ts_st->pcr_period) {
++ if (pcr >= ts_st->pcr_timer) {
++ ts_st->pcr_timer = pcr + ts_st->pcr_period;
+ write_pcr = 1;
+ }
+ }
+
++ if (write_pcr && ts->pcr_stream_pid >= 0) {
++ mpegts_insert_pcr_only(s, 0);
++ continue;
++ }
++
++ if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
++ (dts - pcr / 300) > ts->delay) {
++ /* pcr insert gets priority over null packet insert */
++ if (write_pcr)
++ mpegts_insert_pcr_only(s, st);
++ else
++ mpegts_insert_null_packet(s);
++ /* recalculate write_pcr and possibly retransimit si_info */
++ continue;
++ }
++
+ /* prepare packet header */
+ q = buf;
+ *q++ = 0x47;
+@@ -1587,7 +1607,6 @@
+ if (write_pcr) {
+ set_af_flag(buf, 0x10);
+ q = get_ts_payload_start(buf);
+- // add 11, pcr references the last byte of program clock reference base
+ if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
+ av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
+ extend_af(buf, write_pcr_bits(q, pcr));
+@@ -1851,8 +1870,8 @@
+ uint8_t *data = NULL;
+ MpegTSWrite *ts = s->priv_data;
+ MpegTSWriteStream *ts_st = st->priv_data;
+- const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2;
+- const int64_t max_audio_delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) / 2;
++ const int64_t delay_ticks2 = ts->delay * 2;
++ const int64_t max_audio_delay = ts->delay / 2;
+ int64_t dts = pkt->dts, pts = pkt->pts;
+ int opus_samples = 0;
+ size_t side_data_size;
+@@ -1872,9 +1891,9 @@
+
+ if (ts->copyts < 1) {
+ if (pts != AV_NOPTS_VALUE)
+- pts += delay;
++ pts += delay_ticks2;
+ if (dts != AV_NOPTS_VALUE)
+- dts += delay;
++ dts += delay_ticks2;
+ }
+
+ if (!ts_st->first_timestamp_checked && (pts == AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE)) {
+@@ -2305,8 +2324,10 @@
+ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" },
+ { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
+ OFFSET(pmt_start_pid), AV_OPT_TYPE_INT, { .i64 = 0x1000 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC },
++ { "mpegts_pcr_stream_pid", "create seperate PCR stream on this pid.",
++ OFFSET(pcr_stream_pid), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 0x1f00, ENC },
+ { "mpegts_start_pid", "Set the first pid.",
+- OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = 0x0100 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC },
++ OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, LAST_OTHER_PID, ENC },
+ { "mpegts_m2ts_mode", "Enable m2ts mode.", OFFSET(m2ts_mode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC },
+ { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC },
+ { "pes_payload_size", "Minimum PES packet payload in bytes",
+@@ -2332,10 +2353,10 @@
+ OFFSET(omit_video_pes_length), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC },
+ { "pcr_period", "PCR retransmission time in milliseconds",
+ OFFSET(pcr_period_ms), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC },
+- { "pat_period", "PAT/PMT retransmission time limit in seconds",
++ { "pat_period", "PAT/PMT retransmission time limit in ms, -1 no pat",
+ OFFSET(pat_period_us), AV_OPT_TYPE_DURATION, { .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
+- { "sdt_period", "SDT retransmission time limit in seconds",
+- OFFSET(sdt_period_us), AV_OPT_TYPE_DURATION, { .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
++ { "sdt_period", "SDT retransmission time limit in ms, -1 no sdt",
++ OFFSET(sdt_period_us), AV_OPT_TYPE_INT64, { .i64 = SDT_RETRANS_TIME * 1000LL }, -1, INT64_MAX, ENC },
+ { "nit_period", "NIT retransmission time limit in seconds",
+ OFFSET(nit_period_us), AV_OPT_TYPE_DURATION, { .i64 = NIT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC },
+ { NULL },
+--- a/libavformat/mpegts.h
++++ b/libavformat/mpegts.h
+@@ -64,6 +64,7 @@
+ /* PID from 0x1FFC to 0x1FFE may be assigned as needed to PMT, elementary
+ * streams and other data tables */
+ #define NULL_PID 0x1FFF /* Null packet (used for fixed bandwidth padding) */
++#define START_PID 0x0400
+
+ /* m2ts pids */
+ #define M2TS_PMT_PID 0x0100
+--- a/libavformat/bluray.c
++++ b/libavformat/bluray.c
+@@ -27,7 +27,7 @@
+ #include "libavutil/opt.h"
+
+ #define BLURAY_PROTO_PREFIX "bluray:"
+-#define MIN_PLAYLIST_LENGTH 180 /* 3 min */
++#define MIN_PLAYLIST_LENGTH 0
+
+ typedef struct {
+ const AVClass *class;
+
+--- a/doc/muxers.texi
++++ b/doc/muxers.texi
+@@ -1932,7 +1932,8 @@
+ Maximum time in seconds between PAT/PMT tables. Default is @code{0.1}.
+
+ @item sdt_period @var{duration}
+-Maximum time in seconds between SDT tables. Default is @code{0.5}.
++Maximum time in seconds between SDT tables. Default is @code{0.5}. Regardless
++of this setting no SDT is written in m2ts mode.
+
+ @item nit_period @var{duration}
+ Maximum time in seconds between NIT tables. Default is @code{0.5}.