From 8b73baeced99de22c71fb76b8209ee504edf8f4a Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Tue, 8 Nov 2011 20:19:41 +0100 Subject: [PATCH] tsdemux: Use incoming timestamps in live mode --- gst/mpegtsdemux/tsdemux.c | 66 ++++++++++++++++++++++++++++++++------- gst/mpegtsdemux/tsdemux.h | 4 +++ 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index c3b26c1b3b..276aaf93c9 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -310,6 +310,7 @@ gst_ts_demux_init (GstTSDemux * demux, GstTSDemuxClass * klass) demux->need_newsegment = TRUE; demux->program_number = -1; demux->duration = GST_CLOCK_TIME_NONE; + demux->pts_delta = GST_CLOCK_TIME_NONE; GST_MPEGTS_BASE (demux)->stream_size = sizeof (TSDemuxStream); gst_segment_init (&demux->segment, GST_FORMAT_TIME); demux->first_pcr = (TSPcrOffset) { @@ -333,6 +334,7 @@ gst_ts_demux_reset (MpegTSBase * base) demux->need_newsegment = TRUE; demux->program_number = -1; demux->duration = GST_CLOCK_TIME_NONE; + demux->pts_delta = GST_CLOCK_TIME_NONE; gst_segment_init (&demux->segment, GST_FORMAT_TIME); demux->first_pcr = (TSPcrOffset) { GST_CLOCK_TIME_NONE, 0, 0}; @@ -2039,9 +2041,11 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) guint32 length; guint64 bufferoffset; PESParsingResult parseres; + GstClockTime origts; data = GST_BUFFER_DATA (stream->pendingbuffers[0]); length = GST_BUFFER_SIZE (stream->pendingbuffers[0]); + origts = GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]); bufferoffset = GST_BUFFER_OFFSET (stream->pendingbuffers[0]); GST_MEMDUMP ("Header buffer", data, MIN (length, 32)); @@ -2081,8 +2085,24 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) time = calc_gsttime_from_pts (&demux->index_pcr, pts); #endif - GST_DEBUG_OBJECT (base, "stream PTS %" GST_TIME_FORMAT, - GST_TIME_ARGS (stream->pts)); + GST_DEBUG_OBJECT (base, + "stream PTS %" GST_TIME_FORMAT " DTS %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream->pts), + GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (header.DTS))); + + /* FIXME : This will only work if the PES header is contained + * at the beginning of an incoming GstBuffer */ + if (base->upstream_live && GST_CLOCK_TIME_IS_VALID (origts) + && !GST_CLOCK_TIME_IS_VALID (demux->pts_delta)) { + if (header.DTS != -1) + demux->pts_delta = MPEGTIME_TO_GSTTIME (header.DTS) - origts; + else + demux->pts_delta = stream->pts - origts; + GST_DEBUG_OBJECT (base, "buffer timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (origts)); + GST_DEBUG_OBJECT (base, "delta %" GST_TIME_FORMAT, + GST_TIME_ARGS (demux->pts_delta)); + } /* safe default if insufficient upstream info */ if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (base->in_gap) && @@ -2112,8 +2132,16 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) if (!GST_CLOCK_TIME_IS_VALID (base->in_gap)) base->in_gap = 0; - GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = - stream->pts + base->in_gap; + if (base->upstream_live) { + if (GST_CLOCK_TIME_IS_VALID (demux->pts_delta)) + GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = + stream->pts - demux->pts_delta; + else + GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = GST_CLOCK_TIME_NONE; + } else + GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = stream->pts + base->in_gap; + GST_DEBUG ("buf %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]))); } /* Remove PES headers */ @@ -2250,8 +2278,10 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream) start = base->segment.start; stop = base->segment.stop; } - /* Shift the start depending on our position in the stream */ - start += firstpts + base->in_gap - base->first_buf_ts; + if (!base->upstream_live) { + /* Shift the start depending on our position in the stream */ + start += firstpts + base->in_gap - base->first_buf_ts; + } position = start; } else { /* pull mode */ @@ -2289,10 +2319,12 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) { GstFlowReturn res = GST_FLOW_OK; MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; + /* MpegTSBase *base = (MpegTSBase*) demux; */ + GstBuffer *firstbuffer = NULL; - GST_DEBUG ("stream:%p, pid:0x%04x stream_type:%d state:%d pad:%s:%s", - stream, bs->pid, bs->stream_type, stream->state, - GST_DEBUG_PAD_NAME (stream->pad)); + GST_DEBUG_OBJECT (stream->pad, + "stream:%p, pid:0x%04x stream_type:%d state:%d", stream, bs->pid, + bs->stream_type, stream->state); if (G_UNLIKELY (stream->current == NULL)) { GST_LOG ("stream->current == NULL"); @@ -2319,15 +2351,25 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) calculate_and_push_newsegment (demux, stream); /* We have a confirmed buffer, let's push it out */ - GST_LOG ("Putting pending data into GstBufferList"); + GST_LOG_OBJECT (stream->pad, "Putting pending data into GstBufferList"); stream->currentlist = g_list_reverse (stream->currentlist); gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist); gst_buffer_list_iterator_free (stream->currentit); + firstbuffer = gst_buffer_list_get (stream->current, 0, 0); + + GST_DEBUG_OBJECT (stream->pad, + "delta %" GST_TIME_FORMAT " stream->pts %" GST_TIME_FORMAT, + GST_TIME_ARGS (demux->pts_delta), GST_TIME_ARGS (stream->pts)); + if (GST_CLOCK_TIME_IS_VALID (demux->pts_delta) + && GST_CLOCK_TIME_IS_VALID (stream->pts) + && !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (firstbuffer))) { + GST_BUFFER_TIMESTAMP (firstbuffer) = stream->pts - demux->pts_delta; + } + GST_DEBUG_OBJECT (stream->pad, "Pushing buffer list with timestamp: %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (gst_buffer_list_get - (stream->current, 0, 0)))); + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (firstbuffer))); res = gst_pad_push_list (stream->pad, stream->current); GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res)); diff --git a/gst/mpegtsdemux/tsdemux.h b/gst/mpegtsdemux/tsdemux.h index 395cf3e134..0a7d880732 100644 --- a/gst/mpegtsdemux/tsdemux.h +++ b/gst/mpegtsdemux/tsdemux.h @@ -81,6 +81,10 @@ struct _GstTSDemux TSPcrOffset last_pcr; TSPcrOffset cur_pcr; TSPcrOffset index_pcr; + + /* LIVE MODE ONLY */ + /* Delta between incoming ts and PTS */ + GstClockTime pts_delta; }; struct _GstTSDemuxClass