static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{
    MpegTSContext *ts = filter->u.section_filter.opaque;
    SectionHeader h1, *h = &h1;
    PESContext *pes;
    AVStream *st;
    const uint8_t *p, *p_end, *desc_list_end, *desc_end;
    int program_info_length, pcr_pid, pid, stream_type;
    int desc_list_len, desc_len, desc_tag;
    int comp_page, anc_page;
    char language[4];
    uint32_t prog_reg_desc = 0; /* registration descriptor */

#ifdef DEBUG
    dprintf(ts->stream, "PMT: len %i\n", section_len);
    av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
#endif

    p_end = section + section_len - 4;
    p = section;
    if (parse_section_header(h, &p, p_end) < 0)
        return;

    dprintf(ts->stream, "sid=0x%x sec_num=%d/%d\n",
           h->id, h->sec_num, h->last_sec_num);

    if (h->tid != PMT_TID)
        return;

    clear_program(ts, h->id);
    pcr_pid = get16(&p, p_end) & 0x1fff;
    if (pcr_pid < 0)
        return;
    add_pid_to_pmt(ts, h->id, pcr_pid);

    dprintf(ts->stream, "pcr_pid=0x%x\n", pcr_pid);

    program_info_length = get16(&p, p_end) & 0xfff;
    if (program_info_length < 0)
        return;
    while(program_info_length >= 2) {
        uint8_t tag, len;
        tag = get8(&p, p_end);
        len = get8(&p, p_end);
        if(len > program_info_length - 2)
            //something else is broken, exit the program_descriptors_loop
            break;
        program_info_length -= len + 2;
        if(tag == 0x05 && len >= 4) { // registration descriptor
            prog_reg_desc = bytestream_get_le32(&p);
            len -= 4;
        }
        p += len;
    }
    p += program_info_length;
    if (p >= p_end)
        return;

    // stop parsing after pmt, we found header
    if (!ts->stream->nb_streams)
        ts->stop_parse = 1;

    for(;;) {
        st = 0;
        stream_type = get8(&p, p_end);
        if (stream_type < 0)
            break;
        pid = get16(&p, p_end) & 0x1fff;
        if (pid < 0)
            break;

        /* now create ffmpeg stream */
        if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) {
            pes = ts->pids[pid]->u.pes_filter.opaque;
            st = pes->st;
        } else {
            if (ts->pids[pid]) mpegts_close_filter(ts, ts->pids[pid]); //wrongly added sdt filter probably
            pes = add_pes_stream(ts, pid, pcr_pid);
            if (pes)
                st = av_new_stream(pes->stream, pes->pid);
        }

        if (!st)
            return;

        if (!pes->stream_type)
            mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc);

        add_pid_to_pmt(ts, h->id, pid);

        av_program_add_stream_index(ts->stream, h->id, st->index);

        desc_list_len = get16(&p, p_end) & 0xfff;
        if (desc_list_len < 0)
            break;
        desc_list_end = p + desc_list_len;
        if (desc_list_end > p_end)
            break;
        for(;;) {
            desc_tag = get8(&p, desc_list_end);
            if (desc_tag < 0)
                break;
            desc_len = get8(&p, desc_list_end);
            if (desc_len < 0)
                break;
            desc_end = p + desc_len;
            if (desc_end > desc_list_end)
                break;

            dprintf(ts->stream, "tag: 0x%02x len=%d\n",
                   desc_tag, desc_len);

            if (st->codec->codec_id == CODEC_ID_NONE &&
                stream_type == STREAM_TYPE_PRIVATE_DATA)
                mpegts_find_stream_type(st, desc_tag, DESC_types);

            switch(desc_tag) {
            case 0x56: /* DVB teletext descriptor */
                language[0] = get8(&p, desc_end);
                language[1] = get8(&p, desc_end);
                language[2] = get8(&p, desc_end);
                language[3] = 0;
                av_metadata_set(&st->metadata, "language", language);
                break;
            case 0x59: /* subtitling descriptor */
                language[0] = get8(&p, desc_end);
                language[1] = get8(&p, desc_end);
                language[2] = get8(&p, desc_end);
                language[3] = 0;
                get8(&p, desc_end);
                comp_page = get16(&p, desc_end);
                anc_page = get16(&p, desc_end);
                st->codec->sub_id = (anc_page << 16) | comp_page;
                av_metadata_set(&st->metadata, "language", language);
                break;
            case 0x0a: /* ISO 639 language descriptor */
                language[0] = get8(&p, desc_end);
                language[1] = get8(&p, desc_end);
                language[2] = get8(&p, desc_end);
                language[3] = 0;
                av_metadata_set(&st->metadata, "language", language);
                break;
            case 0x05: /* registration descriptor */
                st->codec->codec_tag = bytestream_get_le32(&p);
                dprintf(ts->stream, "reg_desc=%.4s\n", (char*)&st->codec->codec_tag);
                if (st->codec->codec_id == CODEC_ID_NONE &&
                    stream_type == STREAM_TYPE_PRIVATE_DATA)
                    mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types);
                break;
            default:
                break;
            }
            p = desc_end;

            if (prog_reg_desc == AV_RL32("HDMV") && stream_type == 0x83 && pes->sub_st) {
                av_program_add_stream_index(ts->stream, h->id, pes->sub_st->index);
                pes->sub_st->codec->codec_tag = st->codec->codec_tag;
            }
        }
        p = desc_list_end;
    }
    /* all parameters are there */
    mpegts_close_filter(ts, filter);
}