diff mbox

[FFmpeg-devel] libavformat: add multiple PCR streams in MPEGTS muxer

Message ID 4907da416549f55665f564b255368d043984@guerrillamail.com
State New
Headers show

Commit Message

fix45u+5vw5dhzga3hjs@guerrillamail.com Oct. 27, 2018, 8:35 p.m. UTC
From 44c9f3d96c5969349bd2dc4d63e9a8b8e6b5a0e2 Mon Sep 17 00:00:00 2001
From: M. Sanders <hidden at gmail.com>
Date: Sat, 27 Oct 2018 21:39:44 +0200
Subject: [PATCH] libavformat: add multiple PCR streams in MPEGTS muxer

---
This simple patch adds two new options to the MPEG-TS muxer.
You can use them to mark PCRs in additional VIDEO and/or AUDIO streams.
It's useful when you will remux the output with pid filtering tools.
For example, if you put PCR in all audio streams, then you can filter 
each audio stream to create a radio service.
PCR marks do not disturb outgoing stream, but it is not recommended 
to do so as a regular rule.

 doc/muxers.texi         |  6 ++++++
 libavformat/mpegtsenc.c | 19 +++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/doc/muxers.texi b/doc/muxers.texi
index f18543e83d..328707d0ed 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -1528,6 +1528,12 @@  is @code{-1}, which results in shifting timestamps so that they start from 0.
 @item omit_video_pes_length @var{boolean}
 Omit the PES packet length for video packets. Default is @code{1} (true).
 
+@item pcr_all_video @var{boolean}
+Include PCR values in all video streams. Default is @code{0} (false).
+
+@item pcr_all_audio @var{boolean}
+Include PCR values in all audio streams. Default is @code{0} (false).
+
 @item pcr_period @var{integer}
 Override the default PCR retransmission time in milliseconds. Ignored if
 variable muxrate is selected. Default is @code{20}.
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 3339e26d50..caef817a3d 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -113,6 +113,8 @@  typedef struct MpegTSWrite {
     double sdt_period;
     int64_t last_pat_ts;
     int64_t last_sdt_ts;
+    int pcr_all_video;
+    int pcr_all_audio;
 
     int omit_video_pes_length;
 } MpegTSWrite;
@@ -1178,11 +1180,18 @@  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 force_pcr = 0;
 
     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) {
         force_pat = 1;
     }
+    if (ts->pcr_all_video && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+        force_pcr = 1;
+    }
+    if (ts->pcr_all_audio && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+        force_pcr = 1;
+    }
 
     is_start = 1;
     while (payload_size > 0) {
@@ -1190,7 +1199,7 @@  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_st->pid == ts_st->service->pcr_pid || force_pcr) {
             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 >=
@@ -1228,7 +1237,7 @@  static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
         }
         if (key && is_start && pts != AV_NOPTS_VALUE) {
             // set Random Access for key frames
-            if (ts_st->pid == ts_st->service->pcr_pid)
+            if (ts_st->pid == ts_st->service->pcr_pid || force_pcr)
                 write_pcr = 1;
             set_af_flag(buf, 0x40);
             q = get_ts_payload_start(buf);
@@ -1951,6 +1960,12 @@  static const AVOption options[] = {
     { "omit_video_pes_length", "Omit the PES packet length for video packets",
       offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_BOOL,
       { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
+    { "pcr_all_video", "Include PCR values in all video streams",
+      offsetof(MpegTSWrite, pcr_all_video), AV_OPT_TYPE_BOOL,
+      { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
+    { "pcr_all_audio", "Include PCR values in all audio streams",
+      offsetof(MpegTSWrite, pcr_all_audio), AV_OPT_TYPE_BOOL,
+      { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
     { "pcr_period", "PCR retransmission time in milliseconds",
       offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT,
       { .i64 = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },