From patchwork Mon Dec 28 22:49:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 24670 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 54C5D44866D for ; Tue, 29 Dec 2020 00:49:52 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 293E868A5E3; Tue, 29 Dec 2020 00:49:52 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 18A7268A6B6 for ; Tue, 29 Dec 2020 00:49:45 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 041E8E4BF7; Mon, 28 Dec 2020 23:49:45 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 2WjM1_fV8qMY; Mon, 28 Dec 2020 23:49:43 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id D230FE4E29; Mon, 28 Dec 2020 23:49:42 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Mon, 28 Dec 2020 23:49:28 +0100 Message-Id: <20201228224929.21299-5-cus@passwd.hu> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201228224929.21299-1-cus@passwd.hu> References: <20201228224929.21299-1-cus@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 5/6] avformat/mpegts: use stream index based lookup with merge_pmt_versions if stream identifier matches multiple streams X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Marton Balint Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Also make sure we are checking the old state of the streams because otherwise some streams might already have the newly parsed stream identifiers which corrupts matching. Fixes streams having the same identifier mixed up on pmt version change. Fixes ticket #9006. Signed-off-by: Marton Balint --- libavformat/mpegts.c | 57 +++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index ee69e2ca29..9a3fd56ece 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -107,11 +107,19 @@ struct MpegTSFilter { } u; }; -#define MAX_PIDS_PER_PROGRAM 64 +struct Stream { + int idx; + int stream_identifier; +}; + +#define MAX_STREAMS_PER_PROGRAM 128 +#define MAX_PIDS_PER_PROGRAM (MAX_STREAMS_PER_PROGRAM + 2) struct Program { unsigned int id; // program id/service id unsigned int nb_pids; unsigned int pids[MAX_PIDS_PER_PROGRAM]; + unsigned int nb_streams; + struct Stream streams[MAX_STREAMS_PER_PROGRAM]; /** have we found pmt for this program */ int pmt_found; @@ -291,6 +299,7 @@ static void clear_program(struct Program *p) if (!p) return; p->nb_pids = 0; + p->nb_streams = 0; p->pmt_found = 0; } @@ -2193,27 +2202,28 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int programid, - int stream_identifier, int pmt_stream_idx) + int stream_identifier, int pmt_stream_idx, struct Program *p) { AVFormatContext *s = ts->stream; int i; AVStream *found = NULL; - 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; + if (stream_identifier) { /* match based on "stream identifier descriptor" if present */ + for (i = 0; i < p->nb_streams; i++) { + if (p->streams[i].stream_identifier == stream_identifier) { + if (found) { /* fallback to idx based guess if multiple streams have the same identifier */ + found = NULL; + break; + } else { + found = s->streams[p->streams[i].idx]; + } } - } else if (st->pmt_stream_idx == pmt_stream_idx) { /* match based on position within the PMT */ - found = st; - break; } } + if (!found && pmt_stream_idx < p->nb_streams) + found = s->streams[p->streams[pmt_stream_idx].idx]; + if (found) { av_log(ts->stream, AV_LOG_VERBOSE, "re-using existing %s stream %d (pid=0x%x) for new pid=0x%x\n", @@ -2270,6 +2280,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len { MpegTSContext *ts = filter->u.section_filter.opaque; MpegTSSectionFilter *tssf = &filter->u.section_filter; + struct Program old_program; SectionHeader h1, *h = &h1; PESContext *pes; AVStream *st; @@ -2303,6 +2314,10 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len return; prg = get_program(ts, h->id); + if (prg) + old_program = *prg; + else + clear_program(&old_program); if (ts->skip_unknown_pmt && !prg) return; @@ -2360,7 +2375,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (prg) prg->pmt_found = 1; - for (i = 0; ; i++) { + for (i = 0; i < MAX_STREAMS_PER_PROGRAM; i++) { st = 0; pes = NULL; stream_type = get8(&p, p_end); @@ -2373,14 +2388,13 @@ 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); + stream_identifier = parse_stream_identifier_desc(p, p_end) + 1; /* 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, i, &old_program); if (st) { pes->st = st; pes->stream_type = stream_type; @@ -2402,7 +2416,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, h->id, stream_identifier, i); + st = find_matching_stream(ts, pid, h->id, stream_identifier, i, &old_program); if (st) { pes->st = st; pes->stream_type = stream_type; @@ -2424,7 +2438,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, i, &old_program); } if (!st) { st = avformat_new_stream(ts->stream, NULL); @@ -2449,6 +2463,11 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc); add_pid_to_program(prg, pid); + if (prg) { + prg->streams[i].idx = st->index; + prg->streams[i].stream_identifier = stream_identifier; + prg->nb_streams++; + } av_program_add_stream_index(ts->stream, h->id, st->index);