gst_rtsp_media_init (GstRTSPMedia * media)
{
media->streams = g_array_new (FALSE, TRUE, sizeof (GstRTSPMediaStream *));
+ media->lock = g_mutex_new ();
+ media->cond = g_cond_new ();
}
static void
g_source_destroy (media->source);
g_source_unref (media->source);
}
+ g_mutex_free (media->lock);
+ g_cond_free (media->cond);
G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
}
GST_INFO ("done seeking %d", res);
gst_element_get_state (media->pipeline, NULL, NULL, -1);
GST_INFO ("prerolled again");
-
- collect_media_stats (media);
} else {
GST_INFO ("no seek needed");
res = TRUE;
}
}
+static void
+gst_rtsp_media_set_status (GstRTSPMedia *media, GstRTSPMediaStatus status)
+{
+ 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);
+}
+
+static GstRTSPMediaStatus
+gst_rtsp_media_get_status (GstRTSPMedia *media)
+{
+ GstRTSPMediaStatus result;
+
+ g_mutex_lock (media->lock);
+ /* while we are preparing, wait */
+ while (media->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
+ GST_DEBUG ("waiting for status change");
+ g_cond_wait (media->cond, media->lock);
+ }
+ /* could be success or error */
+ result = media->status;
+ GST_DEBUG ("got status %d", result);
+ g_mutex_unlock (media->lock);
+
+ return result;
+}
+
static gboolean
default_handle_message (GstRTSPMedia * media, GstMessage * message)
{
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);
break;
}
case GST_MESSAGE_WARNING:
break;
case GST_MESSAGE_STREAM_STATUS:
break;
+ case GST_MESSAGE_ASYNC_DONE:
+ GST_INFO ("%p: got ASYNC_DONE", media);
+ collect_media_stats (media);
+
+ gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
+ break;
default:
GST_INFO ("%p: got message type %s", media,
gst_message_type_get_name (type));
gst_rtsp_media_prepare (GstRTSPMedia * media)
{
GstStateChangeReturn ret;
+ GstRTSPMediaStatus status;
guint i, n_streams;
GstRTSPMediaClass *klass;
GstBus *bus;
GList *walk;
- if (media->prepared)
+ if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED)
goto was_prepared;
if (!media->reusable && media->reused)
/* reset some variables */
media->is_live = FALSE;
media->buffering = FALSE;
+ /* we're preparing now */
+ media->status = GST_RTSP_MEDIA_STATUS_PREPARING;
bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (media->pipeline));
}
/* now wait for all pads to be prerolled */
- ret = gst_element_get_state (media->pipeline, NULL, NULL, -1);
- if (ret == GST_STATE_CHANGE_FAILURE)
+ status = gst_rtsp_media_get_status (media);
+ if (status == GST_RTSP_MEDIA_STATUS_ERROR)
goto state_failed;
- /* collect stats about the media */
- collect_media_stats (media);
-
GST_INFO ("object %p is prerolled", media);
- media->prepared = TRUE;
-
return TRUE;
/* OK */
GstRTSPMediaClass *klass;
gboolean success;
- if (!media->prepared)
+ if (media->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
return TRUE;
GST_INFO ("unprepare media %p", media);
else
success = TRUE;
- media->prepared = FALSE;
+ media->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
media->reused = TRUE;
/* when the media is not reusable, this will effectively unref the media and
};
/**
+ * GstRTSPMediaStatus:
+ * @GST_RTSP_MEDIA_STATUS_UNPREPARED: media pipeline not prerolled
+ * @GST_RTSP_MEDIA_STATUS_PREPARING: media pipeline is prerolling
+ * @GST_RTSP_MEDIA_STATUS_PREPARED: media pipeline is prerolled
+ * @GST_RTSP_MEDIA_STATUS_ERROR: media pipeline is in error
+ *
+ * The state of the media pipeline.
+ */
+typedef enum {
+ GST_RTSP_MEDIA_STATUS_UNPREPARED = 0,
+ GST_RTSP_MEDIA_STATUS_PREPARING = 1,
+ GST_RTSP_MEDIA_STATUS_PREPARED = 2,
+ GST_RTSP_MEDIA_STATUS_ERROR = 3
+} GstRTSPMediaStatus;
+
+/**
* GstRTSPMedia:
* @shared: if this media can be shared between clients
* @reusable: if this media can be reused after an unprepare
* @element: the data providing element
* @streams: the different streams provided by @element
- * @prepared: if the media is prepared for streaming
+ * @status: the status of the media pipeline
* @pipeline: the toplevel pipeline
* @source: the bus watch for pipeline messages.
* @id: the id of the watch
* This object is usually created from a #GstRTSPMediaFactory.
*/
struct _GstRTSPMedia {
- GObject parent;
+ GObject parent;
- gboolean shared;
- gboolean reusable;
- gboolean reused;
+ GMutex *lock;
+ GCond *cond;
- GstElement *element;
- GArray *streams;
- GList *dynamic;
- gboolean prepared;
- gint active;
+ gboolean shared;
+ gboolean reusable;
+ gboolean reused;
+
+ GstElement *element;
+ GArray *streams;
+ GList *dynamic;
+ GstRTSPMediaStatus status;
+ gint active;
/* the pipeline for the media */
- GstElement *pipeline;
- GstElement *fakesink;
- GSource *source;
- guint id;
+ GstElement *pipeline;
+ GstElement *fakesink;
+ GSource *source;
+ guint id;
- gboolean is_live;
- gboolean buffering;
- GstState target_state;
+ gboolean is_live;
+ gboolean buffering;
+ GstState target_state;
/* RTP session manager */
- GstElement *rtpbin;
+ GstElement *rtpbin;
/* the range of media */
- GstRTSPTimeRange range;
+ GstRTSPTimeRange range;
};
/**