X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmpegts.c;h=587ed3332749de909269c63ecb0143277363e30b;hb=99d78e4f424918c6584b358cd98cfc6165c5d158;hp=8f686393886e59a26b8eaa0d8913579f82863660;hpb=5c363d3e595a9e5b7c42897b7aab91b91b154ac1;p=ffmpeg diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 8f686393886..587ed333274 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -168,6 +168,8 @@ struct MpegTSContext { /** filters for various streams specified by PMT + for the PAT and PMT */ MpegTSFilter *pids[NB_PID_MAX]; int current_pid; + + AVStream *epg_stream; }; #define MPEGTS_OPTIONS \ @@ -803,6 +805,7 @@ static const StreamType ISO_types[] = { { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, + { 0xd2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS2 }, { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, }; @@ -1303,15 +1306,17 @@ skip: st = pst; } } - if (f->last_pcr != -1 && st && st->discard != AVDISCARD_ALL) { + if (f->last_pcr != -1 && !f->discard) { // teletext packets do not always have correct timestamps, // the standard says they should be handled after 40.6 ms at most, // and the pcr error to this packet should be no more than 100 ms. // TODO: we should interpolate the PCR, not just use the last one int64_t pcr = f->last_pcr / 300; pcr_found = 1; - pes->st->pts_wrap_reference = st->pts_wrap_reference; - pes->st->pts_wrap_behavior = st->pts_wrap_behavior; + if (st) { + pes->st->pts_wrap_reference = st->pts_wrap_reference; + pes->st->pts_wrap_behavior = st->pts_wrap_behavior; + } if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) { pes->pts = pes->dts = pcr; } else if (pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT && @@ -1723,6 +1728,13 @@ static void scte_data_cb(MpegTSFilter *filter, const uint8_t *section, if (idx < 0) return; + /** + * In case we receive an SCTE-35 packet before mpegts context is fully + * initialized. + */ + if (!ts->pkt) + return; + new_data_packet(section, section_len, ts->pkt); ts->pkt->stream_index = idx; prg = av_find_program_from_stream(ts->stream, NULL, idx); @@ -2130,7 +2142,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type return 0; } -static AVStream *find_matching_stream(MpegTSContext *ts, int pid, +static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int programid, int stream_identifier, int pmt_stream_idx) { AVFormatContext *s = ts->stream; @@ -2139,6 +2151,8 @@ static AVStream *find_matching_stream(MpegTSContext *ts, int pid, 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; @@ -2309,7 +2323,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len 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, stream_identifier, i); + st = find_matching_stream(ts, pid, h->id, stream_identifier, i); if (st) { pes->st = st; pes->stream_type = stream_type; @@ -2331,7 +2345,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, stream_identifier, i); + st = find_matching_stream(ts, pid, h->id, stream_identifier, i); if (st) { pes->st = st; pes->stream_type = stream_type; @@ -2353,7 +2367,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, stream_identifier, i); + st = find_matching_stream(ts, pid, h->id, stream_identifier, i); } if (!st) { st = avformat_new_stream(ts->stream, NULL); @@ -2487,6 +2501,60 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len } } +static void eit_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) +{ + MpegTSContext *ts = filter->u.section_filter.opaque; + const uint8_t *p, *p_end; + SectionHeader h1, *h = &h1; + + /* + * Sometimes we receive EPG packets but SDT table do not have + * eit_pres_following or eit_sched turned on, so we open EPG + * stream directly here. + */ + if (!ts->epg_stream) { + ts->epg_stream = avformat_new_stream(ts->stream, NULL); + if (!ts->epg_stream) + return; + ts->epg_stream->id = EIT_PID; + ts->epg_stream->codecpar->codec_type = AVMEDIA_TYPE_DATA; + ts->epg_stream->codecpar->codec_id = AV_CODEC_ID_EPG; + } + + if (ts->epg_stream->discard == AVDISCARD_ALL) + return; + + p_end = section + section_len - 4; + p = section; + + if (parse_section_header(h, &p, p_end) < 0) + return; + if (h->tid < EIT_TID || h->tid > OEITS_END_TID) + return; + + av_log(ts->stream, AV_LOG_TRACE, "EIT: tid received = %.02x\n", h->tid); + + /** + * Service_id 0xFFFF is reserved, it indicates that the current EIT table + * is scrambled. + */ + if (h->id == 0xFFFF) { + av_log(ts->stream, AV_LOG_TRACE, "Scrambled EIT table received.\n"); + return; + } + + /** + * In case we receive an EPG packet before mpegts context is fully + * initialized. + */ + if (!ts->pkt) + return; + + new_data_packet(section, section_len, ts->pkt); + ts->pkt->stream_index = ts->epg_stream->index; + ts->stop_parse = 1; +} + static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) { MpegTSContext *ts = filter->u.section_filter.opaque; @@ -2868,7 +2936,7 @@ static int handle_packets(MpegTSContext *ts, int64_t nb_packets) return ret; } -static int mpegts_probe(AVProbeData *p) +static int mpegts_probe(const AVProbeData *p) { const int size = p->buf_size; int maxscore = 0; @@ -2973,8 +3041,8 @@ static int mpegts_read_header(AVFormatContext *s) seek_back(s, pb, pos); mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); - mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); + mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1); handle_packets(ts, probesize / ts->raw_packet_size); /* if could not find service, enable auto_guess */ @@ -3229,8 +3297,10 @@ MpegTSContext *avpriv_mpegts_parse_open(AVFormatContext *s) ts->raw_packet_size = TS_PACKET_SIZE; ts->stream = s; ts->auto_guess = 1; + mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); + mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1); return ts; }