[FFmpeg-devel,v4,2/3] avformat/mpegts: keep track of PMT details in AVProgram/AVStream

Submitted by Aman Gupta on May 18, 2018, 6:15 p.m.

Details

Message ID 20180518181506.88903-2-ffmpeg@tmm1.net
State New
Headers show

Commit Message

Aman Gupta May 18, 2018, 6:15 p.m.
From: Aman Gupta <aman@tmm1.net>

With these fields, the user has enough information to
detect PMT changes and switch to new streams when the PMT
is updated with new ES pids.

To do so, the user would monitor the AVProgram they're interested
in for changes to pmt_version. If the version changes, they would
iterate over the program's streams to find new streams added with
the updated version number.

If new versions of streams are found, then the user would first try
to replace existing streams where stream_identifier matched.
If stream_identifier is not available, then the user would compare
pmt_stream_idx instead to replace the stream that was previously
at the same position within the PMT.

Signed-off-by: Aman Gupta <aman@tmm1.net>
---
 libavformat/mpegts.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index fc9bb3940e..229202e09d 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -330,12 +330,23 @@  static void set_pmt_found(MpegTSContext *ts, unsigned int programid)
     p->pmt_found = 1;
 }
 
-static void set_pcr_pid(AVFormatContext *s, unsigned int programid, unsigned int pid)
+static void update_av_program_info(AVFormatContext *s, unsigned int programid,
+                                   unsigned int pid, int version)
 {
     int i;
     for (i = 0; i < s->nb_programs; i++) {
-        if (s->programs[i]->id == programid) {
-            s->programs[i]->pcr_pid = pid;
+        AVProgram *program = s->programs[i];
+        if (program->id == programid) {
+            int old_pcr_pid = program->pcr_pid,
+                old_version = program->pmt_version;
+            program->pcr_pid = pid;
+            program->pmt_version = version;
+
+            if (old_version != -1 && old_version != version) {
+                av_log(s, AV_LOG_DEBUG,
+                       "detected PMT change on program %d (version=%d/%d, pcr_pid=0x%x/0x%x)\n",
+                       programid, old_version, version, old_pcr_pid, pid);
+            }
             break;
         }
     }
@@ -2036,7 +2047,7 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
         return;
     pcr_pid &= 0x1fff;
     add_pid_to_pmt(ts, h->id, pcr_pid);
-    set_pcr_pid(ts->stream, h->id, pcr_pid);
+    update_av_program_info(ts->stream, h->id, pcr_pid, h->version);
 
     av_log(ts->stream, AV_LOG_TRACE, "pcr_pid=0x%x\n", pcr_pid);
 
@@ -2078,7 +2089,7 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
     set_pmt_found(ts, h->id);
 
 
-    for (;;) {
+    for (i = 0; ; i++) {
         st = 0;
         pes = NULL;
         stream_type = get8(&p, p_end);
@@ -2099,6 +2110,9 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 if (!pes->st)
                     goto out;
                 pes->st->id = pes->pid;
+                pes->st->program_num = h->id;
+                pes->st->pmt_version = h->version;
+                pes->st->pmt_stream_idx = i;
             }
             st = pes->st;
         } else if (is_pes_stream(stream_type, prog_reg_desc)) {
@@ -2110,6 +2124,9 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 if (!st)
                     goto out;
                 st->id = pes->pid;
+                st->program_num = h->id;
+                st->pmt_version = h->version;
+                st->pmt_stream_idx = i;
             }
         } else {
             int idx = ff_find_stream_index(ts->stream, pid);
@@ -2120,6 +2137,9 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 if (!st)
                     goto out;
                 st->id = pid;
+                st->program_num = h->id;
+                st->pmt_version = h->version;
+                st->pmt_stream_idx = i;
                 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
                 if (stream_type == 0x86 && prog_reg_desc == AV_RL32("CUEI")) {
                     mpegts_find_stream_type(st, stream_type, SCTE_types);