mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-05 05:52:37 +00:00
tsdemux: Fix newsegment creation for push mode
And all relevent comments to what it should be doing, refactor everything a bit. Still not perfect ... but better. Fixes #654657
This commit is contained in:
parent
b73679e13d
commit
9f1511e998
1 changed files with 96 additions and 70 deletions
|
@ -2208,17 +2208,81 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
|
{
|
||||||
|
MpegTSBase *base = (MpegTSBase *) demux;
|
||||||
|
GstClockTime firstpts = GST_CLOCK_TIME_NONE;
|
||||||
|
GstEvent *newsegmentevent;
|
||||||
|
guint i;
|
||||||
|
gint64 start, stop, position;
|
||||||
|
|
||||||
|
GST_DEBUG ("Creating new newsegment");
|
||||||
|
|
||||||
|
/* Outgoing newsegment values
|
||||||
|
* start : The first/start PTS
|
||||||
|
* stop : The last PTS (or -1)
|
||||||
|
* position : The stream time corresponding to start
|
||||||
|
*
|
||||||
|
* Except for live mode with incoming GST_TIME_FORMAT newsegment where
|
||||||
|
* it is the same values as that incoming newsegment (and we convert the
|
||||||
|
* PTS to that remote clock).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Find the earliest current PTS we're going to push */
|
||||||
|
for (i = 0; i < 0x2000; i++) {
|
||||||
|
if (demux->program->streams[i]) {
|
||||||
|
if ((!GST_CLOCK_TIME_IS_VALID (firstpts))
|
||||||
|
|| (((TSDemuxStream *) demux->program->streams[i])->pts < firstpts))
|
||||||
|
firstpts = ((TSDemuxStream *) demux->program->streams[i])->pts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base->mode == BASE_MODE_PUSHING) {
|
||||||
|
/* FIXME : We're just ignore the upstream format for the time being */
|
||||||
|
/* FIXME : We should use base->segment.format and a upstream latency query
|
||||||
|
* to decide if we need to use live values or not */
|
||||||
|
|
||||||
|
start = firstpts;
|
||||||
|
stop = GST_CLOCK_TIME_NONE;
|
||||||
|
position = demux->segment.time;
|
||||||
|
} else {
|
||||||
|
/* pull mode */
|
||||||
|
GST_DEBUG ("pull-based. Segment start:%" GST_TIME_FORMAT " duration:%"
|
||||||
|
GST_TIME_FORMAT ", time:%" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (demux->segment.start),
|
||||||
|
GST_TIME_ARGS (demux->segment.duration),
|
||||||
|
GST_TIME_ARGS (demux->segment.time));
|
||||||
|
|
||||||
|
GST_DEBUG ("firstpcr gsttime : %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (demux->first_pcr.gsttime));
|
||||||
|
|
||||||
|
/* FIXME : This is not entirely correct. We should be using the PTS time
|
||||||
|
* realm and not the PCR one. Doesn't matter *too* much if PTS/PCR values
|
||||||
|
* aren't too far apart, but still. */
|
||||||
|
start = demux->first_pcr.gsttime + demux->segment.start;
|
||||||
|
stop = demux->first_pcr.gsttime + demux->segment.duration;
|
||||||
|
position = demux->segment.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG ("new segment: start: %" GST_TIME_FORMAT " stop: %"
|
||||||
|
GST_TIME_FORMAT " time: %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
|
||||||
|
GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
|
||||||
|
newsegmentevent =
|
||||||
|
gst_event_new_new_segment (0, 1.0, GST_FORMAT_TIME, start, stop,
|
||||||
|
position);
|
||||||
|
|
||||||
|
push_event ((MpegTSBase *) demux, newsegmentevent);
|
||||||
|
|
||||||
|
demux->need_newsegment = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
|
gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
{
|
{
|
||||||
GstFlowReturn res = GST_FLOW_OK;
|
GstFlowReturn res = GST_FLOW_OK;
|
||||||
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
|
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
|
||||||
|
|
||||||
|
|
||||||
guint i;
|
|
||||||
GstClockTime tinypts = GST_CLOCK_TIME_NONE;
|
|
||||||
GstEvent *newsegmentevent;
|
|
||||||
|
|
||||||
GST_DEBUG ("stream:%p, pid:0x%04x stream_type:%d state:%d pad:%s:%s",
|
GST_DEBUG ("stream:%p, pid:0x%04x stream_type:%d state:%d pad:%s:%s",
|
||||||
stream, bs->pid, bs->stream_type, stream->state,
|
stream, bs->pid, bs->stream_type, stream->state,
|
||||||
GST_DEBUG_PAD_NAME (stream->pad));
|
GST_DEBUG_PAD_NAME (stream->pad));
|
||||||
|
@ -2233,53 +2297,26 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (stream->state != PENDING_PACKET_BUFFER))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (stream->pad == NULL)) {
|
||||||
|
g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL);
|
||||||
|
g_list_free (stream->currentlist);
|
||||||
|
gst_buffer_list_iterator_free (stream->currentit);
|
||||||
|
gst_buffer_list_unref (stream->current);
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (demux->need_newsegment))
|
||||||
|
calculate_and_push_newsegment (demux, stream);
|
||||||
|
|
||||||
/* We have a confirmed buffer, let's push it out */
|
/* We have a confirmed buffer, let's push it out */
|
||||||
if (stream->state == PENDING_PACKET_BUFFER) {
|
GST_LOG ("Putting pending data into GstBufferList");
|
||||||
GST_LOG ("BUFFER: pushing out pending data");
|
|
||||||
stream->currentlist = g_list_reverse (stream->currentlist);
|
stream->currentlist = g_list_reverse (stream->currentlist);
|
||||||
gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist);
|
gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist);
|
||||||
gst_buffer_list_iterator_free (stream->currentit);
|
gst_buffer_list_iterator_free (stream->currentit);
|
||||||
|
|
||||||
|
|
||||||
if (stream->pad) {
|
|
||||||
|
|
||||||
if (demux->need_newsegment) {
|
|
||||||
|
|
||||||
for (i = 0; i < 0x2000; i++) {
|
|
||||||
|
|
||||||
if (demux->program->streams[i]) {
|
|
||||||
if ((!GST_CLOCK_TIME_IS_VALID (tinypts))
|
|
||||||
|| (((TSDemuxStream *) demux->program->streams[i])->pts <
|
|
||||||
tinypts))
|
|
||||||
tinypts = ((TSDemuxStream *) demux->program->streams[i])->pts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("old segment: tinypts: %" GST_TIME_FORMAT " stop: %"
|
|
||||||
GST_TIME_FORMAT " time: %" GST_TIME_FORMAT,
|
|
||||||
GST_TIME_ARGS (tinypts),
|
|
||||||
GST_TIME_ARGS (demux->first_pcr.gsttime + demux->duration),
|
|
||||||
GST_TIME_ARGS (tinypts - demux->first_pcr.gsttime));
|
|
||||||
/* newsegmentevent = */
|
|
||||||
/* gst_event_new_new_segment (0, 1.0, GST_FORMAT_TIME, tinypts, */
|
|
||||||
/* demux->first_pcr.gsttime + demux->duration, */
|
|
||||||
/* tinypts - demux->first_pcr.gsttime); */
|
|
||||||
GST_DEBUG ("new segment: start: %" GST_TIME_FORMAT " stop: %"
|
|
||||||
GST_TIME_FORMAT " time: %" GST_TIME_FORMAT,
|
|
||||||
GST_TIME_ARGS (demux->first_pcr.gsttime + demux->segment.start),
|
|
||||||
GST_TIME_ARGS (demux->first_pcr.gsttime + demux->segment.duration),
|
|
||||||
GST_TIME_ARGS (demux->segment.time));
|
|
||||||
newsegmentevent =
|
|
||||||
gst_event_new_new_segment (0, 1.0, GST_FORMAT_TIME,
|
|
||||||
demux->first_pcr.gsttime + demux->segment.start,
|
|
||||||
demux->first_pcr.gsttime + demux->segment.duration,
|
|
||||||
demux->segment.time);
|
|
||||||
|
|
||||||
push_event ((MpegTSBase *) demux, newsegmentevent);
|
|
||||||
|
|
||||||
demux->need_newsegment = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (stream->pad,
|
GST_DEBUG_OBJECT (stream->pad,
|
||||||
"Pushing buffer list with timestamp: %" GST_TIME_FORMAT,
|
"Pushing buffer list with timestamp: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (gst_buffer_list_get
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (gst_buffer_list_get
|
||||||
|
@ -2287,28 +2324,17 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
|
|
||||||
res = gst_pad_push_list (stream->pad, stream->current);
|
res = gst_pad_push_list (stream->pad, stream->current);
|
||||||
GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res));
|
GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res));
|
||||||
/* FIXME : combine flow returns */
|
|
||||||
res = tsdemux_combine_flows (demux, stream, res);
|
res = tsdemux_combine_flows (demux, stream, res);
|
||||||
GST_DEBUG_OBJECT (stream->pad, "combined %s", gst_flow_get_name (res));
|
GST_DEBUG_OBJECT (stream->pad, "combined %s", gst_flow_get_name (res));
|
||||||
} else {
|
|
||||||
gst_buffer_list_unref (stream->current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
beach:
|
beach:
|
||||||
/* Reset everything */
|
/* Reset everything */
|
||||||
GST_LOG ("Resetting to EMPTY");
|
GST_LOG ("Resetting to EMPTY");
|
||||||
stream->state = PENDING_PACKET_EMPTY;
|
stream->state = PENDING_PACKET_EMPTY;
|
||||||
|
|
||||||
/* for (i = 0; i < stream->nbpending; i++) */
|
|
||||||
/* gst_buffer_unref (stream->pendingbuffers[i]); */
|
|
||||||
memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS);
|
memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS);
|
||||||
stream->nbpending = 0;
|
stream->nbpending = 0;
|
||||||
|
|
||||||
stream->current = NULL;
|
stream->current = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue