summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-04-03 22:22:30 +0200
committerWim Taymans <wim@metal.(none)>2009-04-03 22:22:30 +0200
commit5dab222089fc7321b7ca074ee969c0bdcb7fe150 (patch)
tree3f7f9480c3f6edf16e0b3c2c96c8419b86ae64aa
parent660006b04f97b8de1e7208dadfda824b766c955a (diff)
media: more work on making the media shared
Add a reusable flag to medias, indicating that they can be reused after a state change to NULL. Small cleanups.
-rw-r--r--gst/rtsp-server/rtsp-media.c119
-rw-r--r--gst/rtsp-server/rtsp-media.h8
2 files changed, 114 insertions, 13 deletions
diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c
index fef38d5..57cf15b 100644
--- a/gst/rtsp-server/rtsp-media.c
+++ b/gst/rtsp-server/rtsp-media.c
@@ -20,11 +20,13 @@
#include "rtsp-media.h"
#define DEFAULT_SHARED FALSE
+#define DEFAULT_REUSABLE FALSE
enum
{
PROP_0,
PROP_SHARED,
+ PROP_REUSABLE,
PROP_LAST
};
@@ -56,6 +58,11 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
g_param_spec_boolean ("shared", "Shared", "If this media pipeline can be shared",
DEFAULT_SHARED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_REUSABLE,
+ g_param_spec_boolean ("reusable", "Reusable",
+ "If this media pipeline can be reused after an unprepare",
+ DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
klass->context = g_main_context_new ();
klass->loop = g_main_loop_new (klass->context, TRUE);
@@ -129,6 +136,9 @@ gst_rtsp_media_get_property (GObject *object, guint propid,
case PROP_SHARED:
g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
break;
+ case PROP_REUSABLE:
+ g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
@@ -144,6 +154,9 @@ gst_rtsp_media_set_property (GObject *object, guint propid,
case PROP_SHARED:
gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
break;
+ case PROP_REUSABLE:
+ gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
@@ -263,6 +276,38 @@ gst_rtsp_media_is_shared (GstRTSPMedia *media)
}
/**
+ * gst_rtsp_media_set_reusable:
+ * @media: a #GstRTSPMedia
+ * @reusable: the new value
+ *
+ * Set or unset if the pipeline for @media can be reused after the pipeline has
+ * been unprepared.
+ */
+void
+gst_rtsp_media_set_reusable (GstRTSPMedia *media, gboolean reusable)
+{
+ g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+
+ media->reusable = reusable;
+}
+
+/**
+ * gst_rtsp_media_is_reusable:
+ * @media: a #GstRTSPMedia
+ *
+ * Check if the pipeline for @media can be reused after an unprepare.
+ *
+ * Returns: %TRUE if the media can be reused
+ */
+gboolean
+gst_rtsp_media_is_reusable (GstRTSPMedia *media)
+{
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+
+ return media->reusable;
+}
+
+/**
* gst_rtsp_media_n_streams:
* @media: a #GstRTSPMedia
*
@@ -971,6 +1016,9 @@ gst_rtsp_media_prepare (GstRTSPMedia *media)
if (media->prepared)
goto was_prepared;
+ if (!media->reusable && media->reused)
+ goto is_reused;
+
g_message ("preparing media %p", media);
media->pipeline = gst_pipeline_new ("media-pipeline");
@@ -1055,6 +1103,37 @@ state_failed:
gst_element_set_state (media->pipeline, GST_STATE_NULL);
return FALSE;
}
+is_reused:
+ {
+ g_warning ("can not reused media %p", media);
+ return FALSE;
+ }
+}
+
+/**
+ * gst_rtsp_media_unprepare:
+ * @obj: a #GstRTSPMedia
+ *
+ * Unprepare @media. After this call, the media should be prepared again before
+ * it can be used again. If the media is set to be non-reusable, a new instance
+ * must be created.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+gst_rtsp_media_unprepare (GstRTSPMedia *media)
+{
+ if (!media->prepared)
+ return TRUE;
+
+ if (media->reusable) {
+ g_message ("unprepare media %p", media);
+ media->target_state = GST_STATE_NULL;
+ gst_element_set_state (media->pipeline, GST_STATE_NULL);
+ media->prepared = FALSE;
+ media->reused = TRUE;
+ }
+ return TRUE;
}
/**
@@ -1073,10 +1152,10 @@ gst_rtsp_media_set_state (GstRTSPMedia *media, GstState state, GArray *transport
gint i;
GstStateChangeReturn ret;
gboolean add, remove, do_state;
+ gint old_active;
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
g_return_val_if_fail (transports != NULL, FALSE);
- g_return_val_if_fail (media->prepared, FALSE);
/* NULL and READY are the same */
if (state == GST_STATE_READY)
@@ -1090,7 +1169,7 @@ gst_rtsp_media_set_state (GstRTSPMedia *media, GstState state, GArray *transport
unlock_streams (media);
break;
case GST_STATE_PAUSED:
- /* we're going from PLAYING to READY or NULL, remove */
+ /* we're going from PLAYING to PAUSED, READY or NULL, remove */
if (media->target_state == GST_STATE_PLAYING)
remove = TRUE;
break;
@@ -1101,6 +1180,7 @@ gst_rtsp_media_set_state (GstRTSPMedia *media, GstState state, GArray *transport
default:
break;
}
+ old_active = media->active;
for (i = 0; i < transports->len; i++) {
GstRTSPMediaTrans *tr;
@@ -1121,18 +1201,27 @@ gst_rtsp_media_set_state (GstRTSPMedia *media, GstState state, GArray *transport
switch (trans->lower_transport) {
case GST_RTSP_LOWER_TRANS_UDP:
case GST_RTSP_LOWER_TRANS_UDP_MCAST:
+ {
+ gchar *dest;
+ gint min, max;
+
+ dest = trans->destination;
+ min = trans->client_port.min;
+ max = trans->client_port.max;
+
if (add) {
- g_message ("adding %s:%d-%d", trans->destination, trans->client_port.min, trans->client_port.max);
- g_signal_emit_by_name (stream->udpsink[0], "add", trans->destination, trans->client_port.min, NULL);
- g_signal_emit_by_name (stream->udpsink[1], "add", trans->destination, trans->client_port.max, NULL);
+ g_message ("adding %s:%d-%d", dest, min, max);
+ g_signal_emit_by_name (stream->udpsink[0], "add", dest, min, NULL);
+ g_signal_emit_by_name (stream->udpsink[1], "add", dest, max, NULL);
media->active++;
} else if (remove) {
- g_message ("removing %s:%d-%d", trans->destination, trans->client_port.min, trans->client_port.max);
- g_signal_emit_by_name (stream->udpsink[0], "remove", trans->destination, trans->client_port.min, NULL);
- g_signal_emit_by_name (stream->udpsink[1], "remove", trans->destination, trans->client_port.max, NULL);
+ g_message ("removing %s:%d-%d", dest, min, max);
+ g_signal_emit_by_name (stream->udpsink[0], "remove", dest, min, NULL);
+ g_signal_emit_by_name (stream->udpsink[1], "remove", dest, max, NULL);
media->active--;
}
break;
+ }
case GST_RTSP_LOWER_TRANS_TCP:
if (add) {
stream->transports = g_list_prepend (stream->transports, tr);
@@ -1147,7 +1236,7 @@ gst_rtsp_media_set_state (GstRTSPMedia *media, GstState state, GArray *transport
}
/* we just added the first media, do the playing state change */
- if (media->active == 1 && add)
+ if (old_active == 0 && add)
do_state = TRUE;
/* if we have no more active media, do the downward state changes */
else if (media->active == 0)
@@ -1157,10 +1246,14 @@ gst_rtsp_media_set_state (GstRTSPMedia *media, GstState state, GArray *transport
g_message ("active %d media %p", media->active, media);
- if (do_state) {
- g_message ("state %s media %p", gst_element_state_get_name (state), media);
- media->target_state = state;
- ret = gst_element_set_state (media->pipeline, state);
+ if (do_state && media->target_state != state) {
+ if (state == GST_STATE_NULL) {
+ gst_rtsp_media_unprepare (media);
+ } else {
+ g_message ("state %s media %p", gst_element_state_get_name (state), media);
+ media->target_state = state;
+ ret = gst_element_set_state (media->pipeline, state);
+ }
}
/* remember where we are */
diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h
index 921c7b5..e4eafaa 100644
--- a/gst/rtsp-server/rtsp-media.h
+++ b/gst/rtsp-server/rtsp-media.h
@@ -123,6 +123,7 @@ struct _GstRTSPMediaStream {
/**
* 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
@@ -144,6 +145,8 @@ struct _GstRTSPMedia {
GObject parent;
gboolean shared;
+ gboolean reusable;
+ gboolean reused;
GstElement *element;
GArray *streams;
@@ -194,8 +197,13 @@ GstRTSPMedia * gst_rtsp_media_new (void);
void gst_rtsp_media_set_shared (GstRTSPMedia *media, gboolean shared);
gboolean gst_rtsp_media_is_shared (GstRTSPMedia *media);
+void gst_rtsp_media_set_reusable (GstRTSPMedia *media, gboolean reusable);
+gboolean gst_rtsp_media_is_reusable (GstRTSPMedia *media);
+
/* prepare the media for playback */
gboolean gst_rtsp_media_prepare (GstRTSPMedia *media);
+gboolean gst_rtsp_media_is_prepared (GstRTSPMedia *media);
+gboolean gst_rtsp_media_unprepare (GstRTSPMedia *media);
/* dealing with the media */
guint gst_rtsp_media_n_streams (GstRTSPMedia *media);