diff options
author | Marton Balint <cus@passwd.hu> | 2013-08-04 04:17:22 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-08-06 02:47:38 +0200 |
commit | a7bb12a307568c0db72e6eb8d496a5651a8228df (patch) | |
tree | e1dcf0cbd20c2bae71f9a87c4099300c127bec26 /libavformat | |
parent | 4c15f3491f1991554ad497788dfb6ad02b552134 (diff) | |
download | ffmpeg-a7bb12a307568c0db72e6eb8d496a5651a8228df.tar.gz |
mpegts: add fix_teletext_pts mpegts demuxer option
Changes since v1 of the patch:
- enable option by default
- add documentation
- move up PTS override code after PES header parsing, to ensure we use the
last PCR before the first packet of the teletext PES packet.
The option overrides teletext packet PTS and DTS values with the timestamps
calculated from the PCR of the first program which the teletext stream is part
of and is not discarded.
Using the same teletext PID for multiple programs is possible, therefore we
need some kind of heuristics to know which program PCR we should synchronize
to. Using the first non-discarded PCR pid among the programs of the teletext
stream seemed like a good choice.
The patch does not do PCR interpolation to estimate the PCR of the teltetext
packet, it just uses the last PCR of the program, which may cause a slight
error (0.1 sec) in the teletext packet pts-es.
Based on a patch by Reimar Döffinger.
http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2012-September/131610.html
Signed-off-by: Marton Balint <cus@passwd.hu>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/mpegts.c | 47 | ||||
-rw-r--r-- | libavformat/version.h | 2 |
2 files changed, 46 insertions, 3 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index c7c957f635..beaed3180b 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -106,6 +106,9 @@ struct MpegTSContext { /** compute exact PCR for each transport stream packet */ int mpeg2ts_compute_pcr; + /** fix dvb teletext pts */ + int fix_teletext_pts; + int64_t cur_pcr; /**< used to estimate the exact PCR */ int pcr_incr; /**< used to estimate the exact PCR */ @@ -131,7 +134,7 @@ struct MpegTSContext { int current_pid; }; -static const AVOption options[] = { +static const AVOption mpegtsraw_options[] = { {"compute_pcr", "Compute exact PCR for each transport stream packet.", offsetof(MpegTSContext, mpeg2ts_compute_pcr), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, { NULL }, @@ -140,7 +143,20 @@ static const AVOption options[] = { static const AVClass mpegtsraw_class = { .class_name = "mpegtsraw demuxer", .item_name = av_default_item_name, - .option = options, + .option = mpegtsraw_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVOption mpegts_options[] = { + {"fix_teletext_pts", "Try to fix pts values of dvb teletext streams.", offsetof(MpegTSContext, fix_teletext_pts), AV_OPT_TYPE_INT, + {.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass mpegts_class = { + .class_name = "mpegts demuxer", + .item_name = av_default_item_name, + .option = mpegts_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -968,6 +984,32 @@ static int mpegts_push_data(MpegTSFilter *filter, p += sl_header_bytes; buf_size -= sl_header_bytes; } + if (pes->ts->fix_teletext_pts && pes->st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) { + AVProgram *p = NULL; + 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) { + // 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; + if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) { + pes->pts = pes->dts = pcr; + } else if (pes->dts > pcr + 3654 + 9000) { + pes->pts = pes->dts = pcr + 3654 + 9000; + } + break; + } + } + } + } + } } break; case MPEGTS_PAYLOAD: @@ -2325,6 +2367,7 @@ AVInputFormat ff_mpegts_demuxer = { .read_close = mpegts_read_close, .read_timestamp = mpegts_get_dts, .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, + .priv_class = &mpegts_class, }; AVInputFormat ff_mpegtsraw_demuxer = { diff --git a/libavformat/version.h b/libavformat/version.h index bea7c7b67f..c2ca0ab935 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 55 #define LIBAVFORMAT_VERSION_MINOR 13 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MICRO 102 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ |