mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
adaptivedemux: Preroll streams before exposing them
To ensure that pads have caps when they are exposed, do the exposing when all pending streams have prerolled an output buffer, and only then EOS and remove any old pads. Improves the switching sequence by making caps available as soon as a pad appears. With fixes from Seungha Yang <sh.yang@lge.com> https://bugzilla.gnome.org/show_bug.cgi?id=758257
This commit is contained in:
parent
9b778f7264
commit
b2113f69c6
2 changed files with 180 additions and 31 deletions
|
@ -198,6 +198,11 @@ struct _GstAdaptiveDemuxPrivate
|
||||||
GCond manifest_cond;
|
GCond manifest_cond;
|
||||||
GMutex manifest_update_lock;
|
GMutex manifest_update_lock;
|
||||||
|
|
||||||
|
/* Lock and condition for prerolling streams before exposing */
|
||||||
|
GMutex preroll_lock;
|
||||||
|
GCond preroll_cond;
|
||||||
|
gint preroll_pending;
|
||||||
|
|
||||||
GMutex api_lock;
|
GMutex api_lock;
|
||||||
|
|
||||||
/* Protects demux and stream segment information
|
/* Protects demux and stream segment information
|
||||||
|
@ -242,8 +247,9 @@ static void gst_adaptive_demux_updates_loop (GstAdaptiveDemux * demux);
|
||||||
static void gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream *
|
static void gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream *
|
||||||
stream);
|
stream);
|
||||||
static void gst_adaptive_demux_reset (GstAdaptiveDemux * demux);
|
static void gst_adaptive_demux_reset (GstAdaptiveDemux * demux);
|
||||||
static gboolean gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
|
static gboolean gst_adaptive_demux_prepare_streams (GstAdaptiveDemux * demux,
|
||||||
gboolean first_and_live);
|
gboolean first_and_live);
|
||||||
|
static gboolean gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux);
|
||||||
static gboolean gst_adaptive_demux_is_live (GstAdaptiveDemux * demux);
|
static gboolean gst_adaptive_demux_is_live (GstAdaptiveDemux * demux);
|
||||||
static GstFlowReturn gst_adaptive_demux_stream_seek (GstAdaptiveDemux * demux,
|
static GstFlowReturn gst_adaptive_demux_stream_seek (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream, gboolean forward, GstSeekFlags flags,
|
GstAdaptiveDemuxStream * stream, gboolean forward, GstSeekFlags flags,
|
||||||
|
@ -270,7 +276,8 @@ static GstFlowReturn
|
||||||
gst_adaptive_demux_stream_push_event (GstAdaptiveDemuxStream * stream,
|
gst_adaptive_demux_stream_push_event (GstAdaptiveDemuxStream * stream,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
|
|
||||||
static void gst_adaptive_demux_start_tasks (GstAdaptiveDemux * demux);
|
static void gst_adaptive_demux_start_tasks (GstAdaptiveDemux * demux,
|
||||||
|
gboolean start_preroll_streams);
|
||||||
static void gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux);
|
static void gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux);
|
||||||
static GstFlowReturn gst_adaptive_demux_combine_flows (GstAdaptiveDemux *
|
static GstFlowReturn gst_adaptive_demux_combine_flows (GstAdaptiveDemux *
|
||||||
demux);
|
demux);
|
||||||
|
@ -483,6 +490,9 @@ gst_adaptive_demux_init (GstAdaptiveDemux * demux,
|
||||||
g_mutex_init (&demux->priv->api_lock);
|
g_mutex_init (&demux->priv->api_lock);
|
||||||
g_mutex_init (&demux->priv->segment_lock);
|
g_mutex_init (&demux->priv->segment_lock);
|
||||||
|
|
||||||
|
g_cond_init (&demux->priv->preroll_cond);
|
||||||
|
g_mutex_init (&demux->priv->preroll_lock);
|
||||||
|
|
||||||
pad_template =
|
pad_template =
|
||||||
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
|
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
|
||||||
g_return_if_fail (pad_template != NULL);
|
g_return_if_fail (pad_template != NULL);
|
||||||
|
@ -525,6 +535,9 @@ gst_adaptive_demux_finalize (GObject * object)
|
||||||
demux->realtime_clock = NULL;
|
demux->realtime_clock = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_cond_clear (&demux->priv->preroll_cond);
|
||||||
|
g_mutex_clear (&demux->priv->preroll_lock);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,9 +697,9 @@ gst_adaptive_demux_sink_event (GstPad * pad, GstObject * parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demux->next_streams) {
|
if (demux->next_streams) {
|
||||||
gst_adaptive_demux_expose_streams (demux,
|
gst_adaptive_demux_prepare_streams (demux,
|
||||||
gst_adaptive_demux_is_live (demux));
|
gst_adaptive_demux_is_live (demux));
|
||||||
gst_adaptive_demux_start_tasks (demux);
|
gst_adaptive_demux_start_tasks (demux, TRUE);
|
||||||
if (gst_adaptive_demux_is_live (demux)) {
|
if (gst_adaptive_demux_is_live (demux)) {
|
||||||
g_mutex_lock (&demux->priv->updates_timed_lock);
|
g_mutex_lock (&demux->priv->updates_timed_lock);
|
||||||
demux->priv->stop_updates_task = FALSE;
|
demux->priv->stop_updates_task = FALSE;
|
||||||
|
@ -775,6 +788,16 @@ gst_adaptive_demux_reset (GstAdaptiveDemux * demux)
|
||||||
gst_event_unref (eos);
|
gst_event_unref (eos);
|
||||||
g_list_free (demux->streams);
|
g_list_free (demux->streams);
|
||||||
demux->streams = NULL;
|
demux->streams = NULL;
|
||||||
|
if (demux->prepared_streams) {
|
||||||
|
g_list_free_full (demux->prepared_streams,
|
||||||
|
(GDestroyNotify) gst_adaptive_demux_stream_free);
|
||||||
|
demux->prepared_streams = NULL;
|
||||||
|
}
|
||||||
|
if (demux->next_streams) {
|
||||||
|
g_list_free_full (demux->next_streams,
|
||||||
|
(GDestroyNotify) gst_adaptive_demux_stream_free);
|
||||||
|
demux->next_streams = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (old_streams) {
|
if (old_streams) {
|
||||||
g_list_free_full (old_streams,
|
g_list_free_full (old_streams,
|
||||||
|
@ -872,10 +895,9 @@ gst_adaptive_demux_set_stream_struct_size (GstAdaptiveDemux * demux,
|
||||||
|
|
||||||
/* must be called with manifest_lock taken */
|
/* must be called with manifest_lock taken */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_adaptive_demux_expose_stream (GstAdaptiveDemux * demux,
|
gst_adaptive_demux_prepare_stream (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream)
|
GstAdaptiveDemuxStream * stream)
|
||||||
{
|
{
|
||||||
gboolean ret;
|
|
||||||
GstPad *pad = stream->pad;
|
GstPad *pad = stream->pad;
|
||||||
gchar *name = gst_pad_get_name (pad);
|
gchar *name = gst_pad_get_name (pad);
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
@ -907,16 +929,33 @@ gst_adaptive_demux_expose_stream (GstAdaptiveDemux * demux,
|
||||||
g_free (stream_id);
|
g_free (stream_id);
|
||||||
g_free (name);
|
g_free (name);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Adding srcpad %s:%s with caps %" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (demux, "Preparing srcpad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||||
GST_DEBUG_PAD_NAME (pad), stream->pending_caps);
|
|
||||||
|
stream->discont = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_adaptive_demux_expose_stream (GstAdaptiveDemux * demux,
|
||||||
|
GstAdaptiveDemuxStream * stream)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
GstPad *pad = stream->pad;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
if (stream->pending_caps) {
|
if (stream->pending_caps) {
|
||||||
gst_pad_set_caps (pad, stream->pending_caps);
|
gst_pad_set_caps (pad, stream->pending_caps);
|
||||||
gst_caps_unref (stream->pending_caps);
|
caps = stream->pending_caps;
|
||||||
stream->pending_caps = NULL;
|
stream->pending_caps = NULL;
|
||||||
|
} else {
|
||||||
|
caps = gst_pad_get_current_caps (pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->discont = TRUE;
|
GST_DEBUG_OBJECT (demux, "Exposing srcpad %s:%s with caps %" GST_PTR_FORMAT,
|
||||||
|
GST_DEBUG_PAD_NAME (pad), caps);
|
||||||
|
if (caps)
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
gst_object_ref (pad);
|
gst_object_ref (pad);
|
||||||
|
|
||||||
|
@ -959,17 +998,21 @@ gst_adaptive_demux_get_period_start_time (GstAdaptiveDemux * demux)
|
||||||
|
|
||||||
/* must be called with manifest_lock taken */
|
/* must be called with manifest_lock taken */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
|
gst_adaptive_demux_prepare_streams (GstAdaptiveDemux * demux,
|
||||||
gboolean first_and_live)
|
gboolean first_and_live)
|
||||||
{
|
{
|
||||||
GList *iter;
|
GList *iter;
|
||||||
GList *old_streams;
|
|
||||||
GstClockTime period_start, min_pts = GST_CLOCK_TIME_NONE;
|
GstClockTime period_start, min_pts = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
g_return_val_if_fail (demux->next_streams != NULL, FALSE);
|
g_return_val_if_fail (demux->next_streams != NULL, FALSE);
|
||||||
|
if (demux->prepared_streams != NULL) {
|
||||||
|
/* Old streams that were never exposed, due to a seek or so */
|
||||||
|
GST_FIXME_OBJECT (demux,
|
||||||
|
"Preparing new streams without cleaning up old ones!");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
old_streams = demux->streams;
|
demux->prepared_streams = demux->next_streams;
|
||||||
demux->streams = demux->next_streams;
|
|
||||||
demux->next_streams = NULL;
|
demux->next_streams = NULL;
|
||||||
|
|
||||||
if (!demux->running) {
|
if (!demux->running) {
|
||||||
|
@ -977,10 +1020,12 @@ gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
|
for (iter = demux->prepared_streams; iter; iter = g_list_next (iter)) {
|
||||||
GstAdaptiveDemuxStream *stream = iter->data;
|
GstAdaptiveDemuxStream *stream = iter->data;
|
||||||
|
|
||||||
if (!gst_adaptive_demux_expose_stream (demux,
|
stream->do_block = TRUE;
|
||||||
|
|
||||||
|
if (!gst_adaptive_demux_prepare_stream (demux,
|
||||||
GST_ADAPTIVE_DEMUX_STREAM_CAST (stream))) {
|
GST_ADAPTIVE_DEMUX_STREAM_CAST (stream))) {
|
||||||
/* TODO act on error */
|
/* TODO act on error */
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1056,7 @@ gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
|
||||||
GST_SEEK_TYPE_NONE, -1, NULL);
|
GST_SEEK_TYPE_NONE, -1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
|
for (iter = demux->prepared_streams; iter; iter = g_list_next (iter)) {
|
||||||
GstAdaptiveDemuxStream *stream = iter->data;
|
GstAdaptiveDemuxStream *stream = iter->data;
|
||||||
GstClockTime offset;
|
GstClockTime offset;
|
||||||
|
|
||||||
|
@ -1091,8 +1136,36 @@ gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
|
||||||
|
|
||||||
stream->pending_segment = gst_event_new_segment (&stream->segment);
|
stream->pending_segment = gst_event_new_segment (&stream->segment);
|
||||||
gst_event_set_seqnum (stream->pending_segment, demux->priv->segment_seqnum);
|
gst_event_set_seqnum (stream->pending_segment, demux->priv->segment_seqnum);
|
||||||
|
|
||||||
|
GST_DEBUG ("Prepared segment %" GST_SEGMENT_FORMAT " for stream %p",
|
||||||
|
&stream->segment, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux)
|
||||||
|
{
|
||||||
|
GList *iter;
|
||||||
|
GList *old_streams;
|
||||||
|
|
||||||
|
g_return_val_if_fail (demux->prepared_streams != NULL, FALSE);
|
||||||
|
|
||||||
|
old_streams = demux->streams;
|
||||||
|
demux->streams = demux->prepared_streams;
|
||||||
|
demux->prepared_streams = NULL;
|
||||||
|
|
||||||
|
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
|
||||||
|
GstAdaptiveDemuxStream *stream = iter->data;
|
||||||
|
|
||||||
|
if (!gst_adaptive_demux_expose_stream (demux,
|
||||||
|
GST_ADAPTIVE_DEMUX_STREAM_CAST (stream))) {
|
||||||
|
/* TODO act on error */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
demux->priv->preroll_pending = 0;
|
||||||
|
|
||||||
GST_MANIFEST_UNLOCK (demux);
|
GST_MANIFEST_UNLOCK (demux);
|
||||||
gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
|
gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
|
||||||
GST_MANIFEST_LOCK (demux);
|
GST_MANIFEST_LOCK (demux);
|
||||||
|
@ -1142,6 +1215,14 @@ gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
|
||||||
g_list_concat (demux->priv->old_streams, old_streams);
|
g_list_concat (demux->priv->old_streams, old_streams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unblock after removing oldstreams */
|
||||||
|
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
|
||||||
|
GstAdaptiveDemuxStream *stream = iter->data;
|
||||||
|
stream->do_block = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (demux, "All streams are exposed");
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1166,6 +1247,11 @@ gst_adaptive_demux_stream_new (GstAdaptiveDemux * demux, GstPad * pad)
|
||||||
g_malloc0 (sizeof (guint64) * NUM_LOOKBACK_FRAGMENTS);
|
g_malloc0 (sizeof (guint64) * NUM_LOOKBACK_FRAGMENTS);
|
||||||
gst_pad_set_element_private (pad, stream);
|
gst_pad_set_element_private (pad, stream);
|
||||||
|
|
||||||
|
g_mutex_lock (&demux->priv->preroll_lock);
|
||||||
|
stream->do_block = TRUE;
|
||||||
|
demux->priv->preroll_pending++;
|
||||||
|
g_mutex_unlock (&demux->priv->preroll_lock);
|
||||||
|
|
||||||
gst_pad_set_query_function (pad,
|
gst_pad_set_query_function (pad,
|
||||||
GST_DEBUG_FUNCPTR (gst_adaptive_demux_src_query));
|
GST_DEBUG_FUNCPTR (gst_adaptive_demux_src_query));
|
||||||
gst_pad_set_event_function (pad,
|
gst_pad_set_event_function (pad,
|
||||||
|
@ -1509,7 +1595,10 @@ gst_adaptive_demux_handle_seek_event (GstAdaptiveDemux * demux, GstPad * pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demux->next_streams) {
|
if (demux->next_streams) {
|
||||||
gst_adaptive_demux_expose_streams (demux, FALSE);
|
/* If the seek generated new streams, get them
|
||||||
|
* to preroll */
|
||||||
|
gst_adaptive_demux_prepare_streams (demux, FALSE);
|
||||||
|
gst_adaptive_demux_start_tasks (demux, TRUE);
|
||||||
} else {
|
} else {
|
||||||
GList *iter;
|
GList *iter;
|
||||||
GstClockTime period_start =
|
GstClockTime period_start =
|
||||||
|
@ -1540,10 +1629,11 @@ gst_adaptive_demux_handle_seek_event (GstAdaptiveDemux * demux, GstPad * pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_ADAPTIVE_DEMUX_SEGMENT_UNLOCK (demux);
|
GST_ADAPTIVE_DEMUX_SEGMENT_UNLOCK (demux);
|
||||||
|
|
||||||
|
/* Restart the demux */
|
||||||
|
gst_adaptive_demux_start_tasks (demux, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restart the demux */
|
|
||||||
gst_adaptive_demux_start_tasks (demux);
|
|
||||||
if (gst_adaptive_demux_is_live (demux)) {
|
if (gst_adaptive_demux_is_live (demux)) {
|
||||||
g_mutex_lock (&demux->priv->updates_timed_lock);
|
g_mutex_lock (&demux->priv->updates_timed_lock);
|
||||||
demux->priv->stop_updates_task = FALSE;
|
demux->priv->stop_updates_task = FALSE;
|
||||||
|
@ -1730,7 +1820,8 @@ gst_adaptive_demux_src_query (GstPad * pad, GstObject * parent,
|
||||||
|
|
||||||
/* must be called with manifest_lock taken */
|
/* must be called with manifest_lock taken */
|
||||||
static void
|
static void
|
||||||
gst_adaptive_demux_start_tasks (GstAdaptiveDemux * demux)
|
gst_adaptive_demux_start_tasks (GstAdaptiveDemux * demux,
|
||||||
|
gboolean start_preroll_streams)
|
||||||
{
|
{
|
||||||
GList *iter;
|
GList *iter;
|
||||||
|
|
||||||
|
@ -1740,12 +1831,17 @@ gst_adaptive_demux_start_tasks (GstAdaptiveDemux * demux)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_INFO_OBJECT (demux, "Starting streams' tasks");
|
GST_INFO_OBJECT (demux, "Starting streams' tasks");
|
||||||
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
|
|
||||||
|
iter = start_preroll_streams ? demux->prepared_streams : demux->streams;
|
||||||
|
|
||||||
|
for (; iter; iter = g_list_next (iter)) {
|
||||||
GstAdaptiveDemuxStream *stream = iter->data;
|
GstAdaptiveDemuxStream *stream = iter->data;
|
||||||
|
|
||||||
g_mutex_lock (&stream->fragment_download_lock);
|
if (!start_preroll_streams) {
|
||||||
stream->cancelled = FALSE;
|
g_mutex_lock (&stream->fragment_download_lock);
|
||||||
g_mutex_unlock (&stream->fragment_download_lock);
|
stream->cancelled = FALSE;
|
||||||
|
g_mutex_unlock (&stream->fragment_download_lock);
|
||||||
|
}
|
||||||
|
|
||||||
stream->last_ret = GST_FLOW_OK;
|
stream->last_ret = GST_FLOW_OK;
|
||||||
gst_task_start (stream->download_task);
|
gst_task_start (stream->download_task);
|
||||||
|
@ -1770,8 +1866,6 @@ gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux)
|
||||||
g_cond_signal (&demux->priv->updates_timed_cond);
|
g_cond_signal (&demux->priv->updates_timed_cond);
|
||||||
g_mutex_unlock (&demux->priv->updates_timed_lock);
|
g_mutex_unlock (&demux->priv->updates_timed_lock);
|
||||||
|
|
||||||
gst_uri_downloader_cancel (demux->downloader);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "Stopping tasks");
|
GST_LOG_OBJECT (demux, "Stopping tasks");
|
||||||
|
|
||||||
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
|
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
|
||||||
|
@ -1784,6 +1878,12 @@ gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux)
|
||||||
g_mutex_unlock (&stream->fragment_download_lock);
|
g_mutex_unlock (&stream->fragment_download_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_mutex_lock (&demux->priv->preroll_lock);
|
||||||
|
g_cond_broadcast (&demux->priv->preroll_cond);
|
||||||
|
g_mutex_unlock (&demux->priv->preroll_lock);
|
||||||
|
|
||||||
|
gst_uri_downloader_cancel (demux->downloader);
|
||||||
|
|
||||||
g_mutex_lock (&demux->priv->manifest_update_lock);
|
g_mutex_lock (&demux->priv->manifest_update_lock);
|
||||||
g_cond_broadcast (&demux->priv->manifest_cond);
|
g_cond_broadcast (&demux->priv->manifest_cond);
|
||||||
g_mutex_unlock (&demux->priv->manifest_update_lock);
|
g_mutex_unlock (&demux->priv->manifest_update_lock);
|
||||||
|
@ -1973,6 +2073,21 @@ gst_adaptive_demux_combine_flows (GstAdaptiveDemux * demux)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called with preroll_lock */
|
||||||
|
static void
|
||||||
|
gst_adaptive_demux_handle_preroll (GstAdaptiveDemux * demux,
|
||||||
|
GstAdaptiveDemuxStream * stream)
|
||||||
|
{
|
||||||
|
demux->priv->preroll_pending--;
|
||||||
|
if (demux->priv->preroll_pending == 0) {
|
||||||
|
/* That was the last one, time to release all streams
|
||||||
|
* and expose them */
|
||||||
|
GST_DEBUG_OBJECT (demux, "All streams prerolled. exposing");
|
||||||
|
gst_adaptive_demux_expose_streams (demux);
|
||||||
|
g_cond_broadcast (&demux->priv->preroll_cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* must be called with manifest_lock taken.
|
/* must be called with manifest_lock taken.
|
||||||
* Temporarily releases manifest_lock
|
* Temporarily releases manifest_lock
|
||||||
*/
|
*/
|
||||||
|
@ -2043,6 +2158,35 @@ gst_adaptive_demux_stream_push_buffer (GstAdaptiveDemuxStream * stream,
|
||||||
gst_caps_unref (stream->pending_caps);
|
gst_caps_unref (stream->pending_caps);
|
||||||
stream->pending_caps = NULL;
|
stream->pending_caps = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream->do_block) {
|
||||||
|
|
||||||
|
g_mutex_lock (&demux->priv->preroll_lock);
|
||||||
|
|
||||||
|
/* If we are preroll state, set caps in here */
|
||||||
|
if (pending_caps) {
|
||||||
|
gst_pad_push_event (stream->pad, pending_caps);
|
||||||
|
pending_caps = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_adaptive_demux_handle_preroll (demux, stream);
|
||||||
|
GST_MANIFEST_UNLOCK (demux);
|
||||||
|
|
||||||
|
while (stream->do_block && !stream->cancelled) {
|
||||||
|
GST_LOG_OBJECT (demux, "Stream %p sleeping for preroll", stream);
|
||||||
|
g_cond_wait (&demux->priv->preroll_cond, &demux->priv->preroll_lock);
|
||||||
|
}
|
||||||
|
if (stream->cancelled) {
|
||||||
|
GST_LOG_OBJECT (demux, "stream %p cancelled", stream);
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
g_mutex_unlock (&demux->priv->preroll_lock);
|
||||||
|
return GST_FLOW_FLUSHING;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mutex_unlock (&demux->priv->preroll_lock);
|
||||||
|
GST_MANIFEST_LOCK (demux);
|
||||||
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (stream->pending_segment)) {
|
if (G_UNLIKELY (stream->pending_segment)) {
|
||||||
GST_ADAPTIVE_DEMUX_SEGMENT_LOCK (demux);
|
GST_ADAPTIVE_DEMUX_SEGMENT_LOCK (demux);
|
||||||
pending_segment = stream->pending_segment;
|
pending_segment = stream->pending_segment;
|
||||||
|
@ -2098,6 +2242,8 @@ gst_adaptive_demux_stream_push_buffer (GstAdaptiveDemuxStream * stream,
|
||||||
pending_events = g_list_delete_link (pending_events, pending_events);
|
pending_events = g_list_delete_link (pending_events, pending_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wait for preroll if blocking */
|
||||||
|
|
||||||
ret = gst_pad_push (stream->pad, buffer);
|
ret = gst_pad_push (stream->pad, buffer);
|
||||||
|
|
||||||
GST_MANIFEST_LOCK (demux);
|
GST_MANIFEST_LOCK (demux);
|
||||||
|
@ -3786,8 +3932,8 @@ gst_adaptive_demux_stream_advance_fragment_unlocked (GstAdaptiveDemux * demux,
|
||||||
if (can_expose) {
|
if (can_expose) {
|
||||||
GST_DEBUG_OBJECT (demux, "Subclass wants new pads "
|
GST_DEBUG_OBJECT (demux, "Subclass wants new pads "
|
||||||
"to do bitrate switching");
|
"to do bitrate switching");
|
||||||
gst_adaptive_demux_expose_streams (demux, FALSE);
|
gst_adaptive_demux_prepare_streams (demux, FALSE);
|
||||||
gst_adaptive_demux_start_tasks (demux);
|
gst_adaptive_demux_start_tasks (demux, TRUE);
|
||||||
} else {
|
} else {
|
||||||
GST_LOG_OBJECT (demux, "Not switching yet - ongoing downloads");
|
GST_LOG_OBJECT (demux, "Not switching yet - ongoing downloads");
|
||||||
}
|
}
|
||||||
|
@ -3946,8 +4092,8 @@ gst_adaptive_demux_advance_period (GstAdaptiveDemux * demux)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Advancing to next period");
|
GST_DEBUG_OBJECT (demux, "Advancing to next period");
|
||||||
klass->advance_period (demux);
|
klass->advance_period (demux);
|
||||||
gst_adaptive_demux_expose_streams (demux, FALSE);
|
gst_adaptive_demux_prepare_streams (demux, FALSE);
|
||||||
gst_adaptive_demux_start_tasks (demux);
|
gst_adaptive_demux_start_tasks (demux, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -185,6 +185,8 @@ struct _GstAdaptiveDemuxStream
|
||||||
|
|
||||||
/* TODO check if used */
|
/* TODO check if used */
|
||||||
gboolean eos;
|
gboolean eos;
|
||||||
|
|
||||||
|
gboolean do_block; /* TRUE if stream should block on preroll */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,6 +209,7 @@ struct _GstAdaptiveDemux
|
||||||
GstUriDownloader *downloader;
|
GstUriDownloader *downloader;
|
||||||
|
|
||||||
GList *streams;
|
GList *streams;
|
||||||
|
GList *prepared_streams;
|
||||||
GList *next_streams;
|
GList *next_streams;
|
||||||
|
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
|
|
Loading…
Reference in a new issue