diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-03-23 02:50:45 +0400 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-03-23 02:50:49 +0400 |
commit | 2765c2ec7d5ec50f5852fe65f89c4a9e238f2157 (patch) | |
tree | 1499082fbb8148e9829913f6eee172fcaf2d7770 /libavformat | |
parent | de182701ac9e5c6f571e21ba1fffb1fa8d0f808d (diff) | |
parent | d2f60547c23018ab1bd007260b3d2fb93957cbb0 (diff) |
Merge remote-tracking branch 'cus/stable'
* cus/stable:
mpegts: fix teletext pts of streams with standalone pcr pid
mpegts: add pcr filter for tracking standalone pcr pids
mpegts: factorize mpegts filter creator code
mpegts: move last_pcr to MpegTSFilter level
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/mpegts.c | 96 |
1 files changed, 58 insertions, 38 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 20d618a620..5ae5c26f77 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -55,12 +55,13 @@ enum MpegTSFilterType { MPEGTS_PES, MPEGTS_SECTION, + MPEGTS_PCR, }; typedef struct MpegTSFilter MpegTSFilter; typedef int PESCallback (MpegTSFilter *f, const uint8_t *buf, int len, - int is_start, int64_t pos, int64_t cur_pcr); + int is_start, int64_t pos); typedef struct MpegTSPESFilter { PESCallback *pes_cb; @@ -85,6 +86,7 @@ struct MpegTSFilter { int pid; int es_id; int last_cc; /* last cc code (-1 if first packet) */ + int64_t last_pcr; enum MpegTSFilterType type; union { MpegTSPESFilter pes_filter; @@ -216,7 +218,6 @@ typedef struct PESContext { uint8_t header[MAX_PES_HEADER_SIZE]; AVBufferRef *buffer; SLConfigDescr sl; - int64_t last_pcr; } PESContext; extern AVInputFormat ff_mpegts_demuxer; @@ -405,14 +406,10 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1, } } -static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, - unsigned int pid, - SectionCallback *section_cb, - void *opaque, - int check_crc) +static MpegTSFilter *mpegts_open_filter(MpegTSContext *ts, unsigned int pid, + enum MpegTSFilterType type) { MpegTSFilter *filter; - MpegTSSectionFilter *sec; av_dlog(ts->stream, "Filter: pid=0x%x\n", pid); @@ -423,11 +420,26 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, return NULL; ts->pids[pid] = filter; - filter->type = MPEGTS_SECTION; + filter->type = type; filter->pid = pid; filter->es_id = -1; filter->last_cc = -1; + filter->last_pcr= -1; + + return filter; +} +static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, + unsigned int pid, + SectionCallback *section_cb, + void *opaque, + int check_crc) +{ + MpegTSFilter *filter; + MpegTSSectionFilter *sec; + + if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_SECTION))) + return NULL; sec = &filter->u.section_filter; sec->section_cb = section_cb; sec->opaque = opaque; @@ -447,24 +459,20 @@ static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid, MpegTSFilter *filter; MpegTSPESFilter *pes; - if (pid >= NB_PID_MAX || ts->pids[pid]) - return NULL; - filter = av_mallocz(sizeof(MpegTSFilter)); - if (!filter) + if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_PES))) return NULL; - ts->pids[pid] = filter; - filter->type = MPEGTS_PES; - filter->pid = pid; - filter->es_id = -1; - filter->last_cc = -1; - pes = &filter->u.pes_filter; pes->pes_cb = pes_cb; pes->opaque = opaque; return filter; } +static MpegTSFilter *mpegts_open_pcr_filter(MpegTSContext *ts, unsigned int pid) +{ + return mpegts_open_filter(ts, pid, MPEGTS_PCR); +} + static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) { int pid; @@ -891,7 +899,7 @@ static int read_sl_header(PESContext *pes, SLConfigDescr *sl, /* return non zero if a packet could be constructed */ static int mpegts_push_data(MpegTSFilter *filter, const uint8_t *buf, int buf_size, int is_start, - int64_t pos, int64_t pcr) + int64_t pos) { PESContext *pes = filter->u.pes_filter.opaque; MpegTSContext *ts = pes->ts; @@ -901,9 +909,6 @@ static int mpegts_push_data(MpegTSFilter *filter, if (!ts->pkt) return 0; - if (pcr != -1) - pes->last_pcr = pcr; - if (is_start) { if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { new_pes_packet(pes, ts->pkt); @@ -1066,16 +1071,28 @@ skip: while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) { if (p->pcr_pid != -1 && p->discard != AVDISCARD_ALL) { MpegTSFilter *f = pes->ts->pids[p->pcr_pid]; - if (f && f->type == MPEGTS_PES) { - PESContext *pcrpes = f->u.pes_filter.opaque; - if (pcrpes && pcrpes->last_pcr != -1 && pcrpes->st && pcrpes->st->discard != AVDISCARD_ALL) { + if (f) { + AVStream *st = NULL; + if (f->type == MPEGTS_PES) { + PESContext *pcrpes = f->u.pes_filter.opaque; + if (pcrpes) + st = pcrpes->st; + } else if (f->type == MPEGTS_PCR) { + int i; + for (i = 0; i < p->nb_stream_indexes; i++) { + AVStream *pst = pes->stream->streams[p->stream_index[i]]; + if (pst->codec->codec_type == AVMEDIA_TYPE_VIDEO) + st = pst; + } + } + if (f->last_pcr != -1 && st && st->discard != AVDISCARD_ALL) { // 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 = pcrpes->last_pcr / 300; - pes->st->pts_wrap_reference = pcrpes->st->pts_wrap_reference; - pes->st->pts_wrap_behavior = pcrpes->st->pts_wrap_behavior; + int64_t pcr = f->last_pcr / 300; + 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->dts > pcr + 3654 + 9000) { @@ -1146,7 +1163,6 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid) pes->state = MPEGTS_SKIP; pes->pts = AV_NOPTS_VALUE; pes->dts = AV_NOPTS_VALUE; - pes->last_pcr= -1; tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); if (!tss) { av_free(pes); @@ -1826,6 +1842,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len p = desc_list_end; } + if (!ts->pids[pcr_pid]) + mpegts_open_pcr_filter(ts, pcr_pid); + out: for (i = 0; i < mp4_descr_count; i++) av_free(mp4_descr[i].dec_config_descr); @@ -2031,7 +2050,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } } - if (!has_payload) + if (!has_payload && tss->type != MPEGTS_PCR) return 0; p = packet + 4; if (has_adaptation) { @@ -2040,7 +2059,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } /* if past the end of packet, ignore */ p_end = packet + TS_PACKET_SIZE; - if (p >= p_end) + if (p > p_end || (p == p_end && tss->type != MPEGTS_PCR)) return 0; pos = avio_tell(ts->stream->pb); @@ -2093,15 +2112,16 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } else { int ret; - int64_t pcr = -1; int64_t pcr_h; int pcr_l; if (parse_pcr(&pcr_h, &pcr_l, packet) == 0) - pcr = pcr_h * 300 + pcr_l; + tss->last_pcr = pcr_h * 300 + pcr_l; // Note: The position here points actually behind the current packet. - if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, - pos - ts->raw_packet_size, pcr)) < 0) - return ret; + if (tss->type == MPEGTS_PES) { + if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, + pos - ts->raw_packet_size)) < 0) + return ret; + } } return 0; @@ -2217,9 +2237,9 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) av_buffer_unref(&pes->buffer); pes->data_index = 0; pes->state = MPEGTS_SKIP; /* skip until pes header */ - pes->last_pcr = -1; } ts->pids[i]->last_cc = -1; + ts->pids[i]->last_pcr = -1; } } } |