[FFmpeg-devel] avformat/mpegts: apply -merge_pmt_versions only when versions change

Submitted by Aman Gupta on May 7, 2019, 3:27 a.m.

Details

Message ID 20190507032726.80597-1-ffmpeg@tmm1.net
State New
Headers show

Commit Message

Aman Gupta May 7, 2019, 3:27 a.m.
From: Aman Gupta <aman@tmm1.net>

Previously the code assumed that stream_identifier was unique per stream
in the PMT, as suggested by the spec. However, I found some samples from
Finland MTV3 where this is not the case.

    PID 0231 ( 561) -> Stream type 04 (  4) 13818-3 audio (MPEG-2)
        ES info (17 bytes): 0a 04 66 69 6e 00 52 01 29 03 01 67 0e 03 c0 01 f6
        Languages: fin
        Stream Identifier (82) (1 byte): 29
        Audio stream (3) (1 byte): 67
        Maximum bitrate (14) (3 bytes): c0 01 f6
    PID 0234 ( 564) -> Stream type 04 (  4) 13818-3 audio (MPEG-2)
        ES info (17 bytes): 0a 04 64 75 74 03 52 01 29 03 01 67 0e 03 c0 01 59
        Languages: dut/visual impaired commentary
        Stream Identifier (82) (1 byte): 29
        Audio stream (3) (1 byte): 67
        Maximum bitrate (14) (3 bytes): c0 01 59

This patch updates the logic to merge streams only when they appear in
different versions of the PMT.

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

Patch hide | download patch | download mbox

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 8a84e5cc19..9928959025 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -2130,7 +2130,7 @@  int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
     return 0;
 }
 
-static AVStream *find_matching_stream(MpegTSContext *ts, int pid,
+static AVStream *find_matching_stream(MpegTSContext *ts, int pid, int pmt_version,
                                       int stream_identifier, int pmt_stream_idx)
 {
     AVFormatContext *s = ts->stream;
@@ -2139,6 +2139,9 @@  static AVStream *find_matching_stream(MpegTSContext *ts, int pid,
 
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
+        if (st->pmt_version == pmt_version) { /* only merge across pmt version changes */
+            continue;
+        }
         if (stream_identifier != -1) { /* match based on "stream identifier descriptor" if present */
             if (st->stream_identifier == stream_identifier+1) {
                 found = st;
@@ -2309,7 +2312,7 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
         if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) {
             pes = ts->pids[pid]->u.pes_filter.opaque;
             if (ts->merge_pmt_versions && !pes->st) {
-                st = find_matching_stream(ts, pid, stream_identifier, i);
+                st = find_matching_stream(ts, pid, h->version, stream_identifier, i);
                 if (st) {
                     pes->st = st;
                     pes->stream_type = stream_type;
@@ -2331,7 +2334,7 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably
             pes = add_pes_stream(ts, pid, pcr_pid);
             if (ts->merge_pmt_versions && pes && !pes->st) {
-                st = find_matching_stream(ts, pid, stream_identifier, i);
+                st = find_matching_stream(ts, pid, h->version, stream_identifier, i);
                 if (st) {
                     pes->st = st;
                     pes->stream_type = stream_type;
@@ -2353,7 +2356,7 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 st = ts->stream->streams[idx];
             }
             if (ts->merge_pmt_versions && !st) {
-                st = find_matching_stream(ts, pid, stream_identifier, i);
+                st = find_matching_stream(ts, pid, h->version, stream_identifier, i);
             }
             if (!st) {
                 st = avformat_new_stream(ts->stream, NULL);