#define PCR_SMALL 17775000
/* maximal PCR time */
#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
* either accurately or for the next timestamp
GST_DEBUG_CATEGORY_STATIC (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_PID;
static GQuark QUARK_PCR;
GstBufferListIterator *currentit;
GList *currentlist;
- /* Current PTS for this stream */
+ /* Current PTS/DTS for this stream */
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 \
/* Create the pad */
if (bstream->stream_type != 0xff)
stream->pad = create_pad_for_stream (base, bstream, program);
+
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;
}
{
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
- GST_LOG ("pid 0x%04x pts:%" GST_TIME_FORMAT " at offset %"
- G_GUINT64_FORMAT, bs->pid,
- GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (pts)), offset);
+ GST_LOG ("pid 0x%04x pts:%" G_GUINT64_FORMAT " at offset %"
+ G_GUINT64_FORMAT, bs->pid, 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)) {
GstStructure *st;
{
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
- GST_LOG ("pid 0x%04x dts:%" GST_TIME_FORMAT " at offset %"
- G_GUINT64_FORMAT, bs->pid,
- GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (dts)), offset);
+ GST_LOG ("pid 0x%04x dts:%" G_GUINT64_FORMAT " at offset %"
+ G_GUINT64_FORMAT, bs->pid, 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)) {
GstStructure *st;
guint8 *data;
guint32 length;
guint64 bufferoffset;
- GstClockTime time;
PESParsingResult parseres;
data = GST_BUFFER_DATA (stream->pendingbuffers[0]);
goto discont;
}
+ if (header.DTS != -1)
+ gst_ts_demux_record_dts (demux, stream, header.DTS, bufferoffset);
+
if (header.PTS != -1) {
gst_ts_demux_record_pts (demux, stream, header.PTS, bufferoffset);
time = calc_gsttime_from_pts (&demux->index_pcr, pts);
#endif
- stream->pts = time = MPEGTIME_TO_GSTTIME (header.PTS);
GST_DEBUG_OBJECT (base, "stream PTS %" GST_TIME_FORMAT,
GST_TIME_ARGS (stream->pts));
if (!GST_CLOCK_TIME_IS_VALID (base->in_gap))
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 */
GST_DEBUG ("Moving data forward by %d bytes", header.header_size);
GST_BUFFER_DATA (stream->pendingbuffers[0]) += header.header_size;