Ticket #9006: 0001-avformat-mpegts-use-stream-index-based-lookup-with-m.patch

File 0001-avformat-mpegts-use-stream-index-based-lookup-with-m.patch, 5.9 KB (added by Marton Balint, 6 years ago)
  • libavformat/mpegts.c

    From eec1547db3df45ab168970b6bbc8c3d5d3d49a7d Mon Sep 17 00:00:00 2001
    From: Marton Balint <cus@passwd.hu>
    Date: Tue, 24 Nov 2020 22:58:18 +0100
    Subject: [PATCH] avformat/mpegts: use stream index based lookup with
     merge_pmt_versions if stream identifier matches multiple streams
    
    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 <cus@passwd.hu>
    ---
     libavformat/mpegts.c | 53 +++++++++++++++++++++++++++++++++++---------
     1 file changed, 42 insertions(+), 11 deletions(-)
    
    diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
    index 7549fc91c9..0bf06b3986 100644
    a b struct Program {  
    116116    int pmt_found;
    117117};
    118118
     119struct Stream {
     120    int pmt_stream_idx;
     121    int stream_identifier;
     122    int program_num;
     123};
     124
    119125struct MpegTSContext {
    120126    const AVClass *class;
    121127    /* user data */
    int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type  
    22012207    return 0;
    22022208}
    22032209
    2204 static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int programid,
     2210static AVStream* find_matching_stream(MpegTSContext *ts, struct Stream *old_streams, int nb_old_streams, int pid, unsigned int programid,
    22052211                                      int stream_identifier, int pmt_stream_idx)
    22062212{
    22072213    AVFormatContext *s = ts->stream;
    22082214    int i;
    22092215    AVStream *found = NULL;
     2216    AVStream *idxfound = NULL;
    22102217
    2211     for (i = 0; i < s->nb_streams; i++) {
    2212         AVStream *st = s->streams[i];
     2218    for (i = 0; i < nb_old_streams; i++) {
     2219        struct Stream *st = old_streams + i;
    22132220        if (st->program_num != programid)
    22142221            continue;
    22152222        if (stream_identifier != -1) { /* match based on "stream identifier descriptor" if present */
    22162223            if (st->stream_identifier == stream_identifier+1) {
    2217                 found = st;
    2218                 break;
     2224                if (found) { /* fallback to idx based guess if multiple streams have the same identifier */
     2225                    stream_identifier = -1;
     2226                    found = NULL;
     2227                } else {
     2228                    found = s->streams[i];
     2229                }
    22192230            }
    2220         } else if (st->pmt_stream_idx == pmt_stream_idx) { /* match based on position within the PMT */
    2221             found = st;
    2222             break;
     2231        }
     2232        if (st->pmt_stream_idx == pmt_stream_idx) { /* match based on position within the PMT */
     2233            if (!idxfound)
     2234                idxfound = s->streams[i];
    22232235        }
    22242236    }
    22252237
     2238    if (!found)
     2239        found = idxfound;
     2240
    22262241    if (found) {
    22272242        av_log(ts->stream, AV_LOG_VERBOSE,
    22282243               "re-using existing %s stream %d (pid=0x%x) for new pid=0x%x\n",
    static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len  
    22882303    uint32_t prog_reg_desc = 0; /* registration descriptor */
    22892304    int stream_identifier = -1;
    22902305
     2306    struct Stream *old_streams = NULL;
     2307    int nb_old_streams = 0;
     2308
    22912309    int mp4_descr_count = 0;
    22922310    Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } };
    22932311    int i;
    static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len  
    23612379
    23622380    set_pmt_found(ts, h->id);
    23632381
     2382    if (ts->merge_pmt_versions) {
     2383        old_streams = av_malloc_array(sizeof(struct Stream), ts->stream->nb_streams);
     2384        if (!old_streams)
     2385            goto out;
     2386        nb_old_streams = ts->stream->nb_streams;
     2387        for (i = 0; i < nb_old_streams; i++) {
     2388            AVStream *st = ts->stream->streams[i];
     2389            old_streams[i].pmt_stream_idx = st->pmt_stream_idx;
     2390            old_streams[i].stream_identifier = st->stream_identifier;
     2391            old_streams[i].program_num = st->program_num;
     2392        }
     2393    }
    23642394
    23652395    for (i = 0; ; i++) {
    23662396        st = 0;
    static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len  
    23822412        if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) {
    23832413            pes = ts->pids[pid]->u.pes_filter.opaque;
    23842414            if (ts->merge_pmt_versions && !pes->st) {
    2385                 st = find_matching_stream(ts, pid, h->id, stream_identifier, i);
     2415                st = find_matching_stream(ts, old_streams, nb_old_streams, pid, h->id, stream_identifier, i);
    23862416                if (st) {
    23872417                    pes->st = st;
    23882418                    pes->stream_type = stream_type;
    static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len  
    24042434                mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably
    24052435            pes = add_pes_stream(ts, pid, pcr_pid);
    24062436            if (ts->merge_pmt_versions && pes && !pes->st) {
    2407                 st = find_matching_stream(ts, pid, h->id, stream_identifier, i);
     2437                st = find_matching_stream(ts, old_streams, nb_old_streams, pid, h->id, stream_identifier, i);
    24082438                if (st) {
    24092439                    pes->st = st;
    24102440                    pes->stream_type = stream_type;
    static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len  
    24262456                st = ts->stream->streams[idx];
    24272457            }
    24282458            if (ts->merge_pmt_versions && !st) {
    2429                 st = find_matching_stream(ts, pid, h->id, stream_identifier, i);
     2459                st = find_matching_stream(ts, old_streams, nb_old_streams, pid, h->id, stream_identifier, i);
    24302460            }
    24312461            if (!st) {
    24322462                st = avformat_new_stream(ts->stream, NULL);
    static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len  
    24812511        mpegts_open_pcr_filter(ts, pcr_pid);
    24822512
    24832513out:
     2514    av_free(old_streams);
    24842515    for (i = 0; i < mp4_descr_count; i++)
    24852516        av_free(mp4_descr[i].dec_config_descr);
    24862517}