[FFmpeg-devel] [PATCH] libavformat/mpegtsenc: improved cbr mode pcr accuracy

alex3d at netup.ru alex3d at netup.ru
Tue Jun 7 13:49:38 CEST 2016


From: Alex Shumsky <alexthreed at gmail.com>

---
 libavformat/mpegtsenc.c | 64 ++++++++++++++++++++++++++++---------------------
 1 file changed, 37 insertions(+), 27 deletions(-)

diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 93cbac1..b1ff82f 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -1061,18 +1061,17 @@ static void mpegts_insert_null_packet(AVFormatContext *s)
 }
 
 /* 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 pcr_pid, int pcr_cc)
 {
     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++ = pcr_pid >> 8;
+    *q++ = pcr_pid;
+    *q++ = 0x20 | pcr_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 */
@@ -1150,6 +1149,14 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
     int64_t pcr = -1; /* avoid warning */
     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 i;
+    MpegTSWriteStream *pcr_st = 0;
+    for (i = 0; i < s->nb_streams; i++) {
+        MpegTSWriteStream *st1 = s->streams[i]->priv_data;
+        if (st1->pid == ts_st->service->pcr_pid) {
+            pcr_st = st1;
+        }
+    }
 
     av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
     if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
@@ -1162,21 +1169,20 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
         force_pat = 0;
 
         write_pcr = 0;
-        if (ts_st->pid == ts_st->service->pcr_pid) {
-            if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames
-                ts_st->service->pcr_packet_count++;
-            if (ts_st->service->pcr_packet_count >=
-                ts_st->service->pcr_packet_period) {
-                ts_st->service->pcr_packet_count = 0;
-                write_pcr = 1;
-            }
+        if (ts->mux_rate > 1 || (is_start && ts_st->pid == ts_st->service->pcr_pid ) ) // VBR pcr period is based on frames
+            ts_st->service->pcr_packet_count++;
+        if (ts_st->service->pcr_packet_count >=
+            ts_st->service->pcr_packet_period) {
+            ts_st->service->pcr_packet_count = 0;
+            write_pcr = 1;
         }
 
-        if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
+        if (is_start && ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
             (dts - get_pcr(ts, s->pb) / 300) > delay) {
             /* pcr insert gets priority over null packet insert */
-            if (write_pcr)
-                mpegts_insert_pcr_only(s, st);
+
+            if (write_pcr && pcr_st)
+                mpegts_insert_pcr_only(s, pcr_st->pid, pcr_st->cc);
             else
                 mpegts_insert_null_packet(s);
             /* recalculate write_pcr and possibly retransmit si_info */
@@ -1201,17 +1207,21 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
             q = get_ts_payload_start(buf);
         }
         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 (ts->mux_rate > 1)
-                pcr = get_pcr(ts, s->pb);
-            else
-                pcr = (dts - delay) * 300;
-            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));
-            q = get_ts_payload_start(buf);
+            if (ts_st->pid == ts_st->service->pcr_pid) {
+                set_af_flag(buf, 0x10);
+                q = get_ts_payload_start(buf);
+                // add 11, pcr references the last byte of program clock reference base
+                if (ts->mux_rate > 1)
+                    pcr = get_pcr(ts, s->pb);
+                else
+                    pcr = (dts - delay) * 300;
+                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));
+                q = get_ts_payload_start(buf);
+            } else if (pcr_st) {
+                mpegts_insert_pcr_only(s, pcr_st->pid, pcr_st->cc);
+            }
         }
         if (is_start) {
             int pes_extension = 0;
-- 
1.9.1



More information about the ffmpeg-devel mailing list