gulong no_more_pads_handler;
};
+static gboolean
+start_prepare (GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv = media->priv;
+ GstStateChangeReturn ret;
+ guint i;
+ GList *walk;
+
+ /* link streams we already have, other streams might appear when we have
+ * dynamic elements */
+ for (i = 0; i < priv->streams->len; i++) {
+ GstRTSPStream *stream;
+
+ stream = g_ptr_array_index (priv->streams, i);
+
+ gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
+ priv->rtpbin, GST_STATE_NULL);
+ }
+
+ for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
+ GstElement *elem = walk->data;
+ DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
+
+ GST_INFO ("adding callbacks for dynamic element %p", elem);
+
+ handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
+ (GCallback) pad_added_cb, media);
+ handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
+ (GCallback) pad_removed_cb, media);
+ handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
+ (GCallback) no_more_pads_cb, media);
+
+ g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
+
+ /* we add a fakesink here in order to make the state change async. We remove
+ * the fakesink again in the no-more-pads callback. */
+ priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
+ gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
+ }
+
+ GST_INFO ("setting pipeline to PAUSED for media %p", media);
+ /* first go to PAUSED */
+ ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+ priv->target_state = GST_STATE_PAUSED;
+
+ switch (ret) {
+ case GST_STATE_CHANGE_SUCCESS:
+ GST_INFO ("SUCCESS state change for media %p", media);
+ priv->seekable = TRUE;
+ break;
+ case GST_STATE_CHANGE_ASYNC:
+ GST_INFO ("ASYNC state change for media %p", media);
+ priv->seekable = TRUE;
+ break;
+ case GST_STATE_CHANGE_NO_PREROLL:
+ /* we need to go to PLAYING */
+ GST_INFO ("NO_PREROLL state change: live media %p", media);
+ /* FIXME we disable seeking for live streams for now. We should perform a
+ * seeking query in preroll instead */
+ priv->seekable = FALSE;
+ priv->is_live = TRUE;
+ ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ goto state_failed;
+ break;
+ case GST_STATE_CHANGE_FAILURE:
+ goto state_failed;
+ }
+
+ return FALSE;
+
+state_failed:
+ {
+ GST_WARNING ("failed to preroll pipeline");
+ gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
+ return FALSE;
+ }
+}
+
/**
* gst_rtsp_media_prepare:
* @media: a #GstRTSPMedia
gst_rtsp_media_prepare (GstRTSPMedia * media, GMainContext * context)
{
GstRTSPMediaPrivate *priv;
- GstStateChangeReturn ret;
GstRTSPMediaStatus status;
- guint i;
GstRTSPMediaClass *klass;
GstBus *bus;
- GList *walk;
+ GSource *source;
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
/* we're preparing now */
priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
+ klass = GST_RTSP_MEDIA_GET_CLASS (media);
+
+ if (context == NULL)
+ context = klass->context;
+
bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
/* add the pipeline bus to our custom mainloop */
g_source_set_callback (priv->source, (GSourceFunc) bus_message,
g_object_ref (media), (GDestroyNotify) watch_destroyed);
- klass = GST_RTSP_MEDIA_GET_CLASS (media);
- priv->id = g_source_attach (priv->source, context ? context : klass->context);
+ priv->id = g_source_attach (priv->source, context);
/* add stuff to the bin */
gst_bin_add (GST_BIN (priv->pipeline), priv->rtpbin);
- /* link streams we already have, other streams might appear when we have
- * dynamic elements */
- for (i = 0; i < priv->streams->len; i++) {
- GstRTSPStream *stream;
-
- stream = g_ptr_array_index (priv->streams, i);
-
- gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
- priv->rtpbin, GST_STATE_NULL);
- }
-
- for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
- GstElement *elem = walk->data;
- DynPaySignalHandlers *handlers = g_slice_new (DynPaySignalHandlers);
-
- GST_INFO ("adding callbacks for dynamic element %p", elem);
-
- handlers->pad_added_handler = g_signal_connect (elem, "pad-added",
- (GCallback) pad_added_cb, media);
- handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed",
- (GCallback) pad_removed_cb, media);
- handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads",
- (GCallback) no_more_pads_cb, media);
-
- g_object_set_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers", handlers);
-
- /* we add a fakesink here in order to make the state change async. We remove
- * the fakesink again in the no-more-pads callback. */
- priv->fakesink = gst_element_factory_make ("fakesink", "fakesink");
- gst_bin_add (GST_BIN (priv->pipeline), priv->fakesink);
- }
-
- GST_INFO ("setting pipeline to PAUSED for media %p", media);
- /* first go to PAUSED */
- ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
- priv->target_state = GST_STATE_PAUSED;
+ /* do remainder in context */
+ source = g_idle_source_new ();
+ g_source_set_callback (source, (GSourceFunc) start_prepare, media, NULL);
+ g_source_attach (source, context);
+ g_source_unref (source);
- switch (ret) {
- case GST_STATE_CHANGE_SUCCESS:
- GST_INFO ("SUCCESS state change for media %p", media);
- priv->seekable = TRUE;
- break;
- case GST_STATE_CHANGE_ASYNC:
- GST_INFO ("ASYNC state change for media %p", media);
- priv->seekable = TRUE;
- break;
- case GST_STATE_CHANGE_NO_PREROLL:
- /* we need to go to PLAYING */
- GST_INFO ("NO_PREROLL state change: live media %p", media);
- /* FIXME we disable seeking for live streams for now. We should perform a
- * seeking query in preroll instead */
- priv->seekable = FALSE;
- priv->is_live = TRUE;
- ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
- if (ret == GST_STATE_CHANGE_FAILURE)
- goto state_failed;
- break;
- case GST_STATE_CHANGE_FAILURE:
- goto state_failed;
- }
wait_status:
g_rec_mutex_unlock (&priv->state_lock);
{
GST_WARNING ("failed to preroll pipeline");
gst_rtsp_media_unprepare (media);
- g_rec_mutex_unlock (&priv->state_lock);
return FALSE;
}
}