diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2012-11-13 13:38:59 +0100 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2012-11-13 13:38:59 +0100 |
commit | 0d06cc420c4b9d2b85a1d56642d45f8a2d3fecd0 (patch) | |
tree | 5ba936d63dd294836c3520d2ab2e4c8341c33188 | |
parent | 7d6e4606fa1c4204c6e87a5f1ae0ef88aa4d565d (diff) |
media: attempt to prepare asyncasync-prepare
Is going to be very complicated from the client point of view. Control needs to
be passed back to the mainloop handling the client connection. When async
completes, we need to restore all state of the client and send the result.
-rw-r--r-- | gst/rtsp-server/rtsp-media.c | 103 | ||||
-rw-r--r-- | gst/rtsp-server/rtsp-media.h | 10 |
2 files changed, 91 insertions, 22 deletions
diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 1797dac..00f665a 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -972,17 +972,29 @@ weird_type: } static void -gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status) +gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status, + GError * error) { - g_mutex_lock (&media->lock); /* never overwrite the error status */ if (media->status != GST_RTSP_MEDIA_STATUS_ERROR) media->status = status; GST_DEBUG ("setting new status to %d", status); - g_cond_broadcast (&media->cond); - g_mutex_unlock (&media->lock); + + while (media->asyncs) { + GSimpleAsyncResult *async = media->asyncs->data; + + g_simple_async_result_set_op_res_gboolean (async, error ? FALSE : TRUE); + if (error) + g_simple_async_result_set_from_error (async, error); + + g_simple_async_result_complete_in_idle (async); + g_object_unref (async); + + media->asyncs = g_list_delete_link (media->asyncs, media->asyncs); + } } +#if 0 static GstRTSPMediaStatus gst_rtsp_media_get_status (GstRTSPMedia * media) { @@ -1006,6 +1018,7 @@ gst_rtsp_media_get_status (GstRTSPMedia * media) return result; } +#endif /* called with state-lock */ static gboolean @@ -1065,10 +1078,9 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message) gst_message_parse_error (message, &gerror, &debug); GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug); - g_error_free (gerror); g_free (debug); - gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR, gerror); break; } case GST_MESSAGE_WARNING: @@ -1094,7 +1106,7 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message) GST_INFO ("%p: got ASYNC_DONE", media); collect_media_stats (media); - gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED); + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED, NULL); } else { GST_INFO ("%p: ignoring ASYNC_DONE", media); } @@ -1181,7 +1193,7 @@ no_more_pads_cb (GstElement * element, GstRTSPMedia * media) } /** - * gst_rtsp_media_prepare: + * gst_rtsp_media_prepare_async: * @media: a #GstRTSPMedia * * Prepare @media for streaming. This function will create the pipeline and @@ -1189,18 +1201,23 @@ no_more_pads_cb (GstElement * element, GstRTSPMedia * media) * * It will preroll the pipeline and collect vital information about the streams * such as the duration. - * - * Returns: %TRUE on success. */ -gboolean -gst_rtsp_media_prepare (GstRTSPMedia * media) +void +gst_rtsp_media_prepare_async (GstRTSPMedia * media, GCancellable * cancellable, + GAsyncReadyCallback callback, gpointer user_data) { GstStateChangeReturn ret; - GstRTSPMediaStatus status; guint i; GstRTSPMediaClass *klass; GstBus *bus; GList *walk; + GSimpleAsyncResult *simple; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + simple = g_simple_async_result_new (G_OBJECT (media), + callback, user_data, gst_rtsp_media_prepare_async); + g_simple_async_result_set_check_cancellable (simple, cancellable); g_rec_mutex_lock (&media->state_lock); if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED) @@ -1296,8 +1313,10 @@ gst_rtsp_media_prepare (GstRTSPMedia * media) goto state_failed; } wait_status: + media->asyncs = g_list_prepend (media->asyncs, simple); g_rec_mutex_unlock (&media->state_lock); +#if 0 /* now wait for all pads to be prerolled, FIXME, we should somehow be * able to do this async so that we don't block the server thread. */ status = gst_rtsp_media_get_status (media); @@ -1307,45 +1326,87 @@ wait_status: g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARED], 0, NULL); GST_INFO ("object %p is prerolled", media); +#endif - return TRUE; + return; /* OK */ was_prepared: { - GST_LOG ("media %p was prepared", media); + GST_LOG ("media %p was already prepared", media); g_rec_mutex_unlock (&media->state_lock); - return TRUE; + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; } /* ERRORS */ not_unprepared: { GST_WARNING ("media %p was not unprepared", media); g_rec_mutex_unlock (&media->state_lock); - return FALSE; + g_simple_async_result_set_error (simple, GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_SETTINGS, "media must be unprepared"); + g_object_unref (simple); + return; } is_reused: { - g_rec_mutex_unlock (&media->state_lock); GST_WARNING ("can not reuse media %p", media); - return FALSE; + g_rec_mutex_unlock (&media->state_lock); + g_simple_async_result_set_error (simple, GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_SETTINGS, "can't reuse media"); + g_object_unref (simple); + return; } no_rtpbin: { g_rec_mutex_unlock (&media->state_lock); GST_WARNING ("no rtpbin element"); g_warning ("failed to create element 'rtpbin', check your installation"); - return FALSE; + g_simple_async_result_set_error (simple, GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_SETTINGS, "can't create 'rtpbin' element"); + g_object_unref (simple); + return; } state_failed: { GST_WARNING ("failed to preroll pipeline"); gst_rtsp_media_unprepare (media); g_rec_mutex_unlock (&media->state_lock); - return FALSE; + g_simple_async_result_set_error (simple, GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_SETTINGS, "failed to preroll pipeline"); + g_object_unref (simple); + return; } } +/** + * gst_rtsp_media_prepare_finish: + * @media: a #GstRTSPMedia + * @res: A #GAsyncResult obtained from the GAsyncReadyCallback passed to + * gst_rtsp_media_prepare_async(). + * error: (allow none): Return location for error or NULL. + * + * Returns: %FALSE if @error is set, otherwise %TRUE. + */ +gboolean +gst_rtsp_media_prepare_finish (GstRTSPMedia * media, + GAsyncResult * res, GError ** error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (media), + gst_rtsp_media_prepare_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (res); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return g_simple_async_result_get_op_res_gboolean (simple); +} + /* must be called with state-lock */ static void finish_unprepare (GstRTSPMedia * media) diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index bf2d0e5..8cd4de9 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -117,6 +117,7 @@ struct _GstRTSPMedia { GstElement *element; GRecMutex state_lock; + GList *asyncs; GPtrArray *streams; GList *dynamic; GstRTSPMediaStatus status; @@ -202,7 +203,14 @@ guint gst_rtsp_media_get_mtu (GstRTSPMedia *media); /* prepare the media for playback */ -gboolean gst_rtsp_media_prepare (GstRTSPMedia *media); +void gst_rtsp_media_prepare_async (GstRTSPMedia * media, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean gst_rtsp_media_prepare_finish (GstRTSPMedia * media, + GAsyncResult *res, + GError **error); + gboolean gst_rtsp_media_unprepare (GstRTSPMedia *media); /* creating streams */ |