mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
asfdemux: use upstream segment and timestamps for some interpolation
This should particularly help in case of upstream live src, e.g. rtspsrc, and especially so if it has to perform fallback to TCP.
This commit is contained in:
parent
71da4cc7ae
commit
e8a6ad2546
3 changed files with 41 additions and 9 deletions
|
@ -191,7 +191,7 @@ gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload,
|
|||
demux->segment_ts = payload->ts;
|
||||
/* always note, but only determines segment when streaming */
|
||||
if (demux->streaming)
|
||||
gst_segment_set_seek (&demux->segment, demux->segment.rate,
|
||||
gst_segment_set_seek (&demux->segment, demux->in_segment.rate,
|
||||
GST_FORMAT_TIME, demux->segment.flags, GST_SEEK_TYPE_SET,
|
||||
demux->segment_ts, GST_SEEK_TYPE_NONE, 0, NULL);
|
||||
}
|
||||
|
|
|
@ -208,6 +208,8 @@ gst_asf_demux_reset (GstASFDemux * demux)
|
|||
demux->activated_streams = FALSE;
|
||||
demux->first_ts = GST_CLOCK_TIME_NONE;
|
||||
demux->segment_ts = GST_CLOCK_TIME_NONE;
|
||||
demux->in_gap = 0;
|
||||
gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
|
||||
demux->state = GST_ASF_DEMUX_STATE_HEADER;
|
||||
demux->seekable = FALSE;
|
||||
demux->broadcast = FALSE;
|
||||
|
@ -292,10 +294,12 @@ gst_asf_demux_sink_event (GstPad * pad, GstEvent * event)
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NEWSEGMENT:{
|
||||
GstFormat newsegment_format;
|
||||
gint64 newsegment_start;
|
||||
gint64 newsegment_start, stop, time;
|
||||
gdouble rate, arate;
|
||||
gboolean update;
|
||||
|
||||
gst_event_parse_new_segment (event, NULL, NULL, &newsegment_format,
|
||||
&newsegment_start, NULL, NULL);
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate,
|
||||
&newsegment_format, &newsegment_start, &stop, &time);
|
||||
|
||||
if (newsegment_format == GST_FORMAT_BYTES) {
|
||||
if (demux->packet_size && newsegment_start > demux->data_offset)
|
||||
|
@ -307,14 +311,21 @@ gst_asf_demux_sink_event (GstPad * pad, GstEvent * event)
|
|||
/* do not know packet position, not really a problem */
|
||||
demux->packet = -1;
|
||||
} else {
|
||||
GST_WARNING_OBJECT (demux, "unsupported newsegment format , ignoring");
|
||||
GST_WARNING_OBJECT (demux, "unsupported newsegment format, ignoring");
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
}
|
||||
|
||||
/* record upstream segment for interpolation */
|
||||
if (newsegment_format != demux->in_segment.format)
|
||||
gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
|
||||
gst_segment_set_newsegment_full (&demux->in_segment, update, rate, arate,
|
||||
newsegment_format, newsegment_start, stop, time);
|
||||
|
||||
/* in either case, clear some state and generate newsegment later on */
|
||||
GST_OBJECT_LOCK (demux);
|
||||
demux->segment_ts = GST_CLOCK_TIME_NONE;
|
||||
demux->in_gap = GST_CLOCK_TIME_NONE;
|
||||
demux->need_newsegment = TRUE;
|
||||
gst_asf_demux_reset_stream_state_after_discont (demux);
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
|
@ -1188,10 +1199,16 @@ gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
|
|||
/* wait until we had a chance to "lock on" some payload's timestamp */
|
||||
if (!GST_CLOCK_TIME_IS_VALID (demux->segment_ts))
|
||||
return GST_FLOW_OK;
|
||||
else {
|
||||
/* safe default if insufficient upstream info */
|
||||
if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
|
||||
demux->in_gap = 0;
|
||||
}
|
||||
|
||||
if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
|
||||
demux->segment.duration > 0) {
|
||||
demux->segment.stop = demux->segment.duration;
|
||||
/* slight HACK; prevent clipping of last bit */
|
||||
demux->segment.stop = demux->segment.duration + demux->in_gap;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
|
||||
|
@ -1240,7 +1257,11 @@ gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
|
|||
|
||||
gst_buffer_set_caps (payload->buf, stream->caps);
|
||||
|
||||
GST_BUFFER_TIMESTAMP (payload->buf) = payload->ts;
|
||||
/* (sort of) interpolate timestamps using upstream "frame of reference",
|
||||
* typically useful for live src, but might (unavoidably) mess with
|
||||
* position reporting if a live src is playing not so live content
|
||||
* (e.g. rtspsrc taking some time to fall back to tcp) */
|
||||
GST_BUFFER_TIMESTAMP (payload->buf) = payload->ts + demux->in_gap;
|
||||
GST_BUFFER_DURATION (payload->buf) = payload->duration;
|
||||
|
||||
/* FIXME: we should really set durations on buffers if we can */
|
||||
|
@ -1398,12 +1419,21 @@ gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
|
|||
|
||||
demux = GST_ASF_DEMUX (GST_PAD_PARENT (pad));
|
||||
|
||||
GST_LOG_OBJECT (demux, "buffer: size=%u, offset=%" G_GINT64_FORMAT,
|
||||
GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf));
|
||||
GST_LOG_OBJECT (demux, "buffer: size=%u, offset=%" G_GINT64_FORMAT ", time=%"
|
||||
GST_TIME_FORMAT, GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf),
|
||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
|
||||
|
||||
if (GST_BUFFER_IS_DISCONT (buf))
|
||||
gst_asf_demux_reset_stream_state_after_discont (demux);
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
|
||||
GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
||||
demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
|
||||
GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
|
||||
", interpolation gap: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
|
||||
}
|
||||
|
||||
gst_adapter_push (demux->adapter, buf);
|
||||
|
||||
switch (demux->state) {
|
||||
|
|
|
@ -170,6 +170,8 @@ struct _GstASFDemux {
|
|||
|
||||
gboolean need_newsegment; /* do we need to send a new-segment event? */
|
||||
GstClockTime segment_ts; /* streaming; timestamp for segment start */
|
||||
GstSegment in_segment; /* streaming; upstream segment info */
|
||||
GstClockTime in_gap; /* streaming; upstream initial segment gap for interpolation */
|
||||
gboolean segment_running; /* if we've started the current segment */
|
||||
gboolean streaming; /* TRUE if we are operating chain-based */
|
||||
GstClockTime latency;
|
||||
|
|
Loading…
Reference in a new issue