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
From 8d2b61cd85ba98edebae3cd2648fe7c4008d76b3 Mon Sep 17 00:00:00 2001 From: Deep Thought <deep...@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
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".