From patchwork Mon Nov 23 23:17:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deep Thought X-Patchwork-Id: 24021 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 32DE444A9DF for ; Tue, 24 Nov 2020 01:50:42 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0B24968BC2E; Tue, 24 Nov 2020 01:50:42 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f45.google.com (mail-lf1-f45.google.com [209.85.167.45]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6269268BB4D for ; Tue, 24 Nov 2020 01:50:35 +0200 (EET) Received: by mail-lf1-f45.google.com with SMTP id d20so10390339lfe.11 for ; Mon, 23 Nov 2020 15:50:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=iV3JZDjxDb0xhybOok9SXB+7/IjH+w5p9HbTRfBMTdA=; b=MQaCEOE4E6o8EMm46P4zn2kk/1d5li00MC0kZuqvJ34qJW25263el2RE6UEtNv+ViB Q0+EFpq2LpmlssDMDuVAtAvp6Es+URVEk6zc0ys7ZG0ExnIVpXgwL6z7uzl13/fUyjom 3Om6qH0r1hXB2ppZzBqRxsXvVzpblVjWEjkeCOiM7CikVgFF1xJtsdqUggmhN08X2XhO Tx1MnmHSVpnCUB7U1QLoQp8bvlmHG9zYpOKuo9CGXiIpxz8TuFwClM9NfKwuwtTfaeHR y/jd0EutCCIUckMcH/A+w7NN7ItKAdN/AyP9DkLuw/XFKXWqWk8XiPN6xX5fLmmo63fQ us8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=iV3JZDjxDb0xhybOok9SXB+7/IjH+w5p9HbTRfBMTdA=; b=KTH7/t5mklWfYr4MfthDUVHIVz7Zf8njaDlnKoRndT6XQndy2lurDdM3WiherOBn6S INdjrS7QF9WY++QBU1vObx3X3m0yiDSB1BS+v4hwLrSBILpIkjI5lulwgeSTT2ot/8WH jSVF9nTyPE6QkJpmUX8FqzXVAjUrWQ/2ljAfdVKnGUSktGNt3BY1sfs1Z8CshkHMFgxC NnLZgk1TLKqhkZz5qQy+nHkqVHTXojMieAN5dp0iPOAVWMpW5HZalAvgU/qLInKMhyim cv2tlFJ99DkbLBLbB0ehN9NW8XMfaLbXM9v+TnEYovpVjEH01dzQJxQvzugD0TPqOaaO AmqQ== X-Gm-Message-State: AOAM531G+re1wRH0V4ZA5uicAxQE1GRMqP6NmDAZ/n875tM53syOCIEH e8sGYGXHKiiMOfvz1G4HyndrGEfJ01pje4/tJeLFwFD1+Vw= X-Google-Smtp-Source: ABdhPJyRbJNPanTTcz87ZqVcKeWv9tUUCwyj9Jt1lI67rgrNaKMSn1v/9ZpD8CVDqehU9UEUCqZtZ0yPY7soHW02W80= X-Received: by 2002:ac2:598f:: with SMTP id w15mr543386lfn.148.1606173443859; Mon, 23 Nov 2020 15:17:23 -0800 (PST) MIME-Version: 1.0 From: Deep Thought Date: Tue, 24 Nov 2020 00:17:12 +0100 Message-ID: To: ffmpeg-devel@ffmpeg.org X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: [FFmpeg-devel] New Ticket #9006 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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. 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);