[FFmpeg-devel] [PATCH 09/10] avformat/mpegtsenc: support generating standalone PCR PID for m2ts
Marton Balint
cus at passwd.hu
Tue Nov 12 23:29:05 EET 2019
Signed-off-by: Marton Balint <cus at passwd.hu>
---
libavformat/mpegtsenc.c | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 2191c134ac..d8a74f4fe1 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -36,6 +36,8 @@
#define PCR_TIME_BASE 27000000
#define M2TS_DEFAULT_MUXRATE 54000000
+#define M2TS_PCR_PID 0x1001
+#define M2TS_PCR_RETRANS_TIME 50
/* write DVB SI sections */
@@ -99,6 +101,8 @@ typedef struct MpegTSWrite {
int m2ts_audio_pid;
int m2ts_subtitle_pid;
int m2ts_other_pid;
+ int64_t m2ts_pcr_period;
+ int64_t m2ts_last_pcr;
int pcr_period_ms;
#define MPEGTS_FLAG_REEMIT_PAT_PMT 0x01
@@ -769,7 +773,7 @@ static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid,
return NULL;
service->pmt.pid = ts->pmt_start_pid + ts->nb_services;
service->sid = sid;
- service->pcr_pid = 0x1fff;
+ service->pcr_pid = ts->m2ts_mode ? M2TS_PCR_PID : 0x1fff;
if (encode_str8(service->provider_name, provider_name) < 0 ||
encode_str8(service->name, service_name) < 0) {
av_log(s, AV_LOG_ERROR, "Too long service or provider name\n");
@@ -1031,7 +1035,11 @@ static int mpegts_init(AVFormatContext *s)
if (ts->copyts < 1)
ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
- select_pcr_streams(s);
+ ts->m2ts_pcr_period = av_rescale(ts->pcr_period_ms == -1 ? M2TS_PCR_RETRANS_TIME : ts->pcr_period_ms, PCR_TIME_BASE, 1000);
+ ts->m2ts_last_pcr = ts->first_pcr - ts->m2ts_pcr_period;
+
+ if (!ts->m2ts_mode)
+ select_pcr_streams(s);
ts->last_pat_ts = AV_NOPTS_VALUE;
ts->last_sdt_ts = AV_NOPTS_VALUE;
@@ -1115,24 +1123,23 @@ static void mpegts_insert_null_packet(AVFormatContext *s, int force)
}
/* Write a single transport stream packet with a PCR and no payload */
-static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
+static void mpegts_insert_pcr_only(AVFormatContext *s, int pid, int cc, int *discontinuity)
{
MpegTSWrite *ts = s->priv_data;
- MpegTSWriteStream *ts_st = st->priv_data;
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++ = pid >> 8;
+ *q++ = pid;
+ *q++ = 0x20 | cc; /* Adaptation only */
/* Continuity Count field does not increment (see 13818-1 section 2.4.3.3) */
*q++ = TS_PACKET_SIZE - 5; /* Adaptation Field Length */
*q++ = 0x10; /* Adaptation flags: PCR present */
- if (ts_st->discontinuity) {
+ if (discontinuity && *discontinuity) {
q[-1] |= 0x80;
- ts_st->discontinuity = 0;
+ *discontinuity = 0;
}
/* PCR coded into 6 bytes */
@@ -1143,6 +1150,12 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
write_packet(s, buf);
}
+static void mpegts_insert_pcr_only_for_stream(AVFormatContext *s, AVStream *st)
+{
+ MpegTSWriteStream *ts_st = st->priv_data;
+ mpegts_insert_pcr_only(s, ts_st->pid, ts_st->cc, &ts_st->discontinuity);
+}
+
static void write_pts(uint8_t *q, int fourbits, int64_t pts)
{
int val;
@@ -1237,6 +1250,11 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
pcr = get_pcr(ts, s->pb);
if (pcr >= ts->next_pcr) {
int64_t next_pcr = INT64_MAX;
+ if (ts->m2ts_mode) {
+ mpegts_insert_pcr_only(s, M2TS_PCR_PID, 0, NULL);
+ ts->m2ts_last_pcr = FFMAX(pcr - ts->m2ts_pcr_period, ts->m2ts_last_pcr + ts->m2ts_pcr_period);
+ next_pcr = FFMIN(next_pcr, ts->m2ts_last_pcr + ts->m2ts_pcr_period);
+ } else {
for (int i = 0; i < s->nb_streams; i++) {
/* Make the current stream the last, because for that we
* can insert the pcr into the payload later */
@@ -1247,7 +1265,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
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) {
- mpegts_insert_pcr_only(s, st2);
+ mpegts_insert_pcr_only_for_stream(s, st2);
pcr = get_pcr(ts, s->pb);
} else {
write_pcr = 1;
@@ -1256,12 +1274,13 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
next_pcr = FFMIN(next_pcr, ts_st2->last_pcr + ts_st2->pcr_period);
}
}
+ }
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);
+ mpegts_insert_pcr_only_for_stream(s, st);
else
mpegts_insert_null_packet(s, 0);
/* recalculate write_pcr and possibly retransmit si_info */
--
2.16.4
More information about the ffmpeg-devel
mailing list