adaptivedemux: Store QoS values on the element

Storing it per-stream requires taking the manifest lock which can apparenly be
hold for aeons. And since the QoS event comes from the video rendering thread
we *really* do not want to do that.

Storing it as-is in the element is fine, the important part is knowing the
earliest time downstream.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1021>
This commit is contained in:
Edward Hervey 2020-11-09 11:41:10 +01:00 committed by GStreamer Merge Bot
parent e700a21993
commit dd425fe0fd
3 changed files with 47 additions and 27 deletions

View file

@ -218,8 +218,7 @@
* GstDashDemuxStream->actual_position.
*
* The downstream position of the pipeline is obtained via QoS events and
* is stored in GstAdaptiveDemuxStream->qos_earliest_time (note: it's a
* running time value).
* is stored in GstAdaptiveDemux (note: it's a running time value).
*
* The estimated buffering level between dashdemux and downstream is
* therefore:
@ -1764,6 +1763,7 @@ gst_dash_demux_stream_get_target_time (GstDashDemux * dashdemux,
GstClockTimeDiff diff;
GstClockTime ret = cur_position;
GstClockTime deadline;
GstClockTime upstream_earliest_time;
GstClockTime earliest_time = GST_CLOCK_TIME_NONE;
g_assert (min_skip > 0);
@ -1785,7 +1785,9 @@ gst_dash_demux_stream_get_target_time (GstDashDemux * dashdemux,
* flush, as otherwise base_time and clock might not be correct because of a
* still pre-rolling sink
*/
if (stream->qos_earliest_time != GST_CLOCK_TIME_NONE) {
upstream_earliest_time =
gst_adaptive_demux_get_qos_earliest_time ((GstAdaptiveDemux *) dashdemux);
if (upstream_earliest_time != GST_CLOCK_TIME_NONE) {
GstClock *clock;
clock = gst_element_get_clock (GST_ELEMENT_CAST (dashdemux));
@ -1803,9 +1805,9 @@ gst_dash_demux_stream_get_target_time (GstDashDemux * dashdemux,
gst_object_unref (clock);
earliest_time = MAX (now_time, stream->qos_earliest_time);
earliest_time = MAX (now_time, upstream_earliest_time);
} else {
earliest_time = stream->qos_earliest_time;
earliest_time = upstream_earliest_time;
}
}

View file

@ -205,6 +205,8 @@ struct _GstAdaptiveDemuxPrivate
* without needing to stop tasks when they just want to
* update the segment boundaries */
GMutex segment_lock;
GstClockTime qos_earliest_time;
};
typedef struct _GstAdaptiveDemuxTimer
@ -1203,12 +1205,12 @@ gst_adaptive_demux_prepare_streams (GstAdaptiveDemux * demux,
stream->pending_segment = gst_event_new_segment (&stream->segment);
gst_event_set_seqnum (stream->pending_segment, demux->priv->segment_seqnum);
stream->qos_earliest_time = GST_CLOCK_TIME_NONE;
GST_DEBUG_OBJECT (demux,
"Prepared segment %" GST_SEGMENT_FORMAT " for stream %p",
&stream->segment, stream);
}
demux->priv->qos_earliest_time = GST_CLOCK_TIME_NONE;
return TRUE;
}
@ -1526,8 +1528,8 @@ gst_adaptive_demux_update_streams_segment (GstAdaptiveDemux * demux,
gst_event_unref (seg_evt);
/* Make sure the first buffer after a seek has the discont flag */
stream->discont = TRUE;
stream->qos_earliest_time = GST_CLOCK_TIME_NONE;
}
demux->priv->qos_earliest_time = GST_CLOCK_TIME_NONE;
}
#define IS_SNAP_SEEK(f) (f & (GST_SEEK_FLAG_SNAP_BEFORE | \
@ -1907,25 +1909,19 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent,
return TRUE;
}
case GST_EVENT_QOS:{
GstAdaptiveDemuxStream *stream;
GstClockTimeDiff diff;
GstClockTime timestamp;
GST_MANIFEST_LOCK (demux);
stream = gst_adaptive_demux_find_stream_for_pad (demux, pad);
if (stream) {
GstClockTimeDiff diff;
GstClockTime timestamp;
gst_event_parse_qos (event, NULL, NULL, &diff, &timestamp);
/* Only take into account lateness if late */
if (diff > 0)
stream->qos_earliest_time = timestamp + 2 * diff;
else
stream->qos_earliest_time = timestamp;
GST_DEBUG_OBJECT (stream->pad, "qos_earliest_time %" GST_TIME_FORMAT,
GST_TIME_ARGS (stream->qos_earliest_time));
}
GST_MANIFEST_UNLOCK (demux);
gst_event_parse_qos (event, NULL, NULL, &diff, &timestamp);
/* Only take into account lateness if late */
GST_OBJECT_LOCK (demux);
if (diff > 0)
demux->priv->qos_earliest_time = timestamp + 2 * diff;
else
demux->priv->qos_earliest_time = timestamp;
GST_OBJECT_UNLOCK (demux);
GST_DEBUG_OBJECT (demux, "qos_earliest_time %" GST_TIME_FORMAT,
GST_TIME_ARGS (demux->priv->qos_earliest_time));
break;
}
default:
@ -2197,10 +2193,10 @@ gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux, gboolean stop_updates)
stream->download_error_count = 0;
stream->need_header = TRUE;
stream->qos_earliest_time = GST_CLOCK_TIME_NONE;
}
list_to_process = demux->prepared_streams;
}
demux->priv->qos_earliest_time = GST_CLOCK_TIME_NONE;
}
/* must be called with manifest_lock taken */
@ -4659,3 +4655,22 @@ gst_adaptive_demux_clock_callback (GstClock * clock,
g_mutex_unlock (timer->mutex);
return TRUE;
}
/**
* gst_adaptive_demux_get_qos_earliest_time:
*
* Returns: The QOS earliest time
*
* Since: 1.18
*/
GstClockTime
gst_adaptive_demux_get_qos_earliest_time (GstAdaptiveDemux * demux)
{
GstClockTime earliest;
GST_OBJECT_LOCK (demux);
earliest = demux->priv->qos_earliest_time;
GST_OBJECT_UNLOCK (demux);
return earliest;
}

View file

@ -184,7 +184,7 @@ struct _GstAdaptiveDemuxStream
guint moving_index;
guint64 *fragment_bitrates;
/* QoS data */
/* QoS data : UNUSED !!! */
GstClockTime qos_earliest_time;
GstAdaptiveDemuxStreamFragment fragment;
@ -532,6 +532,9 @@ GDateTime *gst_adaptive_demux_get_client_now_utc (GstAdaptiveDemux * demux);
GST_ADAPTIVE_DEMUX_API
gboolean gst_adaptive_demux_is_running (GstAdaptiveDemux * demux);
GST_ADAPTIVE_DEMUX_API
GstClockTime gst_adaptive_demux_get_qos_earliest_time (GstAdaptiveDemux *demux);
G_END_DECLS
#endif