tsdemux: Handle rollover in PTS and DTS

Also hands back-rollover which can happen with PTS
This commit is contained in:
Edward Hervey 2012-01-10 11:37:13 +01:00
parent 3d34779e24
commit 24408bce96

View file

@ -63,6 +63,7 @@
#define PCR_SMALL 17775000 #define PCR_SMALL 17775000
/* maximal PCR time */ /* maximal PCR time */
#define PCR_MAX_VALUE (((((guint64)1)<<33) * 300) + 298) #define PCR_MAX_VALUE (((((guint64)1)<<33) * 300) + 298)
#define PTS_DTS_MAX_VALUE (((guint64)1) << 33)
/* seek to SEEK_TIMESTAMP_OFFSET before the desired offset and search then /* seek to SEEK_TIMESTAMP_OFFSET before the desired offset and search then
* either accurately or for the next timestamp * either accurately or for the next timestamp
@ -72,6 +73,8 @@
GST_DEBUG_CATEGORY_STATIC (ts_demux_debug); GST_DEBUG_CATEGORY_STATIC (ts_demux_debug);
#define GST_CAT_DEFAULT ts_demux_debug #define GST_CAT_DEFAULT ts_demux_debug
#define ABSDIFF(a,b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
static GQuark QUARK_TSDEMUX; static GQuark QUARK_TSDEMUX;
static GQuark QUARK_PID; static GQuark QUARK_PID;
static GQuark QUARK_PCR; static GQuark QUARK_PCR;
@ -116,8 +119,15 @@ struct _TSDemuxStream
GstBufferListIterator *currentit; GstBufferListIterator *currentit;
GList *currentlist; GList *currentlist;
/* Current PTS for this stream */ /* Current PTS/DTS for this stream */
GstClockTime pts; GstClockTime pts;
GstClockTime dts;
/* Raw value of current PTS/DTS */
guint64 raw_pts;
guint64 raw_dts;
/* Number of rollover seen for PTS/DTS (default:0) */
guint nb_pts_rollover;
guint nb_dts_rollover;
}; };
#define VIDEO_CAPS \ #define VIDEO_CAPS \
@ -1229,7 +1239,13 @@ gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * bstream,
/* Create the pad */ /* Create the pad */
if (bstream->stream_type != 0xff) if (bstream->stream_type != 0xff)
stream->pad = create_pad_for_stream (base, bstream, program); stream->pad = create_pad_for_stream (base, bstream, program);
stream->pts = GST_CLOCK_TIME_NONE; stream->pts = GST_CLOCK_TIME_NONE;
stream->dts = GST_CLOCK_TIME_NONE;
stream->raw_pts = 0;
stream->raw_dts = 0;
stream->nb_pts_rollover = 0;
stream->nb_dts_rollover = 0;
} }
stream->flow_return = GST_FLOW_OK; stream->flow_return = GST_FLOW_OK;
} }
@ -1865,9 +1881,33 @@ gst_ts_demux_record_pts (GstTSDemux * demux, TSDemuxStream * stream,
{ {
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
GST_LOG ("pid 0x%04x pts:%" GST_TIME_FORMAT " at offset %" GST_LOG ("pid 0x%04x pts:%" G_GUINT64_FORMAT " at offset %"
G_GUINT64_FORMAT, bs->pid, G_GUINT64_FORMAT, bs->pid, pts, offset);
GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (pts)), offset);
if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (stream->pts) &&
ABSDIFF (stream->raw_pts, pts) > 900000)) {
/* Detect rollover if diff > 10s */
GST_LOG ("Detected rollover (previous:%" G_GUINT64_FORMAT " new:%"
G_GUINT64_FORMAT ")", stream->raw_pts, pts);
if (pts < stream->raw_pts) {
/* Forward rollover */
GST_LOG ("Forward rollover, incrementing nb_pts_rollover");
stream->nb_pts_rollover++;
} else {
/* Reverse rollover */
GST_LOG ("Reverse rollover, decrementing nb_pts_rollover");
stream->nb_pts_rollover--;
}
}
/* Compute PTS in GstClockTime */
stream->raw_pts = pts;
stream->pts =
MPEGTIME_TO_GSTTIME (pts + stream->nb_pts_rollover * PTS_DTS_MAX_VALUE);
GST_LOG ("pid 0x%04x Stored PTS %" G_GUINT64_FORMAT " (%" GST_TIME_FORMAT ")",
bs->pid, stream->raw_pts, GST_TIME_ARGS (stream->pts));
if (G_UNLIKELY (demux->emit_statistics)) { if (G_UNLIKELY (demux->emit_statistics)) {
GstStructure *st; GstStructure *st;
@ -1887,9 +1927,32 @@ gst_ts_demux_record_dts (GstTSDemux * demux, TSDemuxStream * stream,
{ {
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
GST_LOG ("pid 0x%04x dts:%" GST_TIME_FORMAT " at offset %" GST_LOG ("pid 0x%04x dts:%" G_GUINT64_FORMAT " at offset %"
G_GUINT64_FORMAT, bs->pid, G_GUINT64_FORMAT, bs->pid, dts, offset);
GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (dts)), offset);
if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (stream->dts) &&
ABSDIFF (stream->raw_dts, dts) > 900000)) {
/* Detect rollover if diff > 10s */
GST_LOG ("Detected rollover (previous:%" G_GUINT64_FORMAT " new:%"
G_GUINT64_FORMAT ")", stream->raw_dts, dts);
if (dts < stream->raw_dts) {
/* Forward rollover */
GST_LOG ("Forward rollover, incrementing nb_dts_rollover");
stream->nb_dts_rollover++;
} else {
/* Reverse rollover */
GST_LOG ("Reverse rollover, decrementing nb_dts_rollover");
stream->nb_dts_rollover--;
}
}
/* Compute DTS in GstClockTime */
stream->raw_dts = dts;
stream->dts =
MPEGTIME_TO_GSTTIME (dts + stream->nb_dts_rollover * PTS_DTS_MAX_VALUE);
GST_LOG ("pid 0x%04x Stored DTS %" G_GUINT64_FORMAT " (%" GST_TIME_FORMAT ")",
bs->pid, stream->raw_dts, GST_TIME_ARGS (stream->dts));
if (G_UNLIKELY (demux->emit_statistics)) { if (G_UNLIKELY (demux->emit_statistics)) {
GstStructure *st; GstStructure *st;
@ -1939,7 +2002,6 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
guint8 *data; guint8 *data;
guint32 length; guint32 length;
guint64 bufferoffset; guint64 bufferoffset;
GstClockTime time;
PESParsingResult parseres; PESParsingResult parseres;
data = GST_BUFFER_DATA (stream->pendingbuffers[0]); data = GST_BUFFER_DATA (stream->pendingbuffers[0]);
@ -1957,6 +2019,9 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
goto discont; goto discont;
} }
if (header.DTS != -1)
gst_ts_demux_record_dts (demux, stream, header.DTS, bufferoffset);
if (header.PTS != -1) { if (header.PTS != -1) {
gst_ts_demux_record_pts (demux, stream, header.PTS, bufferoffset); gst_ts_demux_record_pts (demux, stream, header.PTS, bufferoffset);
@ -1980,7 +2045,6 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
time = calc_gsttime_from_pts (&demux->index_pcr, pts); time = calc_gsttime_from_pts (&demux->index_pcr, pts);
#endif #endif
stream->pts = time = MPEGTIME_TO_GSTTIME (header.PTS);
GST_DEBUG_OBJECT (base, "stream PTS %" GST_TIME_FORMAT, GST_DEBUG_OBJECT (base, "stream PTS %" GST_TIME_FORMAT,
GST_TIME_ARGS (stream->pts)); GST_TIME_ARGS (stream->pts));
@ -2012,12 +2076,10 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
if (!GST_CLOCK_TIME_IS_VALID (base->in_gap)) if (!GST_CLOCK_TIME_IS_VALID (base->in_gap))
base->in_gap = 0; base->in_gap = 0;
GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = time + base->in_gap; GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) =
stream->pts + base->in_gap;
} }
if (header.DTS != -1)
gst_ts_demux_record_dts (demux, stream, header.DTS, bufferoffset);
/* Remove PES headers */ /* Remove PES headers */
GST_DEBUG ("Moving data forward by %d bytes", header.header_size); GST_DEBUG ("Moving data forward by %d bytes", header.header_size);
GST_BUFFER_DATA (stream->pendingbuffers[0]) += header.header_size; GST_BUFFER_DATA (stream->pendingbuffers[0]) += header.header_size;