aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/mpegts.c
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2013-08-04 04:17:22 +0200
committerMichael Niedermayer <michaelni@gmx.at>2013-08-06 02:47:38 +0200
commita7bb12a307568c0db72e6eb8d496a5651a8228df (patch)
treee1dcf0cbd20c2bae71f9a87c4099300c127bec26 /libavformat/mpegts.c
parent4c15f3491f1991554ad497788dfb6ad02b552134 (diff)
downloadffmpeg-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/mpegts.c')
-rw-r--r--libavformat/mpegts.c47
1 files changed, 45 insertions, 2 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 = {