mpegts: add fix_teletext_pts mpegts demuxer option
authorMarton Balint <cus@passwd.hu>
Sun, 4 Aug 2013 02:17:22 +0000 (04:17 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 6 Aug 2013 00:47:38 +0000 (02:47 +0200)
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>
doc/demuxers.texi
libavformat/mpegts.c
libavformat/version.h

index 1a4d739..e18448f 100644 (file)
@@ -257,6 +257,19 @@ ffmpeg -pattern_type glob -i "*.png" -r 10 out.mkv
 @end example
 @end itemize
 
+@section mpegts
+
+MPEG-2 transport stream demuxer.
+
+@table @option
+
+@item fix_teletext_pts
+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. Default value is 1, set this option to 0 if you want your
+teletext packet PTS and DTS values untouched.
+@end table
+
 @section rawvideo
 
 Raw video demuxer.
index c7c957f..beaed31 100644 (file)
@@ -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 = {
index bea7c7b..c2ca0ab 100644 (file)
@@ -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, \