[FFmpeg-devel] New Ticket #9006

Deep Thought deeptho at gmail.com
Tue Nov 24 01:17:12 EET 2020


I have opened a ticket explaining a problem with the code for
merge_pmt_versions.

Attached is also a patch which fixes this problem. The main idea is the
following:


for the INITIAL pmt, the old code finds matching streams by
1) checking the stream_identifier. If the current stream has one,
and if an earlier processed stream has the same one, it is assumed
that the two streams should be merged (I am not sure what this really
means, but the result is playback problems).

This behavior is wrong for streams having multiple audio streams with the
same stream_identifier

2) for streams without a stream identifier, it will look for a stream which
has the same position in the pmt as the current stream and will obviously
not find one. This is correct

So the patch solves the problem in 1) as follows:
1) if a stream has a stream identifier, it first computes a new variable
pmt_stream_index which will equal for the first stream with that
identifier, 1 for the second one with that identifier and so on
2) if a stream has no stream_identifier, pmt_stream_index will equal 0 for
the first such stream, 1 for the second such stream ... This is the same
as 1) but with stream_identifier==-1

find_matching_stream then compares streams based on a DUAL criterion:
pmt_stream_index must match, and stream_type must match.

The result is that for the INITIAL pmt all audi streams will be considered
different. If later the PMT changes, streams will be matched based on
stream identifier as the primary criterion and based on pmt_stream_index as
the secondary criterion.



-- 
---Deep Thought
-------------- next part --------------
From 8d2b61cd85ba98edebae3cd2648fe7c4008d76b3 Mon Sep 17 00:00:00 2001
From: Deep Thought <deeptho at gmail.com>
Date: Mon, 23 Nov 2020 23:57:17 +0100
Subject: [PATCH] Patch for ticket #9006 incorrect merge_pmt_versions behavior

---
 libavformat/mpegts.c | 59 +++++++++++++++++++++++++++++---------------
 1 file changed, 39 insertions(+), 20 deletions(-)

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index a2003c6632..c4f1377d97 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -2200,6 +2200,22 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
     return 0;
 }
 
+
+#define MAX_NUM_STREAMS (32)
+
+
+static char compute_pmt_stream_idx(char stream_identifier,
+																	 char stream_identifiers[MAX_NUM_STREAMS], int num_stream_identifiers)
+{
+	int i;
+	int pmt_stream_idx =0;
+	for(i=0;i <  num_stream_identifiers && i < MAX_NUM_STREAMS; ++i)
+		if(stream_identifiers[i]== stream_identifier)
+			pmt_stream_idx++;
+	return pmt_stream_idx;
+
+}
+
 static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int programid,
                                       int stream_identifier, int pmt_stream_idx)
 {
@@ -2210,17 +2226,14 @@ static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int p
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
         if (st->program_num != programid)
-            continue;
-        if (stream_identifier != -1) { /* match based on "stream identifier descriptor" if present */
-            if (st->stream_identifier == stream_identifier+1) {
-                found = st;
-                break;
-            }
-        } else if (st->pmt_stream_idx == pmt_stream_idx) { /* match based on position within the PMT */
-            found = st;
-            break;
-        }
-    }
+					continue;
+				if (st->stream_identifier == stream_identifier+1
+						&& st->pmt_stream_idx == pmt_stream_idx) {
+					found = st;
+					break;
+				}
+		}
+
 
     if (found) {
         av_log(ts->stream, AV_LOG_VERBOSE,
@@ -2360,6 +2373,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
 
     set_pmt_found(ts, h->id);
 
+		char stream_identifiers[MAX_NUM_STREAMS];
+		int pmt_stream_idx=-1;
 
     for (i = 0; ; i++) {
         st = 0;
@@ -2374,14 +2389,18 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
         if (pid == ts->current_pid)
             goto out;
 
-        if (ts->merge_pmt_versions)
-            stream_identifier = parse_stream_identifier_desc(p, p_end);
+        if (ts->merge_pmt_versions) {
+	         stream_identifier = parse_stream_identifier_desc(p, p_end);
+          	pmt_stream_idx = compute_pmt_stream_idx(stream_identifier,stream_identifiers, i);
+					if(i< MAX_NUM_STREAMS)
+						stream_identifiers[i] =  stream_identifier;
+				}
 
         /* now create stream */
         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, h->id, stream_identifier, i);
+                st = find_matching_stream(ts, pid, h->id, stream_identifier, pmt_stream_idx);
                 if (st) {
                     pes->st = st;
                     pes->stream_type = stream_type;
@@ -2395,7 +2414,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 pes->st->id = pes->pid;
                 pes->st->program_num = h->id;
                 pes->st->pmt_version = h->version;
-                pes->st->pmt_stream_idx = i;
+                pes->st->pmt_stream_idx = pmt_stream_idx;
             }
             st = pes->st;
         } else if (is_pes_stream(stream_type, prog_reg_desc)) {
@@ -2403,8 +2422,8 @@ 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, h->id, stream_identifier, i);
-                if (st) {
+							st = find_matching_stream(ts, pid, h->id, stream_identifier, pmt_stream_idx);
+							if (st) {
                     pes->st = st;
                     pes->stream_type = stream_type;
                     pes->merged_st = 1;
@@ -2417,7 +2436,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 st->id = pes->pid;
                 st->program_num = h->id;
                 st->pmt_version = h->version;
-                st->pmt_stream_idx = i;
+								st->pmt_stream_idx = pmt_stream_idx;
             }
         } else {
             int idx = ff_find_stream_index(ts->stream, pid);
@@ -2425,7 +2444,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, h->id, stream_identifier, i);
+							st = find_matching_stream(ts, pid, h->id, stream_identifier, pmt_stream_idx);
             }
             if (!st) {
                 st = avformat_new_stream(ts->stream, NULL);
@@ -2434,7 +2453,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 st->id = pid;
                 st->program_num = h->id;
                 st->pmt_version = h->version;
-                st->pmt_stream_idx = i;
+								st->pmt_stream_idx = pmt_stream_idx;
                 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);
-- 
2.25.4



More information about the ffmpeg-devel mailing list