rtsp: make object details private
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 29 Nov 2012 10:11:05 +0000 (11:11 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 29 Nov 2012 10:11:05 +0000 (11:11 +0100)
Make all object details private
Add methods to access private bits

28 files changed:
docs/libs/gst-rtsp-server-sections.txt
examples/test-auth.c
gst/rtsp-server/rtsp-auth.c
gst/rtsp-server/rtsp-auth.h
gst/rtsp-server/rtsp-client.c
gst/rtsp-server/rtsp-client.h
gst/rtsp-server/rtsp-media-factory-uri.c
gst/rtsp-server/rtsp-media-factory-uri.h
gst/rtsp-server/rtsp-media-factory.c
gst/rtsp-server/rtsp-media-factory.h
gst/rtsp-server/rtsp-media.c
gst/rtsp-server/rtsp-media.h
gst/rtsp-server/rtsp-mount-points.c
gst/rtsp-server/rtsp-mount-points.h
gst/rtsp-server/rtsp-sdp.c
gst/rtsp-server/rtsp-server.c
gst/rtsp-server/rtsp-server.h
gst/rtsp-server/rtsp-session-media.c
gst/rtsp-server/rtsp-session-media.h
gst/rtsp-server/rtsp-session-pool.c
gst/rtsp-server/rtsp-session-pool.h
gst/rtsp-server/rtsp-session.c
gst/rtsp-server/rtsp-session.h
gst/rtsp-server/rtsp-stream-transport.c
gst/rtsp-server/rtsp-stream-transport.h
gst/rtsp-server/rtsp-stream.c
gst/rtsp-server/rtsp-stream.h
tests/check/gst/media.c

index a94dea9..0122798 100644 (file)
@@ -313,6 +313,7 @@ gst_rtsp_stream_set_mtu
 gst_rtsp_stream_join_bin
 gst_rtsp_stream_leave_bin
 gst_rtsp_stream_get_rtpinfo
+gst_rtsp_stream_get_caps
 gst_rtsp_stream_recv_rtcp
 gst_rtsp_stream_recv_rtp
 gst_rtsp_stream_add_transport
index a505743..a810b4d 100644 (file)
@@ -35,8 +35,8 @@ remove_sessions (GstRTSPServer * server)
 
   g_print ("removing all sessions\n");
   pool = gst_rtsp_server_get_session_pool (server);
-  gst_rtsp_session_pool_filter (pool, (GstRTSPSessionFilterFunc) remove_func,
-      server);
+  gst_rtsp_session_pool_filter (pool,
+      (GstRTSPSessionPoolFilterFunc) remove_func, server);
   g_object_unref (pool);
 
   return FALSE;
index 398bc28..5a156fb 100644 (file)
 
 #include "rtsp-auth.h"
 
+#define GST_RTSP_AUTH_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuthPrivate))
+
+struct _GstRTSPAuthPrivate
+{
+  GMutex lock;
+  gchar *basic;
+  GstRTSPMethod methods;
+};
+
 enum
 {
   PROP_0,
@@ -48,6 +58,8 @@ gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPAuthPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->get_property = gst_rtsp_auth_get_property;
@@ -63,9 +75,11 @@ gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
 static void
 gst_rtsp_auth_init (GstRTSPAuth * auth)
 {
-  g_mutex_init (&auth->lock);
+  auth->priv = GST_RTSP_AUTH_GET_PRIVATE (auth);
+
+  g_mutex_init (&auth->priv->lock);
   /* bitwise or of all methods that need authentication */
-  auth->methods = GST_RTSP_DESCRIBE |
+  auth->priv->methods = GST_RTSP_DESCRIBE |
       GST_RTSP_ANNOUNCE |
       GST_RTSP_GET_PARAMETER |
       GST_RTSP_SET_PARAMETER |
@@ -77,10 +91,11 @@ static void
 gst_rtsp_auth_finalize (GObject * obj)
 {
   GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
+  GstRTSPAuthPrivate *priv = auth->priv;
 
   GST_INFO ("finalize auth %p", auth);
-  g_free (auth->basic);
-  g_mutex_clear (&auth->lock);
+  g_free (priv->basic);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
 }
@@ -132,12 +147,16 @@ gst_rtsp_auth_new (void)
 void
 gst_rtsp_auth_set_basic (GstRTSPAuth * auth, const gchar * basic)
 {
+  GstRTSPAuthPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
 
-  g_mutex_lock (&auth->lock);
-  g_free (auth->basic);
-  auth->basic = g_strdup (basic);
-  g_mutex_unlock (&auth->lock);
+  priv = auth->priv;
+
+  g_mutex_lock (&priv->lock);
+  g_free (priv->basic);
+  priv->basic = g_strdup (basic);
+  g_mutex_unlock (&priv->lock);
 }
 
 static gboolean
@@ -190,10 +209,11 @@ static gboolean
 default_check_method (GstRTSPAuth * auth, GstRTSPClient * client,
     GQuark hint, GstRTSPClientState * state)
 {
+  GstRTSPAuthPrivate *priv = auth->priv;
   gboolean result = TRUE;
   GstRTSPResult res;
 
-  if ((state->method & auth->methods) != 0) {
+  if ((state->method & priv->methods) != 0) {
     gchar *authorization;
 
     result = FALSE;
@@ -207,10 +227,10 @@ default_check_method (GstRTSPAuth * auth, GstRTSPClient * client,
     /* parse type */
     if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) {
       GST_DEBUG_OBJECT (auth, "check Basic auth");
-      g_mutex_lock (&auth->lock);
-      if (auth->basic && strcmp (&authorization[6], auth->basic) == 0)
+      g_mutex_lock (&priv->lock);
+      if (priv->basic && strcmp (&authorization[6], priv->basic) == 0)
         result = TRUE;
-      g_mutex_unlock (&auth->lock);
+      g_mutex_unlock (&priv->lock);
     } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) {
       GST_DEBUG_OBJECT (auth, "check Digest auth");
       /* not implemented yet */
index a71388c..6fd1a2f 100644 (file)
@@ -24,6 +24,7 @@
 
 typedef struct _GstRTSPAuth GstRTSPAuth;
 typedef struct _GstRTSPAuthClass GstRTSPAuthClass;
+typedef struct _GstRTSPAuthPrivate GstRTSPAuthPrivate;
 
 #include "rtsp-client.h"
 
@@ -46,10 +47,7 @@ G_BEGIN_DECLS
 struct _GstRTSPAuth {
   GObject       parent;
 
-  /*< private >*/
-  GMutex        lock;
-  gchar        *basic;
-  GstRTSPMethod methods;
+  GstRTSPAuthPrivate *priv;
 };
 
 struct _GstRTSPAuthClass {
index 15d3696..e8f3957 100644 (file)
 #include "rtsp-sdp.h"
 #include "rtsp-params.h"
 
+#define GST_RTSP_CLIENT_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_CLIENT, GstRTSPClientPrivate))
+
+struct _GstRTSPClientPrivate
+{
+  GMutex lock;
+  GstRTSPConnection *connection;
+  GstRTSPWatch *watch;
+  guint close_seq;
+  gchar *server_ip;
+  gboolean is_ipv6;
+  gboolean use_client_settings;
+
+  GstRTSPClientSendFunc send_func;
+  gpointer send_data;
+  GDestroyNotify send_notify;
+
+  GstRTSPSessionPool *session_pool;
+  GstRTSPMountPoints *mount_points;
+  GstRTSPAuth *auth;
+
+  GstRTSPUrl *uri;
+  GstRTSPMedia *media;
+
+  GList *transports;
+  GList *sessions;
+};
+
 static GMutex tunnels_lock;
 static GHashTable *tunnels;
 
@@ -79,6 +107,8 @@ gst_rtsp_client_class_init (GstRTSPClientClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPClientPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->get_property = gst_rtsp_client_get_property;
@@ -173,39 +203,50 @@ gst_rtsp_client_class_init (GstRTSPClientClass * klass)
 static void
 gst_rtsp_client_init (GstRTSPClient * client)
 {
-  g_mutex_init (&client->lock);
-  client->use_client_settings = DEFAULT_USE_CLIENT_SETTINGS;
-  client->close_seq = 0;
+  GstRTSPClientPrivate *priv = GST_RTSP_CLIENT_GET_PRIVATE (client);
+
+  client->priv = priv;
+
+  g_mutex_init (&priv->lock);
+  priv->use_client_settings = DEFAULT_USE_CLIENT_SETTINGS;
+  priv->close_seq = 0;
+}
+
+static GstRTSPFilterResult
+filter_session (GstRTSPSession * sess, GstRTSPSessionMedia * media,
+    gpointer user_data)
+{
+  GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+
+  gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
+  unlink_session_transports (client, sess, media);
+
+  /* unmanage the media in the session */
+  return GST_RTSP_FILTER_REMOVE;
 }
 
 static void
 client_unlink_session (GstRTSPClient * client, GstRTSPSession * session)
 {
   /* unlink all media managed in this session */
-  while (session->medias) {
-    GstRTSPSessionMedia *media = session->medias->data;
-
-    gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
-    unlink_session_transports (client, session, media);
-    /* unmanage the media in the session. this will modify session->medias */
-    gst_rtsp_session_release_media (session, media);
-  }
+  gst_rtsp_session_filter (session, filter_session, client);
 }
 
 static void
 client_cleanup_sessions (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GList *sessions;
 
   /* remove weak-ref from sessions */
-  for (sessions = client->sessions; sessions; sessions = g_list_next (sessions)) {
+  for (sessions = priv->sessions; sessions; sessions = g_list_next (sessions)) {
     GstRTSPSession *session = (GstRTSPSession *) sessions->data;
     g_object_weak_unref (G_OBJECT (session),
         (GWeakNotify) client_session_finalized, client);
     client_unlink_session (client, session);
   }
-  g_list_free (client->sessions);
-  client->sessions = NULL;
+  g_list_free (priv->sessions);
+  priv->sessions = NULL;
 }
 
 /* A client is finalized when the connection is broken */
@@ -213,35 +254,36 @@ static void
 gst_rtsp_client_finalize (GObject * obj)
 {
   GstRTSPClient *client = GST_RTSP_CLIENT (obj);
+  GstRTSPClientPrivate *priv = client->priv;
 
   GST_INFO ("finalize client %p", client);
 
-  if (client->watch)
-    g_source_destroy ((GSource *) client->watch);
+  if (priv->watch)
+    g_source_destroy ((GSource *) priv->watch);
 
-  if (client->send_notify)
-    client->send_notify (client->send_data);
+  if (priv->send_notify)
+    priv->send_notify (priv->send_data);
 
   client_cleanup_sessions (client);
 
-  if (client->connection)
-    gst_rtsp_connection_free (client->connection);
-  if (client->session_pool)
-    g_object_unref (client->session_pool);
-  if (client->mount_points)
-    g_object_unref (client->mount_points);
-  if (client->auth)
-    g_object_unref (client->auth);
+  if (priv->connection)
+    gst_rtsp_connection_free (priv->connection);
+  if (priv->session_pool)
+    g_object_unref (priv->session_pool);
+  if (priv->mount_points)
+    g_object_unref (priv->mount_points);
+  if (priv->auth)
+    g_object_unref (priv->auth);
 
-  if (client->uri)
-    gst_rtsp_url_free (client->uri);
-  if (client->media) {
-    gst_rtsp_media_unprepare (client->media);
-    g_object_unref (client->media);
+  if (priv->uri)
+    gst_rtsp_url_free (priv->uri);
+  if (priv->media) {
+    gst_rtsp_media_unprepare (priv->media);
+    g_object_unref (priv->media);
   }
 
-  g_free (client->server_ip);
-  g_mutex_clear (&client->lock);
+  g_free (priv->server_ip);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_client_parent_class)->finalize (obj);
 }
@@ -311,6 +353,8 @@ static void
 send_response (GstRTSPClient * client, GstRTSPSession * session,
     GstRTSPMessage * response, gboolean close)
 {
+  GstRTSPClientPrivate *priv = client->priv;
+
   gst_rtsp_message_add_header (response, GST_RTSP_HDR_SERVER,
       "GStreamer RTSP server");
 
@@ -330,8 +374,8 @@ send_response (GstRTSPClient * client, GstRTSPSession * session,
   if (close)
     gst_rtsp_message_add_header (response, GST_RTSP_HDR_CONNECTION, "close");
 
-  if (client->send_func)
-    client->send_func (client, response, close, client->send_data);
+  if (priv->send_func)
+    priv->send_func (client, response, close, priv->send_data);
 
   gst_rtsp_message_unset (response);
 }
@@ -380,28 +424,29 @@ compare_uri (const GstRTSPUrl * uri1, const GstRTSPUrl * uri2)
 static GstRTSPMedia *
 find_media (GstRTSPClient * client, GstRTSPClientState * state)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GstRTSPMediaFactory *factory;
   GstRTSPMedia *media;
   GstRTSPAuth *auth;
 
-  if (!compare_uri (client->uri, state->uri)) {
+  if (!compare_uri (priv->uri, state->uri)) {
     /* remove any previously cached values before we try to construct a new
      * media for uri */
-    if (client->uri)
-      gst_rtsp_url_free (client->uri);
-    client->uri = NULL;
-    if (client->media) {
-      gst_rtsp_media_unprepare (client->media);
-      g_object_unref (client->media);
+    if (priv->uri)
+      gst_rtsp_url_free (priv->uri);
+    priv->uri = NULL;
+    if (priv->media) {
+      gst_rtsp_media_unprepare (priv->media);
+      g_object_unref (priv->media);
     }
-    client->media = NULL;
+    priv->media = NULL;
 
-    if (!client->mount_points)
+    if (!priv->mount_points)
       goto no_mount_points;
 
     /* find the factory for the uri first */
     if (!(factory =
-            gst_rtsp_mount_points_find_factory (client->mount_points,
+            gst_rtsp_mount_points_find_factory (priv->mount_points,
                 state->uri)))
       goto no_factory;
 
@@ -423,19 +468,17 @@ find_media (GstRTSPClient * client, GstRTSPClientState * state)
     g_object_unref (factory);
     factory = NULL;
 
-    /* set ipv6 on the media before preparing */
-    media->is_ipv6 = client->is_ipv6;
     /* prepare the media */
     if (!(gst_rtsp_media_prepare (media)))
       goto no_prepare;
 
     /* now keep track of the uri and the media */
-    client->uri = gst_rtsp_url_copy (state->uri);
-    client->media = media;
+    priv->uri = gst_rtsp_url_copy (state->uri);
+    priv->media = media;
     state->media = media;
   } else {
     /* we have seen this uri before, used cached media */
-    media = client->media;
+    media = priv->media;
     state->media = media;
     GST_INFO ("reusing cached media %p", media);
   }
@@ -486,6 +529,7 @@ no_prepare:
 static gboolean
 do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GstRTSPMessage message = { 0 };
   GstMapInfo map_info;
   guint8 *data;
@@ -499,8 +543,8 @@ do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
 
   gst_rtsp_message_take_body (&message, map_info.data, map_info.size);
 
-  if (client->send_func)
-    client->send_func (client, &message, FALSE, client->send_data);
+  if (priv->send_func)
+    priv->send_func (client, &message, FALSE, priv->send_data);
 
   gst_rtsp_message_steal_body (&message, &data, &usize);
   gst_buffer_unmap (buffer, &map_info);
@@ -514,12 +558,15 @@ static void
 link_transport (GstRTSPClient * client, GstRTSPSession * session,
     GstRTSPStreamTransport * trans)
 {
+  GstRTSPClientPrivate *priv = client->priv;
+
   GST_DEBUG ("client %p: linking transport %p", client, trans);
+
   gst_rtsp_stream_transport_set_callbacks (trans,
       (GstRTSPSendFunc) do_send_data,
       (GstRTSPSendFunc) do_send_data, client, NULL);
 
-  client->transports = g_list_prepend (client->transports, trans);
+  priv->transports = g_list_prepend (priv->transports, trans);
 
   /* make sure our session can't expire */
   gst_rtsp_session_prevent_expire (session);
@@ -529,10 +576,13 @@ static void
 unlink_transport (GstRTSPClient * client, GstRTSPSession * session,
     GstRTSPStreamTransport * trans)
 {
+  GstRTSPClientPrivate *priv = client->priv;
+
   GST_DEBUG ("client %p: unlinking transport %p", client, trans);
+
   gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
 
-  client->transports = g_list_remove (client->transports, trans);
+  priv->transports = g_list_remove (priv->transports, trans);
 
   /* our session can now expire */
   gst_rtsp_session_allow_expire (session);
@@ -544,17 +594,18 @@ unlink_session_transports (GstRTSPClient * client, GstRTSPSession * session,
 {
   guint n_streams, i;
 
-  n_streams = gst_rtsp_media_n_streams (media->media);
+  n_streams =
+      gst_rtsp_media_n_streams (gst_rtsp_session_media_get_media (media));
   for (i = 0; i < n_streams; i++) {
     GstRTSPStreamTransport *trans;
-    GstRTSPTransport *tr;
+    const GstRTSPTransport *tr;
 
     /* get the transport, if there is no transport configured, skip this stream */
     trans = gst_rtsp_session_media_get_transport (media, i);
     if (trans == NULL)
       continue;
 
-    tr = trans->transport;
+    tr = gst_rtsp_stream_transport_get_transport (trans);
 
     if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
       /* for TCP, unlink the stream from the TCP connection of the client */
@@ -566,23 +617,25 @@ unlink_session_transports (GstRTSPClient * client, GstRTSPSession * session,
 static void
 close_connection (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   const gchar *tunnelid;
 
   GST_DEBUG ("client %p: closing connection", client);
 
-  if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
+  if ((tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection))) {
     g_mutex_lock (&tunnels_lock);
     /* remove from tunnelids */
     g_hash_table_remove (tunnels, tunnelid);
     g_mutex_unlock (&tunnels_lock);
   }
 
-  gst_rtsp_connection_close (client->connection);
+  gst_rtsp_connection_close (priv->connection);
 }
 
 static gboolean
 handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GstRTSPSession *session;
   GstRTSPSessionMedia *media;
   GstRTSPStatusCode code;
@@ -605,7 +658,7 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
   /* remove the session from the watched sessions */
   g_object_weak_unref (G_OBJECT (session),
       (GWeakNotify) client_session_finalized, client);
-  client->sessions = g_list_remove (client->sessions, session);
+  priv->sessions = g_list_remove (priv->sessions, session);
 
   gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
 
@@ -613,7 +666,7 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
    * are torn down. */
   if (!gst_rtsp_session_release_media (session, media)) {
     /* remove the session */
-    gst_rtsp_session_pool_remove (client->session_pool, session);
+    gst_rtsp_session_pool_remove (priv->session_pool, session);
   }
   /* construct the response now */
   code = GST_RTSP_STS_OK;
@@ -723,6 +776,7 @@ handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
   GstRTSPSession *session;
   GstRTSPSessionMedia *media;
   GstRTSPStatusCode code;
+  GstRTSPState rtspstate;
 
   if (!(session = state->session))
     goto no_session;
@@ -734,9 +788,10 @@ handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
 
   state->sessmedia = media;
 
+  rtspstate = gst_rtsp_session_media_get_rtsp_state (media);
   /* the session state must be playing or recording */
-  if (media->state != GST_RTSP_STATE_PLAYING &&
-      media->state != GST_RTSP_STATE_RECORDING)
+  if (rtspstate != GST_RTSP_STATE_PLAYING &&
+      rtspstate != GST_RTSP_STATE_RECORDING)
     goto invalid_state;
 
   /* unlink the all TCP callbacks */
@@ -753,7 +808,7 @@ handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
   send_response (client, session, state->response, FALSE);
 
   /* the state is now READY */
-  media->state = GST_RTSP_STATE_READY;
+  gst_rtsp_session_media_set_rtsp_state (media, GST_RTSP_STATE_READY);
 
   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PAUSE_REQUEST],
       0, state);
@@ -793,6 +848,7 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
   gchar *str;
   GstRTSPTimeRange *range;
   GstRTSPResult res;
+  GstRTSPState rtspstate;
 
   if (!(session = state->session))
     goto no_session;
@@ -805,8 +861,8 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
   state->sessmedia = media;
 
   /* the session state must be playing or ready */
-  if (media->state != GST_RTSP_STATE_PLAYING &&
-      media->state != GST_RTSP_STATE_READY)
+  rtspstate = gst_rtsp_session_media_get_rtsp_state (media);
+  if (rtspstate != GST_RTSP_STATE_PLAYING && rtspstate != GST_RTSP_STATE_READY)
     goto invalid_state;
 
   /* parse the range header if we have one */
@@ -815,7 +871,7 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
   if (res == GST_RTSP_OK) {
     if (gst_rtsp_range_parse (str, &range) == GST_RTSP_OK) {
       /* we have a range, seek to the position */
-      gst_rtsp_media_seek (media->media, range);
+      gst_rtsp_media_seek (gst_rtsp_session_media_get_media (media), range);
       gst_rtsp_range_free (range);
     }
   }
@@ -823,10 +879,12 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
   /* grab RTPInfo from the payloaders now */
   rtpinfo = g_string_new ("");
 
-  n_streams = gst_rtsp_media_n_streams (media->media);
+  n_streams =
+      gst_rtsp_media_n_streams (gst_rtsp_session_media_get_media (media));
   for (i = 0, infocount = 0; i < n_streams; i++) {
     GstRTSPStreamTransport *trans;
-    GstRTSPTransport *tr;
+    GstRTSPStream *stream;
+    const GstRTSPTransport *tr;
     gchar *uristr;
     guint rtptime, seq;
 
@@ -836,14 +894,15 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
       GST_INFO ("stream %d is not configured", i);
       continue;
     }
-    tr = trans->transport;
+    tr = gst_rtsp_stream_transport_get_transport (trans);
 
     if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
       /* for TCP, link the stream to the TCP connection of the client */
       link_transport (client, session, trans);
     }
 
-    if (gst_rtsp_stream_get_rtpinfo (trans->stream, &rtptime, &seq)) {
+    stream = gst_rtsp_stream_transport_get_stream (trans);
+    if (gst_rtsp_stream_get_rtpinfo (stream, &rtptime, &seq)) {
       if (infocount > 0)
         g_string_append (rtpinfo, ", ");
 
@@ -872,7 +931,9 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
   }
 
   /* add the range */
-  str = gst_rtsp_media_get_range_string (media->media, TRUE);
+  str =
+      gst_rtsp_media_get_range_string (gst_rtsp_session_media_get_media (media),
+      TRUE);
   gst_rtsp_message_take_header (state->response, GST_RTSP_HDR_RANGE, str);
 
   send_response (client, session, state->response, FALSE);
@@ -880,7 +941,7 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
   /* start playing after sending the request */
   gst_rtsp_session_media_set_state (media, GST_STATE_PLAYING);
 
-  media->state = GST_RTSP_STATE_PLAYING;
+  gst_rtsp_session_media_set_rtsp_state (media, GST_RTSP_STATE_PLAYING);
 
   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PLAY_REQUEST],
       0, state);
@@ -1001,9 +1062,11 @@ static gboolean
 configure_client_transport (GstRTSPClient * client, GstRTSPClientState * state,
     GstRTSPTransport * ct)
 {
+  GstRTSPClientPrivate *priv = client->priv;
+
   /* we have a valid transport now, set the destination of the client. */
   if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
-    if (ct->destination == NULL || !client->use_client_settings) {
+    if (ct->destination == NULL || !priv->use_client_settings) {
       GstRTSPAddress *addr;
 
       addr = gst_rtsp_stream_get_address (state->stream);
@@ -1019,7 +1082,7 @@ configure_client_transport (GstRTSPClient * client, GstRTSPClientState * state,
   } else {
     GstRTSPUrl *url;
 
-    url = gst_rtsp_connection_get_url (client->connection);
+    url = gst_rtsp_connection_get_url (priv->connection);
     g_free (ct->destination);
     ct->destination = g_strdup (url->host);
 
@@ -1057,7 +1120,7 @@ make_server_transport (GstRTSPClient * client, GstRTSPClientState * state,
   switch (st->lower_transport) {
     case GST_RTSP_LOWER_TRANS_UDP:
       st->client_port = ct->client_port;
-      st->server_port = state->stream->server_port;
+      gst_rtsp_stream_get_server_port (state->stream, &st->server_port);
       break;
     case GST_RTSP_LOWER_TRANS_UDP_MCAST:
       st->port = ct->port;
@@ -1070,8 +1133,7 @@ make_server_transport (GstRTSPClient * client, GstRTSPClientState * state,
       break;
   }
 
-  if (state->stream->session)
-    g_object_get (state->stream->session, "internal-ssrc", &st->ssrc, NULL);
+  gst_rtsp_stream_get_ssrc (state->stream, &st->ssrc);
 
   return st;
 }
@@ -1079,6 +1141,7 @@ make_server_transport (GstRTSPClient * client, GstRTSPClientState * state,
 static gboolean
 handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GstRTSPResult res;
   GstRTSPUrl *uri;
   gchar *transport;
@@ -1092,6 +1155,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
   GstRTSPSessionMedia *sessmedia;
   GstRTSPMedia *media;
   GstRTSPStream *stream;
+  GstRTSPState rtspstate;
 
   uri = state->uri;
 
@@ -1130,7 +1194,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
 
   /* we create the session after parsing stuff so that we don't make
    * a session for malformed requests */
-  if (client->session_pool == NULL)
+  if (priv->session_pool == NULL)
     goto no_pool;
 
   session = state->session;
@@ -1143,7 +1207,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
   } else {
     /* create a session if this fails we probably reached our session limit or
      * something. */
-    if (!(session = gst_rtsp_session_pool_create (client->session_pool)))
+    if (!(session = gst_rtsp_session_pool_create (priv->session_pool)))
       goto service_unavailable;
 
     state->session = session;
@@ -1166,7 +1230,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
     goto not_found;
 
   state->sessmedia = sessmedia;
-  state->media = media = sessmedia->media;
+  state->media = media = gst_rtsp_session_media_get_media (sessmedia);
 
   /* now get the stream */
   stream = gst_rtsp_media_get_stream (media, streamid);
@@ -1207,14 +1271,15 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
   send_response (client, session, state->response, FALSE);
 
   /* update the state */
-  switch (sessmedia->state) {
+  rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia);
+  switch (rtspstate) {
     case GST_RTSP_STATE_PLAYING:
     case GST_RTSP_STATE_RECORDING:
     case GST_RTSP_STATE_READY:
       /* no state change */
       break;
     default:
-      sessmedia->state = GST_RTSP_STATE_READY;
+      gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_READY);
       break;
   }
   g_object_unref (session);
@@ -1287,6 +1352,7 @@ service_unavailable:
 static GstSDPMessage *
 create_sdp (GstRTSPClient * client, GstRTSPMedia * media)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GstSDPMessage *sdp;
   GstSDPInfo info;
   const gchar *proto;
@@ -1296,13 +1362,13 @@ create_sdp (GstRTSPClient * client, GstRTSPMedia * media)
   /* some standard things first */
   gst_sdp_message_set_version (sdp, "0");
 
-  if (client->is_ipv6)
+  if (priv->is_ipv6)
     proto = "IP6";
   else
     proto = "IP4";
 
   gst_sdp_message_set_origin (sdp, "-", "1188340656180883", "1", "IN", proto,
-      client->server_ip);
+      priv->server_ip);
 
   gst_sdp_message_set_session_name (sdp, "Session streamed with GStreamer");
   gst_sdp_message_set_information (sdp, "rtsp-server");
@@ -1312,7 +1378,7 @@ create_sdp (GstRTSPClient * client, GstRTSPMedia * media)
   gst_sdp_message_add_attribute (sdp, "control", "*");
 
   info.server_proto = proto;
-  info.server_ip = g_strdup (client->server_ip);
+  info.server_ip = g_strdup (priv->server_ip);
 
   /* create an SDP for the media object */
   if (!gst_rtsp_sdp_from_media (sdp, &info, media))
@@ -1484,13 +1550,15 @@ sanitize_uri (GstRTSPUrl * uri)
 static void
 client_session_finalized (GstRTSPClient * client, GstRTSPSession * session)
 {
+  GstRTSPClientPrivate *priv = client->priv;
+
   GST_INFO ("client %p: session %p finished", client, session);
 
   /* unlink all media managed in this session */
   client_unlink_session (client, session);
 
   /* remove the session */
-  if (!(client->sessions = g_list_remove (client->sessions, session))) {
+  if (!(priv->sessions = g_list_remove (priv->sessions, session))) {
     GST_INFO ("client %p: all sessions finalized, close the connection",
         client);
     close_connection (client);
@@ -1500,9 +1568,10 @@ client_session_finalized (GstRTSPClient * client, GstRTSPSession * session)
 static void
 client_watch_session (GstRTSPClient * client, GstRTSPSession * session)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GList *walk;
 
-  for (walk = client->sessions; walk; walk = g_list_next (walk)) {
+  for (walk = priv->sessions; walk; walk = g_list_next (walk)) {
     GstRTSPSession *msession = (GstRTSPSession *) walk->data;
 
     /* we already know about this session */
@@ -1514,7 +1583,7 @@ client_watch_session (GstRTSPClient * client, GstRTSPSession * session)
 
   g_object_weak_ref (G_OBJECT (session), (GWeakNotify) client_session_finalized,
       client);
-  client->sessions = g_list_prepend (client->sessions, session);
+  priv->sessions = g_list_prepend (priv->sessions, session);
 
   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_NEW_SESSION], 0,
       session);
@@ -1523,6 +1592,7 @@ client_watch_session (GstRTSPClient * client, GstRTSPSession * session)
 static void
 handle_request (GstRTSPClient * client, GstRTSPMessage * request)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GstRTSPMethod method;
   const gchar *uristr;
   GstRTSPUrl *uri = NULL;
@@ -1557,11 +1627,11 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request)
   /* get the session if there is any */
   res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_SESSION, &sessid, 0);
   if (res == GST_RTSP_OK) {
-    if (client->session_pool == NULL)
+    if (priv->session_pool == NULL)
       goto no_pool;
 
     /* we had a session in the request, find it again */
-    if (!(session = gst_rtsp_session_pool_find (client->session_pool, sessid)))
+    if (!(session = gst_rtsp_session_pool_find (priv->session_pool, sessid)))
       goto session_not_found;
 
     /* we add the session to the client list of watched sessions. When a session
@@ -1575,8 +1645,8 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request)
   state.uri = uri;
   state.session = session;
 
-  if (client->auth) {
-    if (!gst_rtsp_auth_check (client->auth, client, 0, &state))
+  if (priv->auth) {
+    if (!gst_rtsp_auth_check (priv->auth, client, 0, &state))
       goto not_authorized;
   }
 
@@ -1651,7 +1721,7 @@ session_not_found:
 not_authorized:
   {
     GST_ERROR ("client %p: not allowed", client);
-    handle_unauthorized_request (client, client->auth, &state);
+    handle_unauthorized_request (client, priv->auth, &state);
     goto done;
   }
 not_implemented:
@@ -1665,6 +1735,7 @@ not_implemented:
 static void
 handle_data (GstRTSPClient * client, GstRTSPMessage * message)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GstRTSPResult res;
   guint8 channel;
   GList *walk;
@@ -1683,16 +1754,15 @@ handle_data (GstRTSPClient * client, GstRTSPMessage * message)
   buffer = gst_buffer_new_wrapped (data, size);
 
   handled = FALSE;
-  for (walk = client->transports; walk; walk = g_list_next (walk)) {
+  for (walk = priv->transports; walk; walk = g_list_next (walk)) {
     GstRTSPStreamTransport *trans;
     GstRTSPStream *stream;
-    GstRTSPTransport *tr;
+    const GstRTSPTransport *tr;
 
     trans = walk->data;
 
-    /* we only add clients with a transport to the list */
-    tr = trans->transport;
-    stream = trans->stream;
+    tr = gst_rtsp_stream_transport_get_transport (trans);
+    stream = gst_rtsp_stream_transport_get_stream (trans);
 
     /* check for TCP transport */
     if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
@@ -1726,16 +1796,19 @@ gst_rtsp_client_set_session_pool (GstRTSPClient * client,
     GstRTSPSessionPool * pool)
 {
   GstRTSPSessionPool *old;
+  GstRTSPClientPrivate *priv;
 
   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
 
+  priv = client->priv;
+
   if (pool)
     g_object_ref (pool);
 
-  g_mutex_lock (&client->lock);
-  old = client->session_pool;
-  client->session_pool = pool;
-  g_mutex_unlock (&client->lock);
+  g_mutex_lock (&priv->lock);
+  old = priv->session_pool;
+  priv->session_pool = pool;
+  g_mutex_unlock (&priv->lock);
 
   if (old)
     g_object_unref (old);
@@ -1752,14 +1825,17 @@ gst_rtsp_client_set_session_pool (GstRTSPClient * client,
 GstRTSPSessionPool *
 gst_rtsp_client_get_session_pool (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv;
   GstRTSPSessionPool *result;
 
   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
 
-  g_mutex_lock (&client->lock);
-  if ((result = client->session_pool))
+  priv = client->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->session_pool))
     g_object_ref (result);
-  g_mutex_unlock (&client->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -1777,17 +1853,20 @@ void
 gst_rtsp_client_set_mount_points (GstRTSPClient * client,
     GstRTSPMountPoints * mounts)
 {
+  GstRTSPClientPrivate *priv;
   GstRTSPMountPoints *old;
 
   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
 
+  priv = client->priv;
+
   if (mounts)
     g_object_ref (mounts);
 
-  g_mutex_lock (&client->lock);
-  old = client->mount_points;
-  client->mount_points = mounts;
-  g_mutex_unlock (&client->lock);
+  g_mutex_lock (&priv->lock);
+  old = priv->mount_points;
+  priv->mount_points = mounts;
+  g_mutex_unlock (&priv->lock);
 
   if (old)
     g_object_unref (old);
@@ -1804,14 +1883,17 @@ gst_rtsp_client_set_mount_points (GstRTSPClient * client,
 GstRTSPMountPoints *
 gst_rtsp_client_get_mount_points (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv;
   GstRTSPMountPoints *result;
 
   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
 
-  g_mutex_lock (&client->lock);
-  if ((result = client->mount_points))
+  priv = client->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->mount_points))
     g_object_ref (result);
-  g_mutex_unlock (&client->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -1829,11 +1911,15 @@ void
 gst_rtsp_client_set_use_client_settings (GstRTSPClient * client,
     gboolean use_client_settings)
 {
+  GstRTSPClientPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
 
-  g_mutex_lock (&client->lock);
-  client->use_client_settings = use_client_settings;
-  g_mutex_unlock (&client->lock);
+  priv = client->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->use_client_settings = use_client_settings;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -1846,13 +1932,16 @@ gst_rtsp_client_set_use_client_settings (GstRTSPClient * client,
 gboolean
 gst_rtsp_client_get_use_client_settings (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv;
   gboolean res;
 
   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
 
-  g_mutex_lock (&client->lock);
-  res = client->use_client_settings;
-  g_mutex_unlock (&client->lock);
+  priv = client->priv;
+
+  g_mutex_lock (&priv->lock);
+  res = priv->use_client_settings;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -1867,17 +1956,20 @@ gst_rtsp_client_get_use_client_settings (GstRTSPClient * client)
 void
 gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth)
 {
+  GstRTSPClientPrivate *priv;
   GstRTSPAuth *old;
 
   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
 
+  priv = client->priv;
+
   if (auth)
     g_object_ref (auth);
 
-  g_mutex_lock (&client->lock);
-  old = client->auth;
-  client->auth = auth;
-  g_mutex_unlock (&client->lock);
+  g_mutex_lock (&priv->lock);
+  old = priv->auth;
+  priv->auth = auth;
+  g_mutex_unlock (&priv->lock);
 
   if (old)
     g_object_unref (old);
@@ -1896,14 +1988,17 @@ gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth)
 GstRTSPAuth *
 gst_rtsp_client_get_auth (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv;
   GstRTSPAuth *result;
 
   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
 
-  g_mutex_lock (&client->lock);
-  if ((result = client->auth))
+  priv = client->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->auth))
     g_object_ref (result);
-  g_mutex_unlock (&client->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -1923,18 +2018,21 @@ void
 gst_rtsp_client_set_send_func (GstRTSPClient * client,
     GstRTSPClientSendFunc func, gpointer user_data, GDestroyNotify notify)
 {
+  GstRTSPClientPrivate *priv;
   GDestroyNotify old_notify;
   gpointer old_data;
 
   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
 
-  g_mutex_lock (&client->lock);
-  client->send_func = func;
-  old_notify = client->send_notify;
-  old_data = client->send_data;
-  client->send_notify = notify;
-  client->send_data = user_data;
-  g_mutex_unlock (&client->lock);
+  priv = client->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->send_func = func;
+  old_notify = priv->send_notify;
+  old_data = priv->send_data;
+  priv->send_notify = notify;
+  priv->send_data = user_data;
+  g_mutex_unlock (&priv->lock);
 
   if (old_notify)
     old_notify (old_data);
@@ -1975,10 +2073,12 @@ static GstRTSPResult
 do_send_message (GstRTSPClient * client, GstRTSPMessage * message,
     gboolean close, gpointer user_data)
 {
+  GstRTSPClientPrivate *priv = client->priv;
+
   /* send the response and store the seq number so we can wait until it's
    * written to the client to close the connection */
-  return gst_rtsp_watch_send_message (client->watch, message, close ?
-      &client->close_seq : NULL);
+  return gst_rtsp_watch_send_message (priv->watch, message, close ?
+      &priv->close_seq : NULL);
 }
 
 static GstRTSPResult
@@ -1992,9 +2092,10 @@ static GstRTSPResult
 message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data)
 {
   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+  GstRTSPClientPrivate *priv = client->priv;
 
-  if (client->close_seq && client->close_seq == cseq) {
-    client->close_seq = 0;
+  if (priv->close_seq && priv->close_seq == cseq) {
+    priv->close_seq = 0;
     close_connection (client);
   }
 
@@ -2005,11 +2106,12 @@ static GstRTSPResult
 closed (GstRTSPWatch * watch, gpointer user_data)
 {
   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+  GstRTSPClientPrivate *priv = client->priv;
   const gchar *tunnelid;
 
   GST_INFO ("client %p: connection closed", client);
 
-  if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
+  if ((tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection))) {
     g_mutex_lock (&tunnels_lock);
     /* remove from tunnelids */
     g_hash_table_remove (tunnels, tunnelid);
@@ -2051,10 +2153,11 @@ error_full (GstRTSPWatch * watch, GstRTSPResult result,
 static gboolean
 remember_tunnel (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   const gchar *tunnelid;
 
   /* store client in the pending tunnels */
-  tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
+  tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection);
   if (tunnelid == NULL)
     goto no_tunnelid;
 
@@ -2088,12 +2191,11 @@ tunnel_existed:
 static GstRTSPStatusCode
 tunnel_start (GstRTSPWatch * watch, gpointer user_data)
 {
-  GstRTSPClient *client;
-
-  client = GST_RTSP_CLIENT (user_data);
+  GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+  GstRTSPClientPrivate *priv = client->priv;
 
   GST_INFO ("client %p: tunnel start (connection %p)", client,
-      client->connection);
+      priv->connection);
 
   if (!remember_tunnel (client))
     goto tunnel_error;
@@ -2111,12 +2213,11 @@ tunnel_error:
 static GstRTSPResult
 tunnel_lost (GstRTSPWatch * watch, gpointer user_data)
 {
-  GstRTSPClient *client;
-
-  client = GST_RTSP_CLIENT (user_data);
+  GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+  GstRTSPClientPrivate *priv = client->priv;
 
   GST_WARNING ("client %p: tunnel lost (connection %p)", client,
-      client->connection);
+      priv->connection);
 
   /* ignore error, it'll only be a problem when the client does a POST again */
   remember_tunnel (client);
@@ -2129,12 +2230,14 @@ tunnel_complete (GstRTSPWatch * watch, gpointer user_data)
 {
   const gchar *tunnelid;
   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+  GstRTSPClientPrivate *priv = client->priv;
   GstRTSPClient *oclient;
+  GstRTSPClientPrivate *opriv;
 
   GST_INFO ("client %p: tunnel complete", client);
 
   /* find previous tunnel */
-  tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
+  tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection);
   if (tunnelid == NULL)
     goto no_tunnelid;
 
@@ -2147,16 +2250,18 @@ tunnel_complete (GstRTSPWatch * watch, gpointer user_data)
   g_object_ref (oclient);
   g_hash_table_remove (tunnels, tunnelid);
 
-  if (oclient->watch == NULL)
+  opriv = oclient->priv;
+
+  if (opriv->watch == NULL)
     goto tunnel_closed;
   g_mutex_unlock (&tunnels_lock);
 
   GST_INFO ("client %p: found tunnel %p (old %p, new %p)", client, oclient,
-      oclient->connection, client->connection);
+      opriv->connection, priv->connection);
 
   /* merge the tunnels into the first client */
-  gst_rtsp_connection_do_tunnel (oclient->connection, client->connection);
-  gst_rtsp_watch_reset (oclient->watch);
+  gst_rtsp_connection_do_tunnel (opriv->connection, priv->connection);
+  gst_rtsp_watch_reset (opriv->watch);
   g_object_unref (oclient);
 
   return GST_RTSP_OK;
@@ -2196,8 +2301,10 @@ static GstRTSPWatchFuncs watch_funcs = {
 static void
 client_watch_notify (GstRTSPClient * client)
 {
+  GstRTSPClientPrivate *priv = client->priv;
+
   GST_INFO ("client %p: watch destroyed", client);
-  client->watch = NULL;
+  priv->watch = NULL;
   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL);
   g_object_unref (client);
 }
@@ -2206,36 +2313,37 @@ static gboolean
 setup_client (GstRTSPClient * client, GSocket * socket,
     GstRTSPConnection * conn, GError ** error)
 {
+  GstRTSPClientPrivate *priv = client->priv;
   GSocket *read_socket;
   GSocketAddress *address;
   GstRTSPUrl *url;
 
   read_socket = gst_rtsp_connection_get_read_socket (conn);
-  client->is_ipv6 = g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6;
+  priv->is_ipv6 = g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6;
 
   if (!(address = g_socket_get_remote_address (read_socket, error)))
     goto no_address;
 
-  g_free (client->server_ip);
+  g_free (priv->server_ip);
   /* keep the original ip that the client connected to */
   if (G_IS_INET_SOCKET_ADDRESS (address)) {
     GInetAddress *iaddr;
 
     iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
 
-    client->server_ip = g_inet_address_to_string (iaddr);
+    priv->server_ip = g_inet_address_to_string (iaddr);
     g_object_unref (address);
   } else {
-    client->server_ip = g_strdup ("unknown");
+    priv->server_ip = g_strdup ("unknown");
   }
 
   GST_INFO ("client %p connected to server ip %s, ipv6 = %d", client,
-      client->server_ip, client->is_ipv6);
+      priv->server_ip, priv->is_ipv6);
 
   url = gst_rtsp_connection_get_url (conn);
   GST_INFO ("added new client %p ip %s:%d", client, url->host, url->port);
 
-  client->connection = conn;
+  priv->connection = conn;
 
   return TRUE;
 
@@ -2343,19 +2451,21 @@ accept_failed:
 guint
 gst_rtsp_client_attach (GstRTSPClient * client, GMainContext * context)
 {
+  GstRTSPClientPrivate *priv;
   guint res;
 
   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), 0);
-  g_return_val_if_fail (client->watch == NULL, 0);
+  priv = client->priv;
+  g_return_val_if_fail (priv->watch == NULL, 0);
 
   /* create watch for the connection and attach */
-  client->watch = gst_rtsp_watch_new (client->connection, &watch_funcs,
+  priv->watch = gst_rtsp_watch_new (priv->connection, &watch_funcs,
       g_object_ref (client), (GDestroyNotify) client_watch_notify);
   gst_rtsp_client_set_send_func (client, do_send_message, NULL, NULL);
 
   GST_INFO ("attaching to context %p", context);
-  res = gst_rtsp_watch_attach (client->watch, context);
-  gst_rtsp_watch_unref (client->watch);
+  res = gst_rtsp_watch_attach (priv->watch, context);
+  gst_rtsp_watch_unref (priv->watch);
 
   return res;
 }
index 6ec1f86..a718cc7 100644 (file)
@@ -28,6 +28,7 @@ G_BEGIN_DECLS
 typedef struct _GstRTSPClient GstRTSPClient;
 typedef struct _GstRTSPClientClass GstRTSPClientClass;
 typedef struct _GstRTSPClientState GstRTSPClientState;
+typedef struct _GstRTSPClientPrivate GstRTSPClientPrivate;
 
 #include "rtsp-media.h"
 #include "rtsp-mount-points.h"
@@ -90,51 +91,13 @@ typedef gboolean (*GstRTSPClientSendFunc)      (GstRTSPClient *client,
 
 /**
  * GstRTSPClient:
- * @lock: lock protecting the client object
- * @connection: the connection object handling the client request.
- * @watch: watch for the connection
- * @close_seq: sequence number of message with close header
- * @server_ip: ip address of the server
- * @is_ipv6: if we are IPv6
- * @use_client_settings: whether to allow client transport settings for multicast
- * @send_func: a #GstRTSPClientSendFunc called when an RTSP message needs to be
- *             sent to the client.
- * @send_data: user data passed to @send_func
- * @send_notify: notify called when @send_data is no longer used.
- * @session_pool: handle to the session pool used by the client.
- * @mount_points: handle to the mount points used by the client.
- * @auth: authorization object
- * @uri: cached uri
- * @media: cached media
- * @transports: a list of #GstRTSPStreamTransport using @connection.
- * @sessions: a list of sessions managed by @connection.
  *
  * The client structure.
  */
 struct _GstRTSPClient {
   GObject       parent;
 
-  GMutex             lock;
-  GstRTSPConnection *connection;
-  GstRTSPWatch      *watch;
-  guint              close_seq;
-  gchar             *server_ip;
-  gboolean           is_ipv6;
-  gboolean           use_client_settings;
-
-  GstRTSPClientSendFunc send_func;
-  gpointer              send_data;
-  GDestroyNotify        send_notify;
-
-  GstRTSPSessionPool   *session_pool;
-  GstRTSPMountPoints   *mount_points;
-  GstRTSPAuth          *auth;
-
-  GstRTSPUrl     *uri;
-  GstRTSPMedia   *media;
-
-  GList *transports;
-  GList *sessions;
+  GstRTSPClientPrivate *priv;
 };
 
 struct _GstRTSPClientClass {
index cd262b3..84022a3 100644 (file)
 
 #include "rtsp-media-factory-uri.h"
 
+#define GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE(obj)  \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_URI, GstRTSPMediaFactoryURIPrivate))
+
+struct _GstRTSPMediaFactoryURIPrivate
+{
+  GMutex lock;
+  gchar *uri;
+  gboolean use_gstpay;
+
+  GstCaps *raw_vcaps;
+  GstCaps *raw_acaps;
+  GList *demuxers;
+  GList *payloaders;
+  GList *decoders;
+};
+
 #define DEFAULT_URI         NULL
 #define DEFAULT_USE_GSTPAY  FALSE
 
@@ -156,41 +172,48 @@ payloader_filter (GstPluginFeature * feature, FilterData * data)
 static void
 gst_rtsp_media_factory_uri_init (GstRTSPMediaFactoryURI * factory)
 {
+  GstRTSPMediaFactoryURIPrivate *priv =
+      GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE (factory);
   FilterData data = { NULL, NULL, NULL };
 
   GST_DEBUG_OBJECT (factory, "new");
 
-  factory->uri = g_strdup (DEFAULT_URI);
-  factory->use_gstpay = DEFAULT_USE_GSTPAY;
+  factory->priv = priv;
+
+  priv->uri = g_strdup (DEFAULT_URI);
+  priv->use_gstpay = DEFAULT_USE_GSTPAY;
+  g_mutex_init (&priv->lock);
 
   /* get the feature list using the filter */
   gst_registry_feature_filter (gst_registry_get (), (GstPluginFeatureFilter)
       payloader_filter, FALSE, &data);
   /* sort */
-  factory->demuxers =
+  priv->demuxers =
       g_list_sort (data.demux, gst_plugin_feature_rank_compare_func);
-  factory->payloaders =
+  priv->payloaders =
       g_list_sort (data.payload, gst_plugin_feature_rank_compare_func);
-  factory->decoders =
+  priv->decoders =
       g_list_sort (data.decode, gst_plugin_feature_rank_compare_func);
 
-  factory->raw_vcaps = gst_static_caps_get (&raw_video_caps);
-  factory->raw_acaps = gst_static_caps_get (&raw_audio_caps);
+  priv->raw_vcaps = gst_static_caps_get (&raw_video_caps);
+  priv->raw_acaps = gst_static_caps_get (&raw_audio_caps);
 }
 
 static void
 gst_rtsp_media_factory_uri_finalize (GObject * obj)
 {
   GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (obj);
+  GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
 
   GST_DEBUG_OBJECT (factory, "finalize");
 
-  g_free (factory->uri);
-  gst_plugin_feature_list_free (factory->demuxers);
-  gst_plugin_feature_list_free (factory->payloaders);
-  gst_plugin_feature_list_free (factory->decoders);
-  gst_caps_unref (factory->raw_vcaps);
-  gst_caps_unref (factory->raw_acaps);
+  g_free (priv->uri);
+  gst_plugin_feature_list_free (priv->demuxers);
+  gst_plugin_feature_list_free (priv->payloaders);
+  gst_plugin_feature_list_free (priv->decoders);
+  gst_caps_unref (priv->raw_vcaps);
+  gst_caps_unref (priv->raw_acaps);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_media_factory_uri_parent_class)->finalize (obj);
 }
@@ -200,13 +223,14 @@ gst_rtsp_media_factory_uri_get_property (GObject * object, guint propid,
     GValue * value, GParamSpec * pspec)
 {
   GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object);
+  GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
 
   switch (propid) {
     case PROP_URI:
       g_value_take_string (value, gst_rtsp_media_factory_uri_get_uri (factory));
       break;
     case PROP_USE_GSTPAY:
-      g_value_set_boolean (value, factory->use_gstpay);
+      g_value_set_boolean (value, priv->use_gstpay);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
@@ -218,13 +242,14 @@ gst_rtsp_media_factory_uri_set_property (GObject * object, guint propid,
     const GValue * value, GParamSpec * pspec)
 {
   GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object);
+  GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
 
   switch (propid) {
     case PROP_URI:
       gst_rtsp_media_factory_uri_set_uri (factory, g_value_get_string (value));
       break;
     case PROP_USE_GSTPAY:
-      factory->use_gstpay = g_value_get_boolean (value);
+      priv->use_gstpay = g_value_get_boolean (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
@@ -259,13 +284,17 @@ void
 gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI * factory,
     const gchar * uri)
 {
+  GstRTSPMediaFactoryURIPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory));
   g_return_if_fail (uri != NULL);
 
-  GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  g_free (factory->uri);
-  factory->uri = g_strdup (uri);
-  GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+  priv = factory->priv;
+
+  g_mutex_lock (&priv->lock);
+  g_free (priv->uri);
+  priv->uri = g_strdup (uri);
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -279,13 +308,16 @@ gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI * factory,
 gchar *
 gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI * factory)
 {
+  GstRTSPMediaFactoryURIPrivate *priv;
   gchar *result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory), NULL);
 
-  GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  result = g_strdup (factory->uri);
-  GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+  priv = factory->priv;
+
+  g_mutex_lock (&priv->lock);
+  result = g_strdup (priv->uri);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -293,12 +325,13 @@ gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI * factory)
 static GstElementFactory *
 find_payloader (GstRTSPMediaFactoryURI * urifact, GstCaps * caps)
 {
+  GstRTSPMediaFactoryURIPrivate *priv = urifact->priv;
   GList *list;
   GstElementFactory *factory = NULL;
   gboolean autoplug_more = FALSE;
 
   /* first find a demuxer that can link */
-  list = gst_element_factory_list_filter (urifact->demuxers, caps,
+  list = gst_element_factory_list_filter (priv->demuxers, caps,
       GST_PAD_SINK, FALSE);
 
   if (list) {
@@ -340,17 +373,17 @@ find_payloader (GstRTSPMediaFactoryURI * urifact, GstCaps * caps)
     return NULL;
 
   /* no demuxer try a depayloader */
-  list = gst_element_factory_list_filter (urifact->payloaders, caps,
+  list = gst_element_factory_list_filter (priv->payloaders, caps,
       GST_PAD_SINK, FALSE);
 
   if (list == NULL) {
-    if (urifact->use_gstpay) {
+    if (priv->use_gstpay) {
       /* no depayloader or parser/demuxer, use gstpay when allowed */
       factory = gst_element_factory_find ("rtpgstpay");
     } else {
       /* no depayloader, try a decoder, we'll get to a payloader for a decoded
        * video or audio format, worst case. */
-      list = gst_element_factory_list_filter (urifact->decoders, caps,
+      list = gst_element_factory_list_filter (priv->decoders, caps,
           GST_PAD_SINK, FALSE);
 
       if (list != NULL) {
@@ -405,6 +438,7 @@ static void
 pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element)
 {
   GstRTSPMediaFactoryURI *urifact;
+  GstRTSPMediaFactoryURIPrivate *priv;
   FactoryData *data;
   GstElementFactory *factory;
   GstElement *payloader;
@@ -418,6 +452,7 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element)
   /* link the element now and expose the pad */
   data = g_object_get_data (G_OBJECT (element), factory_key);
   urifact = data->factory;
+  priv = urifact->priv;
 
   /* ref to make refcounting easier later */
   gst_object_ref (pad);
@@ -429,10 +464,10 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element)
       goto no_caps;
 
   /* check for raw caps */
-  if (gst_caps_can_intersect (caps, urifact->raw_vcaps)) {
+  if (gst_caps_can_intersect (caps, priv->raw_vcaps)) {
     /* we have raw video caps, insert converter */
     convert = gst_element_factory_make ("videoconvert", NULL);
-  } else if (gst_caps_can_intersect (caps, urifact->raw_acaps)) {
+  } else if (gst_caps_can_intersect (caps, priv->raw_acaps)) {
     /* we have raw audio caps, insert converter */
     convert = gst_element_factory_make ("audioconvert", NULL);
   } else {
@@ -536,11 +571,13 @@ static GstElement *
 rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * factory,
     const GstRTSPUrl * url)
 {
+  GstRTSPMediaFactoryURIPrivate *priv;
   GstElement *topbin, *element, *uribin;
   GstRTSPMediaFactoryURI *urifact;
   FactoryData *data;
 
   urifact = GST_RTSP_MEDIA_FACTORY_URI_CAST (factory);
+  priv = urifact->priv;
 
   GST_LOG ("creating element");
 
@@ -555,7 +592,7 @@ rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * factory,
   if (uribin == NULL)
     goto no_uridecodebin;
 
-  g_object_set (uribin, "uri", urifact->uri, NULL);
+  g_object_set (uribin, "uri", priv->uri, NULL);
 
   /* keep factory data around */
   data = g_new0 (FactoryData, 1);
index da71aa7..fd1eb98 100644 (file)
@@ -38,24 +38,17 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPMediaFactoryURI GstRTSPMediaFactoryURI;
 typedef struct _GstRTSPMediaFactoryURIClass GstRTSPMediaFactoryURIClass;
+typedef struct _GstRTSPMediaFactoryURIPrivate GstRTSPMediaFactoryURIPrivate;
 
 /**
  * GstRTSPMediaFactoryURI:
- * @uri: the uri
  *
  * A media factory that creates a pipeline to play and uri.
  */
 struct _GstRTSPMediaFactoryURI {
   GstRTSPMediaFactory   parent;
 
-  gchar *uri;
-  gboolean use_gstpay;
-
-  GstCaps *raw_vcaps;
-  GstCaps *raw_acaps;
-  GList *demuxers;
-  GList *payloaders;
-  GList *decoders;
+  GstRTSPMediaFactoryURIPrivate *priv;
 };
 
 /**
index 0861c97..cd4b1a7 100644 (file)
 
 #include "rtsp-media-factory.h"
 
+#define GST_RTSP_MEDIA_FACTORY_GET_PRIVATE(obj)  \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryPrivate))
+
+#define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)       (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->priv->lock))
+#define GST_RTSP_MEDIA_FACTORY_LOCK(f)           (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
+#define GST_RTSP_MEDIA_FACTORY_UNLOCK(f)         (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
+
+struct _GstRTSPMediaFactoryPrivate
+{
+  GMutex lock;
+  gchar *launch;
+  gboolean shared;
+  gboolean eos_shutdown;
+  GstRTSPLowerTrans protocols;
+  GstRTSPAuth *auth;
+  guint buffer_size;
+  GstRTSPAddressPool *pool;
+
+  GMutex medias_lock;
+  GHashTable *medias;
+};
+
 #define DEFAULT_LAUNCH          NULL
 #define DEFAULT_SHARED          FALSE
 #define DEFAULT_EOS_SHUTDOWN    FALSE
@@ -72,6 +94,8 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->get_property = gst_rtsp_media_factory_get_property;
@@ -144,15 +168,19 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
 static void
 gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
 {
-  factory->launch = g_strdup (DEFAULT_LAUNCH);
-  factory->shared = DEFAULT_SHARED;
-  factory->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
-  factory->protocols = DEFAULT_PROTOCOLS;
-  factory->buffer_size = DEFAULT_BUFFER_SIZE;
-
-  g_mutex_init (&factory->lock);
-  g_mutex_init (&factory->medias_lock);
-  factory->medias = g_hash_table_new_full (g_str_hash, g_str_equal,
+  GstRTSPMediaFactoryPrivate *priv =
+      GST_RTSP_MEDIA_FACTORY_GET_PRIVATE (factory);
+  factory->priv = priv;
+
+  priv->launch = g_strdup (DEFAULT_LAUNCH);
+  priv->shared = DEFAULT_SHARED;
+  priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
+  priv->protocols = DEFAULT_PROTOCOLS;
+  priv->buffer_size = DEFAULT_BUFFER_SIZE;
+
+  g_mutex_init (&priv->lock);
+  g_mutex_init (&priv->medias_lock);
+  priv->medias = g_hash_table_new_full (g_str_hash, g_str_equal,
       g_free, g_object_unref);
 }
 
@@ -160,15 +188,16 @@ static void
 gst_rtsp_media_factory_finalize (GObject * obj)
 {
   GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (obj);
+  GstRTSPMediaFactoryPrivate *priv = factory->priv;
 
-  g_hash_table_unref (factory->medias);
-  g_mutex_clear (&factory->medias_lock);
-  g_free (factory->launch);
-  g_mutex_clear (&factory->lock);
-  if (factory->auth)
-    g_object_unref (factory->auth);
-  if (factory->pool)
-    g_object_unref (factory->pool);
+  g_hash_table_unref (priv->medias);
+  g_mutex_clear (&priv->medias_lock);
+  g_free (priv->launch);
+  g_mutex_clear (&priv->lock);
+  if (priv->auth)
+    g_object_unref (priv->auth);
+  if (priv->pool)
+    g_object_unref (priv->pool);
 
   G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj);
 }
@@ -268,12 +297,16 @@ void
 gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory,
     const gchar * launch)
 {
+  GstRTSPMediaFactoryPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
   g_return_if_fail (launch != NULL);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  g_free (factory->launch);
-  factory->launch = g_strdup (launch);
+  g_free (priv->launch);
+  priv->launch = g_strdup (launch);
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 }
 
@@ -289,12 +322,15 @@ gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory,
 gchar *
 gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory * factory)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   gchar *result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  result = g_strdup (factory->launch);
+  result = g_strdup (priv->launch);
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
   return result;
@@ -311,10 +347,14 @@ void
 gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory,
     gboolean shared)
 {
+  GstRTSPMediaFactoryPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  factory->shared = shared;
+  priv->shared = shared;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 }
 
@@ -329,12 +369,15 @@ gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory,
 gboolean
 gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory * factory)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   gboolean result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  result = factory->shared;
+  result = priv->shared;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
   return result;
@@ -352,10 +395,14 @@ void
 gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory,
     gboolean eos_shutdown)
 {
+  GstRTSPMediaFactoryPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  factory->eos_shutdown = eos_shutdown;
+  priv->eos_shutdown = eos_shutdown;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 }
 
@@ -371,12 +418,15 @@ gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory,
 gboolean
 gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory * factory)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   gboolean result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  result = factory->eos_shutdown;
+  result = priv->eos_shutdown;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
   return result;
@@ -393,10 +443,14 @@ void
 gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory,
     guint size)
 {
+  GstRTSPMediaFactoryPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  factory->buffer_size = size;
+  priv->buffer_size = size;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 }
 
@@ -411,12 +465,15 @@ gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory,
 guint
 gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   guint result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  result = factory->buffer_size;
+  result = priv->buffer_size;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
   return result;
@@ -433,13 +490,16 @@ void
 gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory,
     GstRTSPAddressPool * pool)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   GstRTSPAddressPool *old;
 
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  if ((old = factory->pool) != pool)
-    factory->pool = pool ? g_object_ref (pool) : NULL;
+  if ((old = priv->pool) != pool)
+    priv->pool = pool ? g_object_ref (pool) : NULL;
   else
     old = NULL;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
@@ -460,12 +520,15 @@ gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory,
 GstRTSPAddressPool *
 gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   GstRTSPAddressPool *result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  if ((result = factory->pool))
+  if ((result = priv->pool))
     g_object_ref (result);
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
@@ -483,13 +546,16 @@ void
 gst_rtsp_media_factory_set_auth (GstRTSPMediaFactory * factory,
     GstRTSPAuth * auth)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   GstRTSPAuth *old;
 
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  if ((old = factory->auth) != auth)
-    factory->auth = auth ? g_object_ref (auth) : NULL;
+  if ((old = priv->auth) != auth)
+    priv->auth = auth ? g_object_ref (auth) : NULL;
   else
     old = NULL;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
@@ -510,12 +576,15 @@ gst_rtsp_media_factory_set_auth (GstRTSPMediaFactory * factory,
 GstRTSPAuth *
 gst_rtsp_media_factory_get_auth (GstRTSPMediaFactory * factory)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   GstRTSPAuth *result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  if ((result = factory->auth))
+  if ((result = priv->auth))
     g_object_ref (result);
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
@@ -533,10 +602,14 @@ void
 gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory,
     GstRTSPLowerTrans protocols)
 {
+  GstRTSPMediaFactoryPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  factory->protocols = protocols;
+  priv->protocols = protocols;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 }
 
@@ -551,13 +624,16 @@ gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory,
 GstRTSPLowerTrans
 gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory * factory)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   GstRTSPLowerTrans res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
       GST_RTSP_LOWER_TRANS_UNKNOWN);
 
+  priv = factory->priv;
+
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  res = factory->protocols;
+  res = priv->protocols;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
   return res;
@@ -572,9 +648,11 @@ compare_media (gpointer key, GstRTSPMedia * media1, GstRTSPMedia * media2)
 static void
 media_unprepared (GstRTSPMedia * media, GstRTSPMediaFactory * factory)
 {
-  g_mutex_lock (&factory->medias_lock);
-  g_hash_table_foreach_remove (factory->medias, (GHRFunc) compare_media, media);
-  g_mutex_unlock (&factory->medias_lock);
+  GstRTSPMediaFactoryPrivate *priv = factory->priv;;
+
+  g_mutex_lock (&priv->medias_lock);
+  g_hash_table_foreach_remove (priv->medias, (GHRFunc) compare_media, media);
+  g_mutex_unlock (&priv->medias_lock);
 }
 
 /**
@@ -598,6 +676,7 @@ GstRTSPMedia *
 gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
     const GstRTSPUrl * url)
 {
+  GstRTSPMediaFactoryPrivate *priv;
   gchar *key;
   GstRTSPMedia *media;
   GstRTSPMediaFactoryClass *klass;
@@ -605,6 +684,7 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
   g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
   g_return_val_if_fail (url != NULL, NULL);
 
+  priv = factory->priv;;
   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
 
   /* convert the url to a key for the hashtable. NULL return or a NULL function
@@ -614,10 +694,10 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
   else
     key = NULL;
 
-  g_mutex_lock (&factory->medias_lock);
+  g_mutex_lock (&priv->medias_lock);
   if (key) {
     /* we have a key, see if we find a cached media */
-    media = g_hash_table_lookup (factory->medias, key);
+    media = g_hash_table_lookup (priv->medias, key);
     if (media)
       g_object_ref (media);
   } else
@@ -647,7 +727,7 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
       if (gst_rtsp_media_is_shared (media)) {
         /* insert in the hashtable, takes ownership of the key */
         g_object_ref (media);
-        g_hash_table_insert (factory->medias, key, media);
+        g_hash_table_insert (priv->medias, key, media);
         key = NULL;
       }
       if (!gst_rtsp_media_is_reusable (media)) {
@@ -658,7 +738,7 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
       }
     }
   }
-  g_mutex_unlock (&factory->medias_lock);
+  g_mutex_unlock (&priv->medias_lock);
 
   if (key)
     g_free (key);
@@ -687,16 +767,17 @@ default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
 static GstElement *
 default_create_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
 {
+  GstRTSPMediaFactoryPrivate *priv = factory->priv;
   GstElement *element;
   GError *error = NULL;
 
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
   /* we need a parse syntax */
-  if (factory->launch == NULL)
+  if (priv->launch == NULL)
     goto no_launch;
 
   /* parse the user provided launch line */
-  element = gst_parse_launch (factory->launch, &error);
+  element = gst_parse_launch (priv->launch, &error);
   if (element == NULL)
     goto parse_error;
 
@@ -719,7 +800,7 @@ no_launch:
 parse_error:
   {
     GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
-    g_critical ("could not parse launch syntax (%s): %s", factory->launch,
+    g_critical ("could not parse launch syntax (%s): %s", priv->launch,
         (error ? error->message : "unknown reason"));
     if (error)
       g_error_free (error);
@@ -731,7 +812,7 @@ static GstRTSPMedia *
 default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
 {
   GstRTSPMedia *media;
-  GstElement *element;
+  GstElement *element, *pipeline;
   GstRTSPMediaFactoryClass *klass;
 
   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
@@ -744,13 +825,12 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
     goto no_element;
 
   /* create a new empty media */
-  media = gst_rtsp_media_new ();
-  media->element = element;
+  media = gst_rtsp_media_new (element);
 
   gst_rtsp_media_collect_streams (media);
 
-  media->pipeline = klass->create_pipeline (factory, media);
-  if (media->pipeline == NULL)
+  pipeline = klass->create_pipeline (factory, media);
+  if (pipeline == NULL)
     goto no_pipeline;
 
   return media;
@@ -779,25 +859,16 @@ default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
 {
   GstElement *pipeline;
 
-  if (media->element == NULL)
-    goto no_element;
-
   pipeline = gst_pipeline_new ("media-pipeline");
-  gst_bin_add (GST_BIN_CAST (pipeline), media->element);
+  gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
 
   return pipeline;
-
-  /* ERRORS */
-no_element:
-  {
-    g_critical ("no element");
-    return NULL;
-  }
 }
 
 static void
 default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
 {
+  GstRTSPMediaFactoryPrivate *priv = factory->priv;
   gboolean shared, eos_shutdown;
   guint size;
   GstRTSPAuth *auth;
@@ -806,10 +877,10 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
 
   /* configure the sharedness */
   GST_RTSP_MEDIA_FACTORY_LOCK (factory);
-  shared = factory->shared;
-  eos_shutdown = factory->eos_shutdown;
-  size = factory->buffer_size;
-  protocols = factory->protocols;
+  shared = priv->shared;
+  eos_shutdown = priv->eos_shutdown;
+  size = priv->buffer_size;
+  protocols = priv->protocols;
   GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
 
   gst_rtsp_media_set_shared (media, shared);
index 2a4745a..dce19e5 100644 (file)
@@ -41,24 +41,11 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPMediaFactory GstRTSPMediaFactory;
 typedef struct _GstRTSPMediaFactoryClass GstRTSPMediaFactoryClass;
-
-#define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)       (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->lock))
-#define GST_RTSP_MEDIA_FACTORY_LOCK(f)           (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
-#define GST_RTSP_MEDIA_FACTORY_UNLOCK(f)         (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
+typedef struct _GstRTSPMediaFactoryPrivate GstRTSPMediaFactoryPrivate;
 
 /**
  * GstRTSPMediaFactory:
  * @parent: the parent GObject
- * @lock: mutex protecting the datastructure.
- * @launch: the launch description
- * @shared: if media from this factory can be shared between clients
- * @eos_shutdown: if shutdown should first send EOS to the pipeline
- * @protocols: allowed transport protocols
- * @auth: the authentication manager
- * @buffer_size: the kernel udp buffer size
- * @pool: the multicast address pool to use
- * @medias_lock: mutex protecting the medias.
- * @medias: hashtable of shared media
  *
  * The definition and logic for constructing the pipeline for a media. The media
  * can contain multiple streams like audio and video.
@@ -66,17 +53,7 @@ typedef struct _GstRTSPMediaFactoryClass GstRTSPMediaFactoryClass;
 struct _GstRTSPMediaFactory {
   GObject            parent;
 
-  GMutex             lock;
-  gchar             *launch;
-  gboolean           shared;
-  gboolean           eos_shutdown;
-  GstRTSPLowerTrans  protocols;
-  GstRTSPAuth       *auth;
-  guint              buffer_size;
-  GstRTSPAddressPool *pool;
-
-  GMutex             medias_lock;
-  GHashTable        *medias;
+  GstRTSPMediaFactoryPrivate *priv;
 };
 
 /**
index 766f670..0165769 100644 (file)
 
 #include "rtsp-media.h"
 
+#define GST_RTSP_MEDIA_GET_PRIVATE(obj)  \
+     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaPrivate))
+
+struct _GstRTSPMediaPrivate
+{
+  GMutex lock;
+  GCond cond;
+
+  gboolean shared;
+  gboolean reusable;
+  GstRTSPLowerTrans protocols;
+  gboolean reused;
+  gboolean eos_shutdown;
+  guint buffer_size;
+  GstRTSPAuth *auth;
+  GstRTSPAddressPool *pool;
+
+  GstElement *element;
+  GRecMutex state_lock;
+  GPtrArray *streams;
+  GList *dynamic;
+  GstRTSPMediaStatus status;
+  gint n_active;
+  gboolean adding;
+
+  /* the pipeline for the media */
+  GstElement *pipeline;
+  GstElement *fakesink;
+  GSource *source;
+  guint id;
+
+  gboolean is_live;
+  gboolean seekable;
+  gboolean buffering;
+  GstState target_state;
+
+  /* RTP session manager */
+  GstElement *rtpbin;
+
+  /* the range of media */
+  GstRTSPTimeRange range;
+  GstClockTime range_start;
+  GstClockTime range_stop;
+};
+
 #define DEFAULT_SHARED          FALSE
 #define DEFAULT_REUSABLE        FALSE
 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
@@ -79,6 +124,8 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPMediaPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->get_property = gst_rtsp_media_get_property;
@@ -144,42 +191,48 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
 static void
 gst_rtsp_media_init (GstRTSPMedia * media)
 {
-  media->streams = g_ptr_array_new_with_free_func (g_object_unref);
-  g_mutex_init (&media->lock);
-  g_cond_init (&media->cond);
-  g_rec_mutex_init (&media->state_lock);
-
-  media->shared = DEFAULT_SHARED;
-  media->reusable = DEFAULT_REUSABLE;
-  media->protocols = DEFAULT_PROTOCOLS;
-  media->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
-  media->buffer_size = DEFAULT_BUFFER_SIZE;
+  GstRTSPMediaPrivate *priv = GST_RTSP_MEDIA_GET_PRIVATE (media);
+
+  media->priv = priv;
+
+  priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
+  g_mutex_init (&priv->lock);
+  g_cond_init (&priv->cond);
+  g_rec_mutex_init (&priv->state_lock);
+
+  priv->shared = DEFAULT_SHARED;
+  priv->reusable = DEFAULT_REUSABLE;
+  priv->protocols = DEFAULT_PROTOCOLS;
+  priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
+  priv->buffer_size = DEFAULT_BUFFER_SIZE;
 }
 
 static void
 gst_rtsp_media_finalize (GObject * obj)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPMedia *media;
 
   media = GST_RTSP_MEDIA (obj);
+  priv = media->priv;
 
   GST_INFO ("finalize media %p", media);
 
   gst_rtsp_media_unprepare (media);
 
-  g_ptr_array_unref (media->streams);
+  g_ptr_array_unref (priv->streams);
 
-  g_list_free_full (media->dynamic, gst_object_unref);
+  g_list_free_full (priv->dynamic, gst_object_unref);
 
-  if (media->pipeline)
-    gst_object_unref (media->pipeline);
-  if (media->auth)
-    g_object_unref (media->auth);
-  if (media->pool)
-    g_object_unref (media->pool);
-  g_mutex_clear (&media->lock);
-  g_cond_clear (&media->cond);
-  g_rec_mutex_clear (&media->state_lock);
+  if (priv->pipeline)
+    gst_object_unref (priv->pipeline);
+  if (priv->auth)
+    g_object_unref (priv->auth);
+  if (priv->pool)
+    g_object_unref (priv->pool);
+  g_mutex_clear (&priv->lock);
+  g_cond_clear (&priv->cond);
+  g_rec_mutex_clear (&priv->state_lock);
 
   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
 }
@@ -252,29 +305,30 @@ do_loop (GstRTSPMediaClass * klass)
 static void
 collect_media_stats (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv = media->priv;
   gint64 position, duration;
 
-  media->range.unit = GST_RTSP_RANGE_NPT;
+  priv->range.unit = GST_RTSP_RANGE_NPT;
 
   GST_INFO ("collect media stats");
 
-  if (media->is_live) {
-    media->range.min.type = GST_RTSP_TIME_NOW;
-    media->range.min.seconds = -1;
-    media->range_start = -1;
-    media->range.max.type = GST_RTSP_TIME_END;
-    media->range.max.seconds = -1;
-    media->range_stop = -1;
+  if (priv->is_live) {
+    priv->range.min.type = GST_RTSP_TIME_NOW;
+    priv->range.min.seconds = -1;
+    priv->range_start = -1;
+    priv->range.max.type = GST_RTSP_TIME_END;
+    priv->range.max.seconds = -1;
+    priv->range_stop = -1;
   } else {
     /* get the position */
-    if (!gst_element_query_position (media->pipeline, GST_FORMAT_TIME,
+    if (!gst_element_query_position (priv->pipeline, GST_FORMAT_TIME,
             &position)) {
       GST_INFO ("position query failed");
       position = 0;
     }
 
     /* get the duration */
-    if (!gst_element_query_duration (media->pipeline, GST_FORMAT_TIME,
+    if (!gst_element_query_duration (priv->pipeline, GST_FORMAT_TIME,
             &duration)) {
       GST_INFO ("duration query failed");
       duration = -1;
@@ -284,46 +338,81 @@ collect_media_stats (GstRTSPMedia * media)
         GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
 
     if (position == -1) {
-      media->range.min.type = GST_RTSP_TIME_NOW;
-      media->range.min.seconds = -1;
-      media->range_start = -1;
+      priv->range.min.type = GST_RTSP_TIME_NOW;
+      priv->range.min.seconds = -1;
+      priv->range_start = -1;
     } else {
-      media->range.min.type = GST_RTSP_TIME_SECONDS;
-      media->range.min.seconds = ((gdouble) position) / GST_SECOND;
-      media->range_start = position;
+      priv->range.min.type = GST_RTSP_TIME_SECONDS;
+      priv->range.min.seconds = ((gdouble) position) / GST_SECOND;
+      priv->range_start = position;
     }
     if (duration == -1) {
-      media->range.max.type = GST_RTSP_TIME_END;
-      media->range.max.seconds = -1;
-      media->range_stop = -1;
+      priv->range.max.type = GST_RTSP_TIME_END;
+      priv->range.max.seconds = -1;
+      priv->range_stop = -1;
     } else {
-      media->range.max.type = GST_RTSP_TIME_SECONDS;
-      media->range.max.seconds = ((gdouble) duration) / GST_SECOND;
-      media->range_stop = duration;
+      priv->range.max.type = GST_RTSP_TIME_SECONDS;
+      priv->range.max.seconds = ((gdouble) duration) / GST_SECOND;
+      priv->range_stop = duration;
     }
   }
 }
 
 /**
  * gst_rtsp_media_new:
+ * @element: (transfer full): a #GstElement
  *
- * Create a new #GstRTSPMedia instance. The #GstRTSPMedia object contains the
+ * Create a new #GstRTSPMedia instance. @element is the bin element that
+ * provides the different streams. The #GstRTSPMedia object contains the
  * element to produce RTP data for one or more related (audio/video/..)
  * streams.
  *
+ * Ownership is taken of @element.
+ *
  * Returns: a new #GstRTSPMedia object.
  */
 GstRTSPMedia *
-gst_rtsp_media_new (void)
+gst_rtsp_media_new (GstElement * element)
 {
   GstRTSPMedia *result;
 
   result = g_object_new (GST_TYPE_RTSP_MEDIA, NULL);
+  result->priv->element = element;
 
   return result;
 }
 
 /**
+ * gst_rtsp_media_take_element:
+ * @media: a #GstRTSPMedia
+ * @pipeline: (transfer full): a #GstPipeline
+ *
+ * Set @pipeline as the #GstPipeline for @media. Ownership is
+ * taken of @pipeline.
+ */
+void
+gst_rtsp_media_take_pipeline (GstRTSPMedia * media, GstPipeline * pipeline)
+{
+  GstRTSPMediaPrivate *priv;
+  GstElement *old;
+
+  g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+  g_return_if_fail (GST_IS_PIPELINE (pipeline));
+
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  old = priv->pipeline;
+  priv->pipeline = GST_ELEMENT_CAST (pipeline);
+  g_mutex_unlock (&priv->lock);
+
+  if (old)
+    gst_object_unref (old);
+
+  gst_bin_add (GST_BIN_CAST (pipeline), priv->element);
+}
+
+/**
  * gst_rtsp_media_set_shared:
  * @media: a #GstRTSPMedia
  * @shared: the new value
@@ -335,11 +424,15 @@ gst_rtsp_media_new (void)
 void
 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
 {
+  GstRTSPMediaPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
-  g_mutex_lock (&media->lock);
-  media->shared = shared;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->shared = shared;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -353,13 +446,16 @@ gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
 gboolean
 gst_rtsp_media_is_shared (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   gboolean res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
 
-  g_mutex_lock (&media->lock);
-  res = media->shared;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  res = priv->shared;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -375,11 +471,15 @@ gst_rtsp_media_is_shared (GstRTSPMedia * media)
 void
 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
 {
+  GstRTSPMediaPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
-  g_mutex_lock (&media->lock);
-  media->reusable = reusable;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->reusable = reusable;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -393,13 +493,16 @@ gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
 gboolean
 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   gboolean res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
 
-  g_mutex_lock (&media->lock);
-  res = media->reusable;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  res = priv->reusable;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -414,11 +517,15 @@ gst_rtsp_media_is_reusable (GstRTSPMedia * media)
 void
 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
 {
+  GstRTSPMediaPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
-  g_mutex_lock (&media->lock);
-  media->protocols = protocols;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->protocols = protocols;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -432,14 +539,17 @@ gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
 GstRTSPLowerTrans
 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPLowerTrans res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
       GST_RTSP_LOWER_TRANS_UNKNOWN);
 
-  g_mutex_lock (&media->lock);
-  res = media->protocols;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  res = priv->protocols;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -455,11 +565,15 @@ gst_rtsp_media_get_protocols (GstRTSPMedia * media)
 void
 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
 {
+  GstRTSPMediaPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
-  g_mutex_lock (&media->lock);
-  media->eos_shutdown = eos_shutdown;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->eos_shutdown = eos_shutdown;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -474,13 +588,16 @@ gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
 gboolean
 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   gboolean res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
 
-  g_mutex_lock (&media->lock);
-  res = media->eos_shutdown;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  res = priv->eos_shutdown;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -495,13 +612,17 @@ gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
 void
 gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
 {
+  GstRTSPMediaPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
   GST_LOG_OBJECT (media, "set buffer size %u", size);
 
-  g_mutex_lock (&media->lock);
-  media->buffer_size = size;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->buffer_size = size;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -515,13 +636,16 @@ gst_rtsp_media_set_buffer_size (GstRTSPMedia * media, guint size)
 guint
 gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   guint res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
 
-  g_mutex_unlock (&media->lock);
-  res = media->buffer_size;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_unlock (&priv->lock);
+  res = priv->buffer_size;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -536,18 +660,21 @@ gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
 void
 gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPAuth *old;
 
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
+  priv = media->priv;
+
   GST_LOG_OBJECT (media, "set auth %p", auth);
 
-  g_mutex_lock (&media->lock);
-  if ((old = media->auth) != auth)
-    media->auth = auth ? g_object_ref (auth) : NULL;
+  g_mutex_lock (&priv->lock);
+  if ((old = priv->auth) != auth)
+    priv->auth = auth ? g_object_ref (auth) : NULL;
   else
     old = NULL;
-  g_mutex_unlock (&media->lock);
+  g_mutex_unlock (&priv->lock);
 
   if (old)
     g_object_unref (old);
@@ -565,14 +692,17 @@ gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth)
 GstRTSPAuth *
 gst_rtsp_media_get_auth (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPAuth *result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
 
-  g_mutex_lock (&media->lock);
-  if ((result = media->auth))
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->auth))
     g_object_ref (result);
-  g_mutex_unlock (&media->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -588,20 +718,23 @@ void
 gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
     GstRTSPAddressPool * pool)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPAddressPool *old;
 
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
+  priv = media->priv;
+
   GST_LOG_OBJECT (media, "set address pool %p", pool);
 
-  g_mutex_lock (&media->lock);
-  if ((old = media->pool) != pool)
-    media->pool = pool ? g_object_ref (pool) : NULL;
+  g_mutex_lock (&priv->lock);
+  if ((old = priv->pool) != pool)
+    priv->pool = pool ? g_object_ref (pool) : NULL;
   else
     old = NULL;
-  g_ptr_array_foreach (media->streams, (GFunc) gst_rtsp_stream_set_address_pool,
+  g_ptr_array_foreach (priv->streams, (GFunc) gst_rtsp_stream_set_address_pool,
       pool);
-  g_mutex_unlock (&media->lock);
+  g_mutex_unlock (&priv->lock);
 
   if (old)
     g_object_unref (old);
@@ -619,14 +752,17 @@ gst_rtsp_media_set_address_pool (GstRTSPMedia * media,
 GstRTSPAddressPool *
 gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPAddressPool *result;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
 
-  g_mutex_lock (&media->lock);
-  if ((result = media->pool))
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->pool))
     g_object_ref (result);
-  g_mutex_unlock (&media->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -644,6 +780,7 @@ gst_rtsp_media_get_address_pool (GstRTSPMedia * media)
 void
 gst_rtsp_media_collect_streams (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   GstElement *element, *elem;
   GstPad *pad;
   gint i;
@@ -651,7 +788,8 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media)
 
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
-  element = media->element;
+  priv = media->priv;
+  element = priv->element;
 
   have_elem = TRUE;
   for (i = 0; have_elem; i++) {
@@ -680,9 +818,9 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media)
 
       GST_INFO ("found dynamic element %d, %p", i, elem);
 
-      g_mutex_lock (&media->lock);
-      media->dynamic = g_list_prepend (media->dynamic, elem);
-      g_mutex_unlock (&media->lock);
+      g_mutex_lock (&priv->lock);
+      priv->dynamic = g_list_prepend (priv->dynamic, elem);
+      g_mutex_unlock (&priv->lock);
 
       have_elem = TRUE;
     }
@@ -706,6 +844,7 @@ GstRTSPStream *
 gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
     GstPad * pad)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPStream *stream;
   GstPad *srcpad;
   gchar *name;
@@ -716,21 +855,25 @@ gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
   g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
 
-  g_mutex_lock (&media->lock);
-  idx = media->streams->len;
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  idx = priv->streams->len;
+
+  GST_DEBUG ("media %p: creating stream with index %d", media, idx);
 
   name = g_strdup_printf ("src_%u", idx);
   srcpad = gst_ghost_pad_new (name, pad);
   gst_pad_set_active (srcpad, TRUE);
-  gst_element_add_pad (media->element, srcpad);
+  gst_element_add_pad (priv->element, srcpad);
   g_free (name);
 
   stream = gst_rtsp_stream_new (idx, payloader, srcpad);
-  if (media->pool)
-    gst_rtsp_stream_set_address_pool (stream, media->pool);
+  if (priv->pool)
+    gst_rtsp_stream_set_address_pool (stream, priv->pool);
 
-  g_ptr_array_add (media->streams, stream);
-  g_mutex_unlock (&media->lock);
+  g_ptr_array_add (priv->streams, stream);
+  g_mutex_unlock (&priv->lock);
 
   g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STREAM], 0, stream,
       NULL);
@@ -749,13 +892,16 @@ gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
 guint
 gst_rtsp_media_n_streams (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   guint res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
 
-  g_mutex_lock (&media->lock);
-  res = media->streams->len;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  res = priv->streams->len;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -773,16 +919,19 @@ gst_rtsp_media_n_streams (GstRTSPMedia * media)
 GstRTSPStream *
 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
 {
+  GstRTSPMediaPrivate *priv;
   GstRTSPStream *res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
 
-  g_mutex_lock (&media->lock);
-  if (idx < media->streams->len)
-    res = g_ptr_array_index (media->streams, idx);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  if (idx < priv->streams->len)
+    res = g_ptr_array_index (priv->streams, idx);
   else
     res = NULL;
-  g_mutex_unlock (&media->lock);
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -800,25 +949,28 @@ gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
 gchar *
 gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play)
 {
+  GstRTSPMediaPrivate *priv;
   gchar *result;
   GstRTSPTimeRange range;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
 
-  g_rec_mutex_lock (&media->state_lock);
-  if (media->status != GST_RTSP_MEDIA_STATUS_PREPARED)
+  priv = media->priv;
+
+  g_rec_mutex_lock (&priv->state_lock);
+  if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
     goto not_prepared;
 
-  g_mutex_lock (&media->lock);
+  g_mutex_lock (&priv->lock);
   /* make copy */
-  range = media->range;
+  range = priv->range;
 
-  if (!play && media->n_active > 0) {
+  if (!play && priv->n_active > 0) {
     range.min.type = GST_RTSP_TIME_NOW;
     range.min.seconds = -1;
   }
-  g_mutex_unlock (&media->lock);
-  g_rec_mutex_unlock (&media->state_lock);
+  g_mutex_unlock (&priv->lock);
+  g_rec_mutex_unlock (&priv->state_lock);
 
   result = gst_rtsp_range_to_string (&range);
 
@@ -828,7 +980,7 @@ gst_rtsp_media_get_range_string (GstRTSPMedia * media, gboolean play)
 not_prepared:
   {
     GST_WARNING ("media %p was not prepared", media);
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     return NULL;
   }
 }
@@ -846,6 +998,7 @@ not_prepared:
 gboolean
 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
 {
+  GstRTSPMediaPrivate *priv;
   GstSeekFlags flags;
   gboolean res;
   GstClockTime start, stop;
@@ -854,11 +1007,13 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
   g_return_val_if_fail (range != NULL, FALSE);
 
-  g_rec_mutex_lock (&media->state_lock);
-  if (media->status != GST_RTSP_MEDIA_STATUS_PREPARED)
+  priv = media->priv;
+
+  g_rec_mutex_lock (&priv->state_lock);
+  if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
     goto not_prepared;
 
-  if (!media->seekable)
+  if (!priv->seekable)
     goto not_seekable;
 
   /* depends on the current playing state of the pipeline. We might need to
@@ -873,14 +1028,14 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
   GST_INFO ("got %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
       GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
   GST_INFO ("current %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (media->range_start), GST_TIME_ARGS (media->range_stop));
+      GST_TIME_ARGS (priv->range_start), GST_TIME_ARGS (priv->range_stop));
 
-  if (media->range_start == start)
+  if (priv->range_start == start)
     start = GST_CLOCK_TIME_NONE;
   else if (start != GST_CLOCK_TIME_NONE)
     start_type = GST_SEEK_TYPE_SET;
 
-  if (media->range_stop == stop)
+  if (priv->range_stop == stop)
     stop = GST_CLOCK_TIME_NONE;
   else if (stop != GST_CLOCK_TIME_NONE)
     stop_type = GST_SEEK_TYPE_SET;
@@ -889,12 +1044,12 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
     GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
         GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
 
-    res = gst_element_seek (media->pipeline, 1.0, GST_FORMAT_TIME,
+    res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
         flags, start_type, start, stop_type, stop);
 
     /* and block for the seek to complete */
     GST_INFO ("done seeking %d", res);
-    gst_element_get_state (media->pipeline, NULL, NULL, -1);
+    gst_element_get_state (priv->pipeline, NULL, NULL, -1);
     GST_INFO ("prerolled again");
 
     collect_media_stats (media);
@@ -902,26 +1057,26 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
     GST_INFO ("no seek needed");
     res = TRUE;
   }
-  g_rec_mutex_unlock (&media->state_lock);
+  g_rec_mutex_unlock (&priv->state_lock);
 
   return res;
 
   /* ERRORS */
 not_prepared:
   {
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     GST_INFO ("media %p is not prepared", media);
     return FALSE;
   }
 not_seekable:
   {
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     GST_INFO ("pipeline is not seekable");
     return TRUE;
   }
 not_supported:
   {
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     GST_WARNING ("seek unit %d not supported", range->unit);
     return FALSE;
   }
@@ -930,35 +1085,47 @@ not_supported:
 static void
 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
 {
-  g_mutex_lock (&media->lock);
+  GstRTSPMediaPrivate *priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
   /* never overwrite the error status */
-  if (media->status != GST_RTSP_MEDIA_STATUS_ERROR)
-    media->status = status;
+  if (priv->status != GST_RTSP_MEDIA_STATUS_ERROR)
+    priv->status = status;
   GST_DEBUG ("setting new status to %d", status);
-  g_cond_broadcast (&media->cond);
-  g_mutex_unlock (&media->lock);
+  g_cond_broadcast (&priv->cond);
+  g_mutex_unlock (&priv->lock);
 }
 
-static GstRTSPMediaStatus
+/**
+ * gst_rtsp_media_get_status:
+ * @media: a #GstRTSPMedia
+ *
+ * Get the status of @media. When @media is busy preparing, this function waits
+ * until @media is prepared or in error.
+ *
+ * Returns: the status of @media.
+ */
+GstRTSPMediaStatus
 gst_rtsp_media_get_status (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv = media->priv;
   GstRTSPMediaStatus result;
   gint64 end_time;
 
-  g_mutex_lock (&media->lock);
+  g_mutex_lock (&priv->lock);
   end_time = g_get_monotonic_time () + 20 * G_TIME_SPAN_SECOND;
   /* while we are preparing, wait */
-  while (media->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
+  while (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
     GST_DEBUG ("waiting for status change");
-    if (!g_cond_wait_until (&media->cond, &media->lock, end_time)) {
+    if (!g_cond_wait_until (&priv->cond, &priv->lock, end_time)) {
       GST_DEBUG ("timeout, assuming error status");
-      media->status = GST_RTSP_MEDIA_STATUS_ERROR;
+      priv->status = GST_RTSP_MEDIA_STATUS_ERROR;
     }
   }
   /* could be success or error */
-  result = media->status;
+  result = priv->status;
   GST_DEBUG ("got status %d", result);
-  g_mutex_unlock (&media->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -967,6 +1134,7 @@ gst_rtsp_media_get_status (GstRTSPMedia * media)
 static gboolean
 default_handle_message (GstRTSPMedia * media, GstMessage * message)
 {
+  GstRTSPMediaPrivate *priv = media->priv;
   GstMessageType type;
 
   type = GST_MESSAGE_TYPE (message);
@@ -981,37 +1149,37 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message)
       gst_message_parse_buffering (message, &percent);
 
       /* no state management needed for live pipelines */
-      if (media->is_live)
+      if (priv->is_live)
         break;
 
       if (percent == 100) {
         /* a 100% message means buffering is done */
-        media->buffering = FALSE;
+        priv->buffering = FALSE;
         /* if the desired state is playing, go back */
-        if (media->target_state == GST_STATE_PLAYING) {
+        if (priv->target_state == GST_STATE_PLAYING) {
           GST_INFO ("Buffering done, setting pipeline to PLAYING");
-          gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
+          gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
         } else {
           GST_INFO ("Buffering done");
         }
       } else {
         /* buffering busy */
-        if (media->buffering == FALSE) {
-          if (media->target_state == GST_STATE_PLAYING) {
+        if (priv->buffering == FALSE) {
+          if (priv->target_state == GST_STATE_PLAYING) {
             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
             GST_INFO ("Buffering, setting pipeline to PAUSED ...");
-            gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
+            gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
           } else {
             GST_INFO ("Buffering ...");
           }
         }
-        media->buffering = TRUE;
+        priv->buffering = TRUE;
       }
       break;
     }
     case GST_MESSAGE_LATENCY:
     {
-      gst_bin_recalculate_latency (GST_BIN_CAST (media->pipeline));
+      gst_bin_recalculate_latency (GST_BIN_CAST (priv->pipeline));
       break;
     }
     case GST_MESSAGE_ERROR:
@@ -1043,7 +1211,7 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message)
     case GST_MESSAGE_STREAM_STATUS:
       break;
     case GST_MESSAGE_ASYNC_DONE:
-      if (!media->adding) {
+      if (!priv->adding) {
         /* when we are dynamically adding pads, the addition of the udpsrc will
          * temporarily produce ASYNC_DONE messages. We have to ignore them and
          * wait for the final ASYNC_DONE after everything prerolled */
@@ -1058,7 +1226,7 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message)
     case GST_MESSAGE_EOS:
       GST_INFO ("%p: got EOS", media);
 
-      if (media->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
+      if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARING) {
         GST_DEBUG ("shutting down after EOS");
         finish_unprepare (media);
         g_object_unref (media);
@@ -1075,17 +1243,18 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message)
 static gboolean
 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv = media->priv;
   GstRTSPMediaClass *klass;
   gboolean ret;
 
   klass = GST_RTSP_MEDIA_GET_CLASS (media);
 
-  g_rec_mutex_lock (&media->state_lock);
+  g_rec_mutex_lock (&priv->state_lock);
   if (klass->handle_message)
     ret = klass->handle_message (media, message);
   else
     ret = FALSE;
-  g_rec_mutex_unlock (&media->state_lock);
+  g_rec_mutex_unlock (&priv->state_lock);
 
   return ret;
 }
@@ -1101,42 +1270,43 @@ watch_destroyed (GstRTSPMedia * media)
 static void
 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv = media->priv;
   GstRTSPStream *stream;
 
   /* FIXME, element is likely not a payloader, find the payloader here */
   stream = gst_rtsp_media_create_stream (media, element, pad);
 
-  GST_INFO ("pad added %s:%s, stream %d", GST_DEBUG_PAD_NAME (pad),
-      stream->idx);
+  GST_INFO ("pad added %s:%s, stream %s", GST_DEBUG_PAD_NAME (pad), stream);
 
-  g_rec_mutex_lock (&media->state_lock);
+  g_rec_mutex_lock (&priv->state_lock);
   /* we will be adding elements below that will cause ASYNC_DONE to be
    * posted in the bus. We want to ignore those messages until the
    * pipeline really prerolled. */
-  media->adding = TRUE;
+  priv->adding = TRUE;
 
   /* join the element in the PAUSED state because this callback is
    * called from the streaming thread and it is PAUSED */
-  gst_rtsp_stream_join_bin (stream, GST_BIN (media->pipeline),
-      media->rtpbin, GST_STATE_PAUSED);
+  gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
+      priv->rtpbin, GST_STATE_PAUSED);
 
-  media->adding = FALSE;
-  g_rec_mutex_unlock (&media->state_lock);
+  priv->adding = FALSE;
+  g_rec_mutex_unlock (&priv->state_lock);
 }
 
 static void
 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv = media->priv;
   GstElement *fakesink;
 
-  g_mutex_lock (&media->lock);
+  g_mutex_lock (&priv->lock);
   GST_INFO ("no more pads");
-  if ((fakesink = media->fakesink)) {
+  if ((fakesink = priv->fakesink)) {
     gst_object_ref (fakesink);
-    media->fakesink = NULL;
-    g_mutex_unlock (&media->lock);
+    priv->fakesink = NULL;
+    g_mutex_unlock (&priv->lock);
 
-    gst_bin_remove (GST_BIN (media->pipeline), fakesink);
+    gst_bin_remove (GST_BIN (priv->pipeline), fakesink);
     gst_element_set_state (fakesink, GST_STATE_NULL);
     gst_object_unref (fakesink);
     GST_INFO ("removed fakesink");
@@ -1158,6 +1328,7 @@ no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
 gboolean
 gst_rtsp_media_prepare (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   GstStateChangeReturn ret;
   GstRTSPMediaStatus status;
   guint i;
@@ -1167,59 +1338,61 @@ gst_rtsp_media_prepare (GstRTSPMedia * media)
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
 
-  g_rec_mutex_lock (&media->state_lock);
-  if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED)
+  priv = media->priv;
+
+  g_rec_mutex_lock (&priv->state_lock);
+  if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED)
     goto was_prepared;
 
-  if (media->status == GST_RTSP_MEDIA_STATUS_PREPARING)
+  if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
     goto wait_status;
 
-  if (media->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
+  if (priv->status != GST_RTSP_MEDIA_STATUS_UNPREPARED)
     goto not_unprepared;
 
-  if (!media->reusable && media->reused)
+  if (!priv->reusable && priv->reused)
     goto is_reused;
 
-  media->rtpbin = gst_element_factory_make ("rtpbin", NULL);
-  if (media->rtpbin == NULL)
+  priv->rtpbin = gst_element_factory_make ("rtpbin", NULL);
+  if (priv->rtpbin == NULL)
     goto no_rtpbin;
 
   GST_INFO ("preparing media %p", media);
 
   /* reset some variables */
-  media->is_live = FALSE;
-  media->seekable = FALSE;
-  media->buffering = FALSE;
+  priv->is_live = FALSE;
+  priv->seekable = FALSE;
+  priv->buffering = FALSE;
   /* we're preparing now */
-  media->status = GST_RTSP_MEDIA_STATUS_PREPARING;
+  priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
 
-  bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (media->pipeline));
+  bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (priv->pipeline));
 
   /* add the pipeline bus to our custom mainloop */
-  media->source = gst_bus_create_watch (bus);
+  priv->source = gst_bus_create_watch (bus);
   gst_object_unref (bus);
 
-  g_source_set_callback (media->source, (GSourceFunc) bus_message,
+  g_source_set_callback (priv->source, (GSourceFunc) bus_message,
       gst_object_ref (media), (GDestroyNotify) watch_destroyed);
 
   klass = GST_RTSP_MEDIA_GET_CLASS (media);
-  media->id = g_source_attach (media->source, klass->context);
+  priv->id = g_source_attach (priv->source, klass->context);
 
   /* add stuff to the bin */
-  gst_bin_add (GST_BIN (media->pipeline), media->rtpbin);
+  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 < media->streams->len; i++) {
+  for (i = 0; i < priv->streams->len; i++) {
     GstRTSPStream *stream;
 
-    stream = g_ptr_array_index (media->streams, i);
+    stream = g_ptr_array_index (priv->streams, i);
 
-    gst_rtsp_stream_join_bin (stream, GST_BIN (media->pipeline),
-        media->rtpbin, GST_STATE_NULL);
+    gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
+        priv->rtpbin, GST_STATE_NULL);
   }
 
-  for (walk = media->dynamic; walk; walk = g_list_next (walk)) {
+  for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
     GstElement *elem = walk->data;
 
     GST_INFO ("adding callbacks for dynamic element %p", elem);
@@ -1229,32 +1402,32 @@ gst_rtsp_media_prepare (GstRTSPMedia * media)
 
     /* we add a fakesink here in order to make the state change async. We remove
      * the fakesink again in the no-more-pads callback. */
-    media->fakesink = gst_element_factory_make ("fakesink", "fakesink");
-    gst_bin_add (GST_BIN (media->pipeline), media->fakesink);
+    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 (media->pipeline, GST_STATE_PAUSED);
-  media->target_state = GST_STATE_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);
-      media->seekable = TRUE;
+      priv->seekable = TRUE;
       break;
     case GST_STATE_CHANGE_ASYNC:
       GST_INFO ("ASYNC state change for media %p", media);
-      media->seekable = TRUE;
+      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 */
-      media->seekable = FALSE;
-      media->is_live = TRUE;
-      ret = gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
+      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;
@@ -1262,7 +1435,7 @@ gst_rtsp_media_prepare (GstRTSPMedia * media)
       goto state_failed;
   }
 wait_status:
-  g_rec_mutex_unlock (&media->state_lock);
+  g_rec_mutex_unlock (&priv->state_lock);
 
   /* 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. */
@@ -1280,25 +1453,25 @@ wait_status:
 was_prepared:
   {
     GST_LOG ("media %p was prepared", media);
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     return TRUE;
   }
   /* ERRORS */
 not_unprepared:
   {
     GST_WARNING ("media %p was not unprepared", media);
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     return FALSE;
   }
 is_reused:
   {
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     GST_WARNING ("can not reuse media %p", media);
     return FALSE;
   }
 no_rtpbin:
   {
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     GST_WARNING ("no rtpbin element");
     g_warning ("failed to create element 'rtpbin', check your installation");
     return FALSE;
@@ -1307,7 +1480,7 @@ state_failed:
   {
     GST_WARNING ("failed to preroll pipeline");
     gst_rtsp_media_unprepare (media);
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     return FALSE;
   }
 }
@@ -1316,37 +1489,37 @@ state_failed:
 static void
 finish_unprepare (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv = media->priv;
   gint i;
 
   GST_DEBUG ("shutting down");
 
-  gst_element_set_state (media->pipeline, GST_STATE_NULL);
+  gst_element_set_state (priv->pipeline, GST_STATE_NULL);
 
-  for (i = 0; i < media->streams->len; i++) {
+  for (i = 0; i < priv->streams->len; i++) {
     GstRTSPStream *stream;
 
     GST_INFO ("Removing elements of stream %d from pipeline", i);
 
-    stream = g_ptr_array_index (media->streams, i);
+    stream = g_ptr_array_index (priv->streams, i);
 
-    gst_rtsp_stream_leave_bin (stream, GST_BIN (media->pipeline),
-        media->rtpbin);
+    gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin);
   }
-  g_ptr_array_set_size (media->streams, 0);
+  g_ptr_array_set_size (priv->streams, 0);
 
-  gst_bin_remove (GST_BIN (media->pipeline), media->rtpbin);
-  media->rtpbin = NULL;
+  gst_bin_remove (GST_BIN (priv->pipeline), priv->rtpbin);
+  priv->rtpbin = NULL;
 
-  gst_object_unref (media->pipeline);
-  media->pipeline = NULL;
+  gst_object_unref (priv->pipeline);
+  priv->pipeline = NULL;
 
-  media->reused = TRUE;
-  media->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
+  priv->reused = TRUE;
+  priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
 
-  if (media->source) {
-    g_source_destroy (media->source);
-    g_source_unref (media->source);
-    media->source = NULL;
+  if (priv->source) {
+    g_source_destroy (priv->source);
+    g_source_unref (priv->source);
+    priv->source = NULL;
   }
 
   /* when the media is not reusable, this will effectively unref the media and
@@ -1358,15 +1531,17 @@ finish_unprepare (GstRTSPMedia * media)
 static gboolean
 default_unprepare (GstRTSPMedia * media)
 {
-  if (media->eos_shutdown) {
+  GstRTSPMediaPrivate *priv = media->priv;
+
+  if (priv->eos_shutdown) {
     GST_DEBUG ("sending EOS for shutdown");
     /* ref so that we don't disappear */
     g_object_ref (media);
-    gst_element_send_event (media->pipeline, gst_event_new_eos ());
+    gst_element_send_event (priv->pipeline, gst_event_new_eos ());
     /* we need to go to playing again for the EOS to propagate, normally in this
      * state, nothing is receiving data from us anymore so this is ok. */
-    gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
-    media->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
+    gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
+    priv->status = GST_RTSP_MEDIA_STATUS_UNPREPARING;
   } else {
     finish_unprepare (media);
   }
@@ -1386,19 +1561,22 @@ default_unprepare (GstRTSPMedia * media)
 gboolean
 gst_rtsp_media_unprepare (GstRTSPMedia * media)
 {
+  GstRTSPMediaPrivate *priv;
   gboolean success;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
 
-  g_rec_mutex_lock (&media->state_lock);
-  if (media->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
+  priv = media->priv;
+
+  g_rec_mutex_lock (&priv->state_lock);
+  if (priv->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
     goto was_unprepared;
 
   GST_INFO ("unprepare media %p", media);
-  media->target_state = GST_STATE_NULL;
+  priv->target_state = GST_STATE_NULL;
   success = TRUE;
 
-  if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
+  if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) {
     GstRTSPMediaClass *klass;
 
     klass = GST_RTSP_MEDIA_GET_CLASS (media);
@@ -1407,13 +1585,13 @@ gst_rtsp_media_unprepare (GstRTSPMedia * media)
   } else {
     finish_unprepare (media);
   }
-  g_rec_mutex_unlock (&media->state_lock);
+  g_rec_mutex_unlock (&priv->state_lock);
 
   return success;
 
 was_unprepared:
   {
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     GST_INFO ("media %p was already unprepared", media);
     return TRUE;
   }
@@ -1435,22 +1613,25 @@ gboolean
 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
     GPtrArray * transports)
 {
+  GstRTSPMediaPrivate *priv;
   gint i;
-  gboolean add, remove, do_state;
+  gboolean activate, deactivate, 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_rec_mutex_lock (&media->state_lock);
-  if (media->status != GST_RTSP_MEDIA_STATUS_PREPARED)
+  priv = media->priv;
+
+  g_rec_mutex_lock (&priv->state_lock);
+  if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
     goto not_prepared;
 
   /* NULL and READY are the same */
   if (state == GST_STATE_READY)
     state = GST_STATE_NULL;
 
-  add = remove = FALSE;
+  activate = deactivate = FALSE;
 
   GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
       media);
@@ -1458,18 +1639,18 @@ gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
   switch (state) {
     case GST_STATE_NULL:
     case GST_STATE_PAUSED:
-      /* we're going from PLAYING to PAUSED, READY or NULL, remove */
-      if (media->target_state == GST_STATE_PLAYING)
-        remove = TRUE;
+      /* we're going from PLAYING to PAUSED, READY or NULL, deactivate */
+      if (priv->target_state == GST_STATE_PLAYING)
+        deactivate = TRUE;
       break;
     case GST_STATE_PLAYING:
-      /* we're going to PLAYING, add */
-      add = TRUE;
+      /* we're going to PLAYING, activate */
+      activate = TRUE;
       break;
     default:
       break;
   }
-  old_active = media->n_active;
+  old_active = priv->n_active;
 
   for (i = 0; i < transports->len; i++) {
     GstRTSPStreamTransport *trans;
@@ -1479,40 +1660,36 @@ gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
     if (trans == NULL)
       continue;
 
-    /* we need a transport */
-    if (!trans->transport)
-      continue;
-
-    if (add) {
-      if (gst_rtsp_stream_add_transport (trans->stream, trans))
-        media->n_active++;
-    } else if (remove) {
-      if (gst_rtsp_stream_remove_transport (trans->stream, trans))
-        media->n_active--;
+    if (activate) {
+      if (gst_rtsp_stream_transport_set_active (trans, TRUE))
+        priv->n_active++;
+    } else if (deactivate) {
+      if (gst_rtsp_stream_transport_set_active (trans, FALSE))
+        priv->n_active--;
     }
   }
 
-  /* we just added the first media, do the playing state change */
-  if (old_active == 0 && add)
+  /* we just activated the first media, do the playing state change */
+  if (old_active == 0 && activate)
     do_state = TRUE;
   /* if we have no more active media, do the downward state changes */
-  else if (media->n_active == 0)
+  else if (priv->n_active == 0)
     do_state = TRUE;
   else
     do_state = FALSE;
 
-  GST_INFO ("state %d active %d media %p do_state %d", state, media->n_active,
+  GST_INFO ("state %d active %d media %p do_state %d", state, priv->n_active,
       media, do_state);
 
-  if (media->target_state != state) {
+  if (priv->target_state != state) {
     if (do_state) {
       if (state == GST_STATE_NULL) {
         gst_rtsp_media_unprepare (media);
       } else {
         GST_INFO ("state %s media %p", gst_element_state_get_name (state),
             media);
-        media->target_state = state;
-        gst_element_set_state (media->pipeline, state);
+        priv->target_state = state;
+        gst_element_set_state (priv->pipeline, state);
       }
     }
     g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state,
@@ -1521,10 +1698,10 @@ gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
 
   /* remember where we are */
   if (state != GST_STATE_NULL && (state == GST_STATE_PAUSED ||
-          old_active != media->n_active))
+          old_active != priv->n_active))
     collect_media_stats (media);
 
-  g_rec_mutex_unlock (&media->state_lock);
+  g_rec_mutex_unlock (&priv->state_lock);
 
   return TRUE;
 
@@ -1532,7 +1709,7 @@ gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
 not_prepared:
   {
     GST_WARNING ("media %p was not prepared", media);
-    g_rec_mutex_unlock (&media->state_lock);
+    g_rec_mutex_unlock (&priv->state_lock);
     return FALSE;
   }
 }
index 64cda5e..230806b 100644 (file)
@@ -38,6 +38,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPMedia GstRTSPMedia;
 typedef struct _GstRTSPMediaClass GstRTSPMediaClass;
+typedef struct _GstRTSPMediaPrivate GstRTSPMediaPrivate;
 
 #include "rtsp-stream.h"
 #include "rtsp-auth.h"
@@ -64,36 +65,6 @@ typedef enum {
 
 /**
  * GstRTSPMedia:
- * @parent: parent GObject
- * @lock: for protecting the object
- * @cond: for signaling the object
- * @shared: if this media can be shared between clients
- * @reusable: if this media can be reused after an unprepare
- * @protocols: the allowed lower transport for this stream
- * @reused: if this media has been reused
- * @is_ipv6: if this media is using ipv6
- * @eos_shutdown: if EOS should be sent on shutdown
- * @buffer_size: The UDP buffer size
- * @auth: the authentication service in use
- * @multicast_group: the multicast group to use
- * @element: the data providing element, owned by @pipeline
- * @streams: the different #GstRTSPStream provided by @element
- * @dynamic: list of dynamic elements managed by @element
- * @status: the status of the media pipeline
- * @n_active: the number of active connections
- * @adding: when elements are added to the pipeline
- * @pipeline: the toplevel pipeline
- * @fakesink: for making state changes async
- * @source: the bus watch for pipeline messages.
- * @id: the id of the watch
- * @is_live: if the pipeline is live
- * @seekable: if the pipeline can perform a seek
- * @buffering: if the pipeline is buffering
- * @target_state: the desired target state of the pipeline
- * @rtpbin: the rtpbin
- * @range: the range of the media being streamed
- * @range_start: range start in #GstClockTime
- * @range_stop: range stop in #GstClockTime
  *
  * A class that contains the GStreamer element along with a list of
  * #GstRTSPStream objects that can produce data.
@@ -103,45 +74,7 @@ typedef enum {
 struct _GstRTSPMedia {
   GObject            parent;
 
-  GMutex             lock;
-  GCond              cond;
-
-  gboolean           shared;
-  gboolean           reusable;
-  GstRTSPLowerTrans  protocols;
-  gboolean           reused;
-  gboolean           is_ipv6;
-  gboolean           eos_shutdown;
-  guint              buffer_size;
-  GstRTSPAuth       *auth;
-  GstRTSPAddressPool*pool;
-
-  GstElement        *element;
-  GRecMutex          state_lock;
-  GPtrArray         *streams;
-  GList             *dynamic;
-  GstRTSPMediaStatus status;
-  gint               n_active;
-  gboolean           adding;
-
-  /* the pipeline for the media */
-  GstElement        *pipeline;
-  GstElement        *fakesink;
-  GSource           *source;
-  guint              id;
-
-  gboolean           is_live;
-  gboolean           seekable;
-  gboolean           buffering;
-  GstState           target_state;
-
-  /* RTP session manager */
-  GstElement        *rtpbin;
-
-  /* the range of media */
-  GstRTSPTimeRange   range;
-  GstClockTime       range_start;
-  GstClockTime       range_stop;
+  GstRTSPMediaPrivate *priv;
 };
 
 /**
@@ -179,7 +112,11 @@ struct _GstRTSPMediaClass {
 GType                 gst_rtsp_media_get_type         (void);
 
 /* creating the media */
-GstRTSPMedia *        gst_rtsp_media_new              (void);
+GstRTSPMedia *        gst_rtsp_media_new              (GstElement *element);
+
+void                  gst_rtsp_media_take_pipeline    (GstRTSPMedia *media, GstPipeline *pipeline);
+
+GstRTSPMediaStatus    gst_rtsp_media_get_status       (GstRTSPMedia *media);
 
 void                  gst_rtsp_media_set_shared       (GstRTSPMedia *media, gboolean shared);
 gboolean              gst_rtsp_media_is_shared        (GstRTSPMedia *media);
index 3a92d55..c18cb63 100644 (file)
 
 #include "rtsp-mount-points.h"
 
+#define GST_RTSP_MOUNT_POINTS_GET_PRIVATE(obj)  \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MOUNT_POINTS, GstRTSPMountPointsPrivate))
+
+struct _GstRTSPMountPointsPrivate
+{
+  GMutex lock;
+  GHashTable *mounts;
+};
+
 G_DEFINE_TYPE (GstRTSPMountPoints, gst_rtsp_mount_points, G_TYPE_OBJECT);
 
 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
@@ -34,6 +43,8 @@ gst_rtsp_mount_points_class_init (GstRTSPMountPointsClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPMountPointsPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->finalize = gst_rtsp_mount_points_finalize;
@@ -47,10 +58,14 @@ gst_rtsp_mount_points_class_init (GstRTSPMountPointsClass * klass)
 static void
 gst_rtsp_mount_points_init (GstRTSPMountPoints * mounts)
 {
+  GstRTSPMountPointsPrivate *priv = GST_RTSP_MOUNT_POINTS_GET_PRIVATE (mounts);
+
   GST_DEBUG_OBJECT (mounts, "created");
 
-  g_mutex_init (&mounts->lock);
-  mounts->mounts = g_hash_table_new_full (g_str_hash, g_str_equal,
+  mounts->priv = priv;
+
+  g_mutex_init (&priv->lock);
+  priv->mounts = g_hash_table_new_full (g_str_hash, g_str_equal,
       g_free, g_object_unref);
 }
 
@@ -58,11 +73,12 @@ static void
 gst_rtsp_mount_points_finalize (GObject * obj)
 {
   GstRTSPMountPoints *mounts = GST_RTSP_MOUNT_POINTS (obj);
+  GstRTSPMountPointsPrivate *priv = mounts->priv;
 
   GST_DEBUG_OBJECT (mounts, "finalized");
 
-  g_hash_table_unref (mounts->mounts);
-  g_mutex_clear (&mounts->lock);
+  g_hash_table_unref (priv->mounts);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_mount_points_parent_class)->finalize (obj);
 }
@@ -87,16 +103,17 @@ gst_rtsp_mount_points_new (void)
 static GstRTSPMediaFactory *
 find_factory (GstRTSPMountPoints * mounts, const GstRTSPUrl * url)
 {
+  GstRTSPMountPointsPrivate *priv = mounts->priv;
   GstRTSPMediaFactory *result;
 
-  g_mutex_lock (&mounts->lock);
+  g_mutex_lock (&priv->lock);
   /* find the location of the media in the hashtable we only use the absolute
    * path of the uri to find a media factory. If the factory depends on other
    * properties found in the url, this method should be overridden. */
-  result = g_hash_table_lookup (mounts->mounts, url->abspath);
+  result = g_hash_table_lookup (priv->mounts, url->abspath);
   if (result)
     g_object_ref (result);
-  g_mutex_unlock (&mounts->lock);
+  g_mutex_unlock (&priv->lock);
 
   GST_INFO ("found media factory %p for url abspath %s", result, url->abspath);
 
@@ -150,13 +167,17 @@ void
 gst_rtsp_mount_points_add_factory (GstRTSPMountPoints * mounts,
     const gchar * path, GstRTSPMediaFactory * factory)
 {
+  GstRTSPMountPointsPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts));
   g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
   g_return_if_fail (path != NULL);
 
-  g_mutex_lock (&mounts->lock);
-  g_hash_table_insert (mounts->mounts, g_strdup (path), factory);
-  g_mutex_unlock (&mounts->lock);
+  priv = mounts->priv;
+
+  g_mutex_lock (&priv->lock);
+  g_hash_table_insert (priv->mounts, g_strdup (path), factory);
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -170,10 +191,14 @@ void
 gst_rtsp_mount_points_remove_factory (GstRTSPMountPoints * mounts,
     const gchar * path)
 {
+  GstRTSPMountPointsPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts));
   g_return_if_fail (path != NULL);
 
-  g_mutex_lock (&mounts->lock);
-  g_hash_table_remove (mounts->mounts, path);
-  g_mutex_unlock (&mounts->lock);
+  priv = mounts->priv;
+
+  g_mutex_lock (&priv->lock);
+  g_hash_table_remove (priv->mounts, path);
+  g_mutex_unlock (&priv->lock);
 }
index 3ab6016..d8dd1b8 100644 (file)
@@ -39,6 +39,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPMountPoints GstRTSPMountPoints;
 typedef struct _GstRTSPMountPointsClass GstRTSPMountPointsClass;
+typedef struct _GstRTSPMountPointsPrivate GstRTSPMountPointsPrivate;
 
 /**
  * GstRTSPMountPoints:
@@ -50,8 +51,7 @@ typedef struct _GstRTSPMountPointsClass GstRTSPMountPointsClass;
 struct _GstRTSPMountPoints {
   GObject       parent;
 
-  GMutex        lock;
-  GHashTable   *mounts;
+  GstRTSPMountPointsPrivate *priv;
 };
 
 /**
index 14ba38e..847b487 100644 (file)
@@ -38,12 +38,12 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
   guint i, n_streams;
   gchar *rangestr;
 
-  if (media->status != GST_RTSP_MEDIA_STATUS_PREPARED)
-    goto not_prepared;
-
   n_streams = gst_rtsp_media_n_streams (media);
 
   rangestr = gst_rtsp_media_get_range_string (media, FALSE);
+  if (rangestr == NULL)
+    goto not_prepared;
+
   gst_sdp_message_add_attribute (sdp, "range", rangestr);
   g_free (rangestr);
 
@@ -57,16 +57,19 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
     guint n_fields, j;
     gboolean first;
     GString *fmtp;
+    GstCaps *caps;
 
     stream = gst_rtsp_media_get_stream (media, i);
+    caps = gst_rtsp_stream_get_caps (stream);
 
-    if (stream->caps == NULL) {
+    if (caps == NULL) {
       g_warning ("ignoring stream %d without media type", i);
       continue;
     }
 
-    s = gst_caps_get_structure (stream->caps, 0);
+    s = gst_caps_get_structure (caps, 0);
     if (s == NULL) {
+      gst_caps_unref (caps);
       g_warning ("ignoring stream %d without media type", i);
       continue;
     }
@@ -152,6 +155,7 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
     }
     gst_sdp_message_add_media (sdp, smedia);
     gst_sdp_media_free (smedia);
+    gst_caps_unref (caps);
   }
 
   return TRUE;
index dfd4de8..f66b23a 100644 (file)
 #include "rtsp-server.h"
 #include "rtsp-client.h"
 
+#define GST_RTSP_SERVER_GET_PRIVATE(obj)  \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SERVER, GstRTSPServerPrivate))
+
+#define GST_RTSP_SERVER_GET_LOCK(server)  (&(GST_RTSP_SERVER_CAST(server)->priv->lock))
+#define GST_RTSP_SERVER_LOCK(server)      (g_mutex_lock(GST_RTSP_SERVER_GET_LOCK(server)))
+#define GST_RTSP_SERVER_UNLOCK(server)    (g_mutex_unlock(GST_RTSP_SERVER_GET_LOCK(server)))
+
+struct _GstRTSPServerPrivate
+{
+  GMutex lock;
+
+  /* server information */
+  gchar *address;
+  gchar *service;
+  gint backlog;
+  gint max_threads;
+
+  GSocket *socket;
+
+  /* sessions on this server */
+  GstRTSPSessionPool *session_pool;
+
+  /* mount points for this server */
+  GstRTSPMountPoints *mount_points;
+
+  /* authentication manager */
+  GstRTSPAuth *auth;
+
+  /* the clients that are connected */
+  GList *clients;
+};
+
 #define DEFAULT_ADDRESS         "0.0.0.0"
 #define DEFAULT_BOUND_PORT      -1
 /* #define DEFAULT_ADDRESS         "::0" */
@@ -80,6 +112,8 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPServerPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->get_property = gst_rtsp_server_get_property;
@@ -185,36 +219,41 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
 static void
 gst_rtsp_server_init (GstRTSPServer * server)
 {
-  g_mutex_init (&server->lock);
-  server->address = g_strdup (DEFAULT_ADDRESS);
-  server->service = g_strdup (DEFAULT_SERVICE);
-  server->socket = NULL;
-  server->backlog = DEFAULT_BACKLOG;
-  server->session_pool = gst_rtsp_session_pool_new ();
-  server->mount_points = gst_rtsp_mount_points_new ();
-  server->max_threads = DEFAULT_MAX_THREADS;
+  GstRTSPServerPrivate *priv = GST_RTSP_SERVER_GET_PRIVATE (server);
+
+  server->priv = priv;
+
+  g_mutex_init (&priv->lock);
+  priv->address = g_strdup (DEFAULT_ADDRESS);
+  priv->service = g_strdup (DEFAULT_SERVICE);
+  priv->socket = NULL;
+  priv->backlog = DEFAULT_BACKLOG;
+  priv->session_pool = gst_rtsp_session_pool_new ();
+  priv->mount_points = gst_rtsp_mount_points_new ();
+  priv->max_threads = DEFAULT_MAX_THREADS;
 }
 
 static void
 gst_rtsp_server_finalize (GObject * object)
 {
   GstRTSPServer *server = GST_RTSP_SERVER (object);
+  GstRTSPServerPrivate *priv = server->priv;
 
   GST_DEBUG_OBJECT (server, "finalize server");
 
-  g_free (server->address);
-  g_free (server->service);
+  g_free (priv->address);
+  g_free (priv->service);
 
-  if (server->socket)
-    g_object_unref (server->socket);
+  if (priv->socket)
+    g_object_unref (priv->socket);
 
-  g_object_unref (server->session_pool);
-  g_object_unref (server->mount_points);
+  g_object_unref (priv->session_pool);
+  g_object_unref (priv->mount_points);
 
-  if (server->auth)
-    g_object_unref (server->auth);
+  if (priv->auth)
+    g_object_unref (priv->auth);
 
-  g_mutex_clear (&server->lock);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_server_parent_class)->finalize (object);
 }
@@ -246,12 +285,16 @@ gst_rtsp_server_new (void)
 void
 gst_rtsp_server_set_address (GstRTSPServer * server, const gchar * address)
 {
+  GstRTSPServerPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_SERVER (server));
   g_return_if_fail (address != NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  g_free (server->address);
-  server->address = g_strdup (address);
+  g_free (priv->address);
+  priv->address = g_strdup (address);
   GST_RTSP_SERVER_UNLOCK (server);
 }
 
@@ -266,11 +309,15 @@ gst_rtsp_server_set_address (GstRTSPServer * server, const gchar * address)
 gchar *
 gst_rtsp_server_get_address (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   gchar *result;
+
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  result = g_strdup (server->address);
+  result = g_strdup (priv->address);
   GST_RTSP_SERVER_UNLOCK (server);
 
   return result;
@@ -287,16 +334,19 @@ gst_rtsp_server_get_address (GstRTSPServer * server)
 int
 gst_rtsp_server_get_bound_port (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   GSocketAddress *address;
   int result = -1;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), result);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  if (server->socket == NULL)
+  if (priv->socket == NULL)
     goto out;
 
-  address = g_socket_get_local_address (server->socket, NULL);
+  address = g_socket_get_local_address (priv->socket, NULL);
   result = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
   g_object_unref (address);
 
@@ -320,12 +370,16 @@ out:
 void
 gst_rtsp_server_set_service (GstRTSPServer * server, const gchar * service)
 {
+  GstRTSPServerPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_SERVER (server));
   g_return_if_fail (service != NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  g_free (server->service);
-  server->service = g_strdup (service);
+  g_free (priv->service);
+  priv->service = g_strdup (service);
   GST_RTSP_SERVER_UNLOCK (server);
 }
 
@@ -340,12 +394,15 @@ gst_rtsp_server_set_service (GstRTSPServer * server, const gchar * service)
 gchar *
 gst_rtsp_server_get_service (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   gchar *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  result = g_strdup (server->service);
+  result = g_strdup (priv->service);
   GST_RTSP_SERVER_UNLOCK (server);
 
   return result;
@@ -364,10 +421,14 @@ gst_rtsp_server_get_service (GstRTSPServer * server)
 void
 gst_rtsp_server_set_backlog (GstRTSPServer * server, gint backlog)
 {
+  GstRTSPServerPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_SERVER (server));
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  server->backlog = backlog;
+  priv->backlog = backlog;
   GST_RTSP_SERVER_UNLOCK (server);
 }
 
@@ -382,12 +443,15 @@ gst_rtsp_server_set_backlog (GstRTSPServer * server, gint backlog)
 gint
 gst_rtsp_server_get_backlog (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   gint result;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), -1);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  result = server->backlog;
+  result = priv->backlog;
   GST_RTSP_SERVER_UNLOCK (server);
 
   return result;
@@ -404,16 +468,19 @@ void
 gst_rtsp_server_set_session_pool (GstRTSPServer * server,
     GstRTSPSessionPool * pool)
 {
+  GstRTSPServerPrivate *priv;
   GstRTSPSessionPool *old;
 
   g_return_if_fail (GST_IS_RTSP_SERVER (server));
 
+  priv = server->priv;
+
   if (pool)
     g_object_ref (pool);
 
   GST_RTSP_SERVER_LOCK (server);
-  old = server->session_pool;
-  server->session_pool = pool;
+  old = priv->session_pool;
+  priv->session_pool = pool;
   GST_RTSP_SERVER_UNLOCK (server);
 
   if (old)
@@ -432,12 +499,15 @@ gst_rtsp_server_set_session_pool (GstRTSPServer * server,
 GstRTSPSessionPool *
 gst_rtsp_server_get_session_pool (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   GstRTSPSessionPool *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  if ((result = server->session_pool))
+  if ((result = priv->session_pool))
     g_object_ref (result);
   GST_RTSP_SERVER_UNLOCK (server);
 
@@ -455,16 +525,19 @@ void
 gst_rtsp_server_set_mount_points (GstRTSPServer * server,
     GstRTSPMountPoints * mounts)
 {
+  GstRTSPServerPrivate *priv;
   GstRTSPMountPoints *old;
 
   g_return_if_fail (GST_IS_RTSP_SERVER (server));
 
+  priv = server->priv;
+
   if (mounts)
     g_object_ref (mounts);
 
   GST_RTSP_SERVER_LOCK (server);
-  old = server->mount_points;
-  server->mount_points = mounts;
+  old = priv->mount_points;
+  priv->mount_points = mounts;
   GST_RTSP_SERVER_UNLOCK (server);
 
   if (old)
@@ -484,12 +557,15 @@ gst_rtsp_server_set_mount_points (GstRTSPServer * server,
 GstRTSPMountPoints *
 gst_rtsp_server_get_mount_points (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   GstRTSPMountPoints *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  if ((result = server->mount_points))
+  if ((result = priv->mount_points))
     g_object_ref (result);
   GST_RTSP_SERVER_UNLOCK (server);
 
@@ -506,16 +582,19 @@ gst_rtsp_server_get_mount_points (GstRTSPServer * server)
 void
 gst_rtsp_server_set_auth (GstRTSPServer * server, GstRTSPAuth * auth)
 {
+  GstRTSPServerPrivate *priv;
   GstRTSPAuth *old;
 
   g_return_if_fail (GST_IS_RTSP_SERVER (server));
 
+  priv = server->priv;
+
   if (auth)
     g_object_ref (auth);
 
   GST_RTSP_SERVER_LOCK (server);
-  old = server->auth;
-  server->auth = auth;
+  old = priv->auth;
+  priv->auth = auth;
   GST_RTSP_SERVER_UNLOCK (server);
 
   if (old)
@@ -535,12 +614,15 @@ gst_rtsp_server_set_auth (GstRTSPServer * server, GstRTSPAuth * auth)
 GstRTSPAuth *
 gst_rtsp_server_get_auth (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   GstRTSPAuth *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  if ((result = server->auth))
+  if ((result = priv->auth))
     g_object_ref (result);
   GST_RTSP_SERVER_UNLOCK (server);
 
@@ -559,10 +641,14 @@ gst_rtsp_server_get_auth (GstRTSPServer * server)
 void
 gst_rtsp_server_set_max_threads (GstRTSPServer * server, gint max_threads)
 {
+  GstRTSPServerPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_SERVER (server));
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  server->max_threads = max_threads;
+  priv->max_threads = max_threads;
   GST_RTSP_SERVER_UNLOCK (server);
 }
 
@@ -578,12 +664,15 @@ gst_rtsp_server_set_max_threads (GstRTSPServer * server, gint max_threads)
 gint
 gst_rtsp_server_get_max_threads (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv;
   gint res;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), -1);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  res = server->max_threads;
+  res = priv->max_threads;
   GST_RTSP_SERVER_UNLOCK (server);
 
   return res;
@@ -668,6 +757,7 @@ GSocket *
 gst_rtsp_server_create_socket (GstRTSPServer * server,
     GCancellable * cancellable, GError ** error)
 {
+  GstRTSPServerPrivate *priv;
   GSocketConnectable *conn;
   GSocketAddressEnumerator *enumerator;
   GSocket *socket = NULL;
@@ -680,16 +770,18 @@ gst_rtsp_server_create_socket (GstRTSPServer * server,
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
 
+  priv = server->priv;
+
   GST_RTSP_SERVER_LOCK (server);
-  GST_DEBUG_OBJECT (server, "getting address info of %s/%s", server->address,
-      server->service);
+  GST_DEBUG_OBJECT (server, "getting address info of %s/%s", priv->address,
+      priv->service);
 
   /* resolve the server IP address */
-  port = atoi (server->service);
-  if (port != 0 || !strcmp (server->service, "0"))
-    conn = g_network_address_new (server->address, port);
+  port = atoi (priv->service);
+  if (port != 0 || !strcmp (priv->service, "0"))
+    conn = g_network_address_new (priv->address, port);
   else
-    conn = g_network_service_new (server->service, "tcp", server->address);
+    conn = g_network_service_new (priv->service, "tcp", priv->address);
 
   enumerator = g_socket_connectable_enumerate (conn);
   g_object_unref (conn);
@@ -764,13 +856,13 @@ gst_rtsp_server_create_socket (GstRTSPServer * server,
   g_socket_set_blocking (socket, FALSE);
 
   /* set listen backlog */
-  g_socket_set_listen_backlog (socket, server->backlog);
+  g_socket_set_listen_backlog (socket, priv->backlog);
 
   if (!g_socket_listen (socket, error))
     goto listen_failed;
 
   GST_DEBUG_OBJECT (server, "listening on server socket %p with queue of %d",
-      socket, server->backlog);
+      socket, priv->backlog);
 
   GST_RTSP_SERVER_UNLOCK (server);
 
@@ -854,13 +946,14 @@ static void
 unmanage_client (GstRTSPClient * client, ClientContext * ctx)
 {
   GstRTSPServer *server = ctx->server;
+  GstRTSPServerPrivate *priv = server->priv;
 
   GST_DEBUG_OBJECT (server, "unmanage client %p", client);
 
   g_object_ref (server);
 
   GST_RTSP_SERVER_LOCK (server);
-  server->clients = g_list_remove (server->clients, ctx);
+  priv->clients = g_list_remove (priv->clients, ctx);
   GST_RTSP_SERVER_UNLOCK (server);
 
   if (ctx->loop)
@@ -877,13 +970,14 @@ static void
 manage_client (GstRTSPServer * server, GstRTSPClient * client)
 {
   ClientContext *ctx;
+  GstRTSPServerPrivate *priv = server->priv;
 
   GST_DEBUG_OBJECT (server, "manage client %p", client);
 
   ctx = g_slice_new0 (ClientContext);
   ctx->server = server;
   ctx->client = client;
-  if (server->max_threads == 0) {
+  if (priv->max_threads == 0) {
     GSource *source;
 
     /* find the context to add the watch */
@@ -899,7 +993,7 @@ manage_client (GstRTSPServer * server, GstRTSPClient * client)
 
   GST_RTSP_SERVER_LOCK (server);
   g_signal_connect (client, "closed", (GCallback) unmanage_client, ctx);
-  server->clients = g_list_prepend (server->clients, ctx);
+  priv->clients = g_list_prepend (priv->clients, ctx);
   GST_RTSP_SERVER_UNLOCK (server);
 
   if (ctx->loop) {
@@ -913,17 +1007,18 @@ static GstRTSPClient *
 default_create_client (GstRTSPServer * server)
 {
   GstRTSPClient *client;
+  GstRTSPServerPrivate *priv = server->priv;
 
   /* a new client connected, create a session to handle the client. */
   client = gst_rtsp_client_new ();
 
   /* set the session pool that this client should use */
   GST_RTSP_SERVER_LOCK (server);
-  gst_rtsp_client_set_session_pool (client, server->session_pool);
+  gst_rtsp_client_set_session_pool (client, priv->session_pool);
   /* set the mount points that this client should use */
-  gst_rtsp_client_set_mount_points (client, server->mount_points);
+  gst_rtsp_client_set_mount_points (client, priv->mount_points);
   /* set authentication manager */
-  gst_rtsp_client_set_auth (client, server->auth);
+  gst_rtsp_client_set_auth (client, priv->auth);
   GST_RTSP_SERVER_UNLOCK (server);
 
   return client;
@@ -1073,9 +1168,12 @@ accept_failed:
 static void
 watch_destroyed (GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv = server->priv;
+
   GST_DEBUG_OBJECT (server, "source destroyed");
-  g_object_unref (server->socket);
-  server->socket = NULL;
+
+  g_object_unref (priv->socket);
+  priv->socket = NULL;
   g_object_unref (server);
 }
 
@@ -1100,18 +1198,21 @@ GSource *
 gst_rtsp_server_create_source (GstRTSPServer * server,
     GCancellable * cancellable, GError ** error)
 {
+  GstRTSPServerPrivate *priv;
   GSocket *socket, *old;
   GSource *source;
 
   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
 
+  priv = server->priv;
+
   socket = gst_rtsp_server_create_socket (server, NULL, error);
   if (socket == NULL)
     goto no_socket;
 
   GST_RTSP_SERVER_LOCK (server);
-  old = server->socket;
-  server->socket = g_object_ref (socket);
+  old = priv->socket;
+  priv->socket = g_object_ref (socket);
   GST_RTSP_SERVER_UNLOCK (server);
 
   if (old)
index 3d56376..6df3a6d 100644 (file)
@@ -26,6 +26,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPServer GstRTSPServer;
 typedef struct _GstRTSPServerClass GstRTSPServerClass;
+typedef struct _GstRTSPServerPrivate GstRTSPServerPrivate;
 
 #include "rtsp-session-pool.h"
 #include "rtsp-mount-points.h"
@@ -41,10 +42,6 @@ typedef struct _GstRTSPServerClass GstRTSPServerClass;
 #define GST_RTSP_SERVER_CAST(obj)         ((GstRTSPServer*)(obj))
 #define GST_RTSP_SERVER_CLASS_CAST(klass) ((GstRTSPServerClass*)(klass))
 
-#define GST_RTSP_SERVER_GET_LOCK(server)  (&(GST_RTSP_SERVER_CAST(server)->lock))
-#define GST_RTSP_SERVER_LOCK(server)      (g_mutex_lock(GST_RTSP_SERVER_GET_LOCK(server)))
-#define GST_RTSP_SERVER_UNLOCK(server)    (g_mutex_unlock(GST_RTSP_SERVER_GET_LOCK(server)))
-
 /**
  * GstRTSPServer:
  *
@@ -54,27 +51,7 @@ typedef struct _GstRTSPServerClass GstRTSPServerClass;
 struct _GstRTSPServer {
   GObject      parent;
 
-  GMutex       lock;
-
-  /* server information */
-  gchar       *address;
-  gchar       *service;
-  gint         backlog;
-  gint         max_threads;
-
-  GSocket     *socket;
-
-  /* sessions on this server */
-  GstRTSPSessionPool  *session_pool;
-
-  /* mount points for this server */
-  GstRTSPMountPoints *mount_points;
-
-  /* authentication manager */
-  GstRTSPAuth *auth;
-
-  /* the clients that are connected */
-  GList   *clients;
+  GstRTSPServerPrivate *priv;
 };
 
 /**
index 31caca7..fb4d71c 100644 (file)
 
 #include "rtsp-session.h"
 
+#define GST_RTSP_SESSION_MEDIA_GET_PRIVATE(obj)  \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION_MEDIA, GstRTSPSessionMediaPrivate))
+
+struct _GstRTSPSessionMediaPrivate
+{
+  GMutex lock;
+  GstRTSPUrl *url;
+  GstRTSPMedia *media;
+  GstRTSPState state;
+  guint counter;
+
+  GPtrArray *transports;
+};
+
 enum
 {
   PROP_0,
@@ -38,6 +52,8 @@ gst_rtsp_session_media_class_init (GstRTSPSessionMediaClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPSessionMediaPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->finalize = gst_rtsp_session_media_finalize;
@@ -49,26 +65,32 @@ gst_rtsp_session_media_class_init (GstRTSPSessionMediaClass * klass)
 static void
 gst_rtsp_session_media_init (GstRTSPSessionMedia * media)
 {
-  g_mutex_init (&media->lock);
-  media->state = GST_RTSP_STATE_INIT;
+  GstRTSPSessionMediaPrivate *priv = GST_RTSP_SESSION_MEDIA_GET_PRIVATE (media);
+
+  media->priv = priv;
+
+  g_mutex_init (&priv->lock);
+  priv->state = GST_RTSP_STATE_INIT;
 }
 
 static void
 gst_rtsp_session_media_finalize (GObject * obj)
 {
   GstRTSPSessionMedia *media;
+  GstRTSPSessionMediaPrivate *priv;
 
   media = GST_RTSP_SESSION_MEDIA (obj);
+  priv = media->priv;
 
   GST_INFO ("free session media %p", media);
 
   gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
 
-  g_ptr_array_unref (media->transports);
+  g_ptr_array_unref (priv->transports);
 
-  gst_rtsp_url_free (media->url);
-  g_object_unref (media->media);
-  g_mutex_clear (&media->lock);
+  gst_rtsp_url_free (priv->url);
+  g_object_unref (priv->media);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_session_media_parent_class)->finalize (obj);
 }
@@ -95,26 +117,66 @@ free_session_media (gpointer data)
 GstRTSPSessionMedia *
 gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media)
 {
+  GstRTSPSessionMediaPrivate *priv;
   GstRTSPSessionMedia *result;
   guint n_streams;
 
   g_return_val_if_fail (url != NULL, NULL);
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
-  g_return_val_if_fail (media->status == GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
+  g_return_val_if_fail (gst_rtsp_media_get_status (media) ==
+      GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
 
   result = g_object_new (GST_TYPE_RTSP_SESSION_MEDIA, NULL);
-  result->url = gst_rtsp_url_copy ((GstRTSPUrl *) url);
-  result->media = media;
+  priv = result->priv;
+
+  priv->url = gst_rtsp_url_copy ((GstRTSPUrl *) url);
+  priv->media = media;
 
   /* prealloc the streams now, filled with NULL */
   n_streams = gst_rtsp_media_n_streams (media);
-  result->transports = g_ptr_array_new_full (n_streams, free_session_media);
-  g_ptr_array_set_size (result->transports, n_streams);
+  priv->transports = g_ptr_array_new_full (n_streams, free_session_media);
+  g_ptr_array_set_size (priv->transports, n_streams);
 
   return result;
 }
 
 /**
+ * gst_rtsp_session_media_matches_url:
+ * @media: a #GstRTSPSessionMedia
+ * @url: a #GstRTSPUrl
+ *
+ * Check if the url of @media matches @url.
+ *
+ * Returns: %TRUE when @url matches the url of @media.
+ */
+gboolean
+gst_rtsp_session_media_matches_url (GstRTSPSessionMedia * media,
+    const GstRTSPUrl * url)
+{
+  g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
+  g_return_val_if_fail (url != NULL, FALSE);
+
+  return g_str_equal (media->priv->url->abspath, url->abspath);
+}
+
+/**
+ * gst_rtsp_session_media_get_media:
+ * @media: a #GstRTSPSessionMedia
+ *
+ * Get the #GstRTSPMedia that was used when constructing @media
+ *
+ * Returns: (transfer none): the #GstRTSPMedia of @media. Remains valid as long
+ *         as @media is valid.
+ */
+GstRTSPMedia *
+gst_rtsp_session_media_get_media (GstRTSPSessionMedia * media)
+{
+  g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
+
+  return media->priv->media;
+}
+
+/**
  * gst_rtsp_session_media_set_transport:
  * @media: a #GstRTSPSessionMedia
  * @stream: a #GstRTSPStream
@@ -128,21 +190,26 @@ GstRTSPStreamTransport *
 gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
     GstRTSPStream * stream, GstRTSPTransport * tr)
 {
+  GstRTSPSessionMediaPrivate *priv;
   GstRTSPStreamTransport *result;
+  guint idx;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
-  g_return_val_if_fail (stream->idx < media->transports->len, NULL);
+  g_return_val_if_fail (tr != NULL, NULL);
+  priv = media->priv;
+  idx = gst_rtsp_stream_get_index (stream);
+  g_return_val_if_fail (idx < priv->transports->len, NULL);
 
-  g_mutex_lock (&media->lock);
-  result = g_ptr_array_index (media->transports, stream->idx);
+  g_mutex_lock (&priv->lock);
+  result = g_ptr_array_index (priv->transports, idx);
   if (result == NULL) {
     result = gst_rtsp_stream_transport_new (stream, tr);
-    g_ptr_array_index (media->transports, stream->idx) = result;
-    g_mutex_unlock (&media->lock);
+    g_ptr_array_index (priv->transports, idx) = result;
+    g_mutex_unlock (&priv->lock);
   } else {
     gst_rtsp_stream_transport_set_transport (result, tr);
-    g_mutex_unlock (&media->lock);
+    g_mutex_unlock (&priv->lock);
   }
 
   return result;
@@ -161,14 +228,16 @@ gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
 GstRTSPStreamTransport *
 gst_rtsp_session_media_get_transport (GstRTSPSessionMedia * media, guint idx)
 {
+  GstRTSPSessionMediaPrivate *priv;
   GstRTSPStreamTransport *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
-  g_return_val_if_fail (idx < media->transports->len, NULL);
+  priv = media->priv;
+  g_return_val_if_fail (idx < priv->transports->len, NULL);
 
-  g_mutex_lock (&media->lock);
-  result = g_ptr_array_index (media->transports, idx);
-  g_mutex_unlock (&media->lock);
+  g_mutex_lock (&priv->lock);
+  result = g_ptr_array_index (priv->transports, idx);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -187,12 +256,16 @@ gboolean
 gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia * media,
     GstRTSPRange * range)
 {
+  GstRTSPSessionMediaPrivate *priv;
+
   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
 
-  g_mutex_lock (&media->lock);
-  range->min = media->counter++;
-  range->max = media->counter++;
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  range->min = priv->counter++;
+  range->max = priv->counter++;
+  g_mutex_unlock (&priv->lock);
 
   return TRUE;
 }
@@ -209,13 +282,64 @@ gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia * media,
 gboolean
 gst_rtsp_session_media_set_state (GstRTSPSessionMedia * media, GstState state)
 {
+  GstRTSPSessionMediaPrivate *priv;
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
 
-  g_mutex_lock (&media->lock);
-  ret = gst_rtsp_media_set_state (media->media, state, media->transports);
-  g_mutex_unlock (&media->lock);
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  ret = gst_rtsp_media_set_state (priv->media, state, priv->transports);
+  g_mutex_unlock (&priv->lock);
+
+  return ret;
+}
+
+/**
+ * gst_rtsp_session_media_set_rtsp_state:
+ * @media: a #GstRTSPSessionMedia
+ * @state: a #GstRTSPState
+ *
+ * Set the RTSP state of @media to @state.
+ */
+void
+gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia * media,
+    GstRTSPState state)
+{
+  GstRTSPSessionMediaPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_SESSION_MEDIA (media));
+
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->state = state;
+  g_mutex_unlock (&priv->lock);
+}
+
+/**
+ * gst_rtsp_session_media_set_rtsp_state:
+ * @media: a #GstRTSPSessionMedia
+ *
+ * Get the current RTSP state of @media.
+ *
+ * Returns: the current RTSP state of @media.
+ */
+GstRTSPState
+gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia * media)
+{
+  GstRTSPSessionMediaPrivate *priv;
+  GstRTSPState ret;
+
+  g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media),
+      GST_RTSP_STATE_INVALID);
+
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  ret = priv->state;
+  g_mutex_unlock (&priv->lock);
 
   return ret;
 }
index 2156f30..ed5284d 100644 (file)
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPSessionMedia GstRTSPSessionMedia;
 typedef struct _GstRTSPSessionMediaClass GstRTSPSessionMediaClass;
+typedef struct _GstRTSPSessionMediaPrivate GstRTSPSessionMediaPrivate;
 
 /**
  * GstRTSPSessionMedia:
@@ -53,13 +54,7 @@ struct _GstRTSPSessionMedia
 {
   GObject  parent;
 
-  GMutex        lock;
-  GstRTSPUrl   *url;
-  GstRTSPMedia *media;
-  GstRTSPState  state;
-  guint         counter;
-
-  GPtrArray    *transports;
+  GstRTSPSessionMediaPrivate *priv;
 };
 
 struct _GstRTSPSessionMediaClass
@@ -71,10 +66,20 @@ GType                    gst_rtsp_session_media_get_type       (void);
 
 GstRTSPSessionMedia *    gst_rtsp_session_media_new            (const GstRTSPUrl *url,
                                                                 GstRTSPMedia *media);
+
+gboolean                 gst_rtsp_session_media_matches_url    (GstRTSPSessionMedia *media,
+                                                                const GstRTSPUrl *url);
+GstRTSPMedia *           gst_rtsp_session_media_get_media      (GstRTSPSessionMedia *media);
+
 /* control media */
+
 gboolean                 gst_rtsp_session_media_set_state      (GstRTSPSessionMedia *media,
                                                                 GstState state);
 
+void                     gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia *media,
+                                                                GstRTSPState state);
+GstRTSPState             gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia *media);
+
 /* get stream transport config */
 GstRTSPStreamTransport * gst_rtsp_session_media_set_transport  (GstRTSPSessionMedia *media,
                                                                 GstRTSPStream *stream,
index 7a3231d..2fe209f 100644 (file)
 
 #include "rtsp-session-pool.h"
 
+#define GST_RTSP_SESSION_POOL_GET_PRIVATE(obj)  \
+         (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION_POOL, GstRTSPSessionPoolPrivate))
+
+struct _GstRTSPSessionPoolPrivate
+{
+  guint max_sessions;
+
+  GMutex lock;
+  GHashTable *sessions;
+};
+
 #define DEFAULT_MAX_SESSIONS 0
 
 enum
@@ -54,6 +65,8 @@ gst_rtsp_session_pool_class_init (GstRTSPSessionPoolClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPSessionPoolPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->get_property = gst_rtsp_session_pool_get_property;
@@ -75,19 +88,24 @@ gst_rtsp_session_pool_class_init (GstRTSPSessionPoolClass * klass)
 static void
 gst_rtsp_session_pool_init (GstRTSPSessionPool * pool)
 {
-  g_mutex_init (&pool->lock);
-  pool->sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
+  GstRTSPSessionPoolPrivate *priv = GST_RTSP_SESSION_POOL_GET_PRIVATE (pool);
+
+  pool->priv = priv;
+
+  g_mutex_init (&priv->lock);
+  priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
       NULL, g_object_unref);
-  pool->max_sessions = DEFAULT_MAX_SESSIONS;
+  priv->max_sessions = DEFAULT_MAX_SESSIONS;
 }
 
 static void
 gst_rtsp_session_pool_finalize (GObject * object)
 {
   GstRTSPSessionPool *pool = GST_RTSP_SESSION_POOL (object);
+  GstRTSPSessionPoolPrivate *priv = pool->priv;
 
-  g_mutex_clear (&pool->lock);
-  g_hash_table_unref (pool->sessions);
+  g_mutex_clear (&priv->lock);
+  g_hash_table_unref (priv->sessions);
 
   G_OBJECT_CLASS (gst_rtsp_session_pool_parent_class)->finalize (object);
 }
@@ -152,11 +170,15 @@ gst_rtsp_session_pool_new (void)
 void
 gst_rtsp_session_pool_set_max_sessions (GstRTSPSessionPool * pool, guint max)
 {
+  GstRTSPSessionPoolPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_SESSION_POOL (pool));
 
-  g_mutex_lock (&pool->lock);
-  pool->max_sessions = max;
-  g_mutex_unlock (&pool->lock);
+  priv = pool->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->max_sessions = max;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -171,13 +193,16 @@ gst_rtsp_session_pool_set_max_sessions (GstRTSPSessionPool * pool, guint max)
 guint
 gst_rtsp_session_pool_get_max_sessions (GstRTSPSessionPool * pool)
 {
+  GstRTSPSessionPoolPrivate *priv;
   guint result;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0);
 
-  g_mutex_lock (&pool->lock);
-  result = pool->max_sessions;
-  g_mutex_unlock (&pool->lock);
+  priv = pool->priv;
+
+  g_mutex_lock (&priv->lock);
+  result = priv->max_sessions;
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -193,13 +218,16 @@ gst_rtsp_session_pool_get_max_sessions (GstRTSPSessionPool * pool)
 guint
 gst_rtsp_session_pool_get_n_sessions (GstRTSPSessionPool * pool)
 {
+  GstRTSPSessionPoolPrivate *priv;
   guint result;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0);
 
-  g_mutex_lock (&pool->lock);
-  result = g_hash_table_size (pool->sessions);
-  g_mutex_unlock (&pool->lock);
+  priv = pool->priv;
+
+  g_mutex_lock (&priv->lock);
+  result = g_hash_table_size (priv->sessions);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -218,18 +246,21 @@ gst_rtsp_session_pool_get_n_sessions (GstRTSPSessionPool * pool)
 GstRTSPSession *
 gst_rtsp_session_pool_find (GstRTSPSessionPool * pool, const gchar * sessionid)
 {
+  GstRTSPSessionPoolPrivate *priv;
   GstRTSPSession *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
   g_return_val_if_fail (sessionid != NULL, NULL);
 
-  g_mutex_lock (&pool->lock);
-  result = g_hash_table_lookup (pool->sessions, sessionid);
+  priv = pool->priv;
+
+  g_mutex_lock (&priv->lock);
+  result = g_hash_table_lookup (priv->sessions, sessionid);
   if (result) {
     g_object_ref (result);
     gst_rtsp_session_touch (result);
   }
-  g_mutex_unlock (&pool->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -260,6 +291,7 @@ create_session_id (GstRTSPSessionPool * pool)
 GstRTSPSession *
 gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
 {
+  GstRTSPSessionPoolPrivate *priv;
   GstRTSPSession *result = NULL;
   GstRTSPSessionPoolClass *klass;
   gchar *id = NULL;
@@ -267,6 +299,8 @@ gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
 
+  priv = pool->priv;
+
   klass = GST_RTSP_SESSION_POOL_GET_CLASS (pool);
 
   retry = 0;
@@ -281,14 +315,14 @@ gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
     if (id == NULL)
       goto no_session;
 
-    g_mutex_lock (&pool->lock);
+    g_mutex_lock (&priv->lock);
     /* check session limit */
-    if (pool->max_sessions > 0) {
-      if (g_hash_table_size (pool->sessions) >= pool->max_sessions)
+    if (priv->max_sessions > 0) {
+      if (g_hash_table_size (priv->sessions) >= priv->max_sessions)
         goto too_many_sessions;
     }
     /* check if the sessionid existed */
-    result = g_hash_table_lookup (pool->sessions, id);
+    result = g_hash_table_lookup (priv->sessions, id);
     if (result) {
       /* found, retry with a different session id */
       result = NULL;
@@ -300,9 +334,10 @@ gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
       result = gst_rtsp_session_new (id);
       /* take additional ref for the pool */
       g_object_ref (result);
-      g_hash_table_insert (pool->sessions, result->sessionid, result);
+      g_hash_table_insert (priv->sessions,
+          (gchar *) gst_rtsp_session_get_sessionid (result), result);
     }
-    g_mutex_unlock (&pool->lock);
+    g_mutex_unlock (&priv->lock);
 
     g_free (id);
   } while (result == NULL);
@@ -323,14 +358,14 @@ no_session:
 collision:
   {
     GST_WARNING ("can't find unique sessionid for GstRTSPSessionPool %p", pool);
-    g_mutex_unlock (&pool->lock);
+    g_mutex_unlock (&priv->lock);
     g_free (id);
     return NULL;
   }
 too_many_sessions:
   {
-    GST_WARNING ("session pool reached max sessions of %d", pool->max_sessions);
-    g_mutex_unlock (&pool->lock);
+    GST_WARNING ("session pool reached max sessions of %d", priv->max_sessions);
+    g_mutex_unlock (&priv->lock);
     g_free (id);
     return NULL;
   }
@@ -348,14 +383,19 @@ too_many_sessions:
 gboolean
 gst_rtsp_session_pool_remove (GstRTSPSessionPool * pool, GstRTSPSession * sess)
 {
+  GstRTSPSessionPoolPrivate *priv;
   gboolean found;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), FALSE);
   g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE);
 
-  g_mutex_lock (&pool->lock);
-  found = g_hash_table_remove (pool->sessions, sess->sessionid);
-  g_mutex_unlock (&pool->lock);
+  priv = pool->priv;
+
+  g_mutex_lock (&priv->lock);
+  found =
+      g_hash_table_remove (priv->sessions,
+      gst_rtsp_session_get_sessionid (sess));
+  g_mutex_unlock (&priv->lock);
 
   return found;
 }
@@ -378,18 +418,21 @@ cleanup_func (gchar * sessionid, GstRTSPSession * sess, GTimeVal * now)
 guint
 gst_rtsp_session_pool_cleanup (GstRTSPSessionPool * pool)
 {
+  GstRTSPSessionPoolPrivate *priv;
   guint result;
   GTimeVal now;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0);
 
+  priv = pool->priv;
+
   g_get_current_time (&now);
 
-  g_mutex_lock (&pool->lock);
+  g_mutex_lock (&priv->lock);
   result =
-      g_hash_table_foreach_remove (pool->sessions, (GHRFunc) cleanup_func,
+      g_hash_table_foreach_remove (priv->sessions, (GHRFunc) cleanup_func,
       &now);
-  g_mutex_unlock (&pool->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -397,7 +440,7 @@ gst_rtsp_session_pool_cleanup (GstRTSPSessionPool * pool)
 typedef struct
 {
   GstRTSPSessionPool *pool;
-  GstRTSPSessionFilterFunc func;
+  GstRTSPSessionPoolFilterFunc func;
   gpointer user_data;
   GList *list;
 } FilterData;
@@ -443,21 +486,24 @@ filter_func (gchar * sessionid, GstRTSPSession * sess, FilterData * data)
  */
 GList *
 gst_rtsp_session_pool_filter (GstRTSPSessionPool * pool,
-    GstRTSPSessionFilterFunc func, gpointer user_data)
+    GstRTSPSessionPoolFilterFunc func, gpointer user_data)
 {
+  GstRTSPSessionPoolPrivate *priv;
   FilterData data;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
   g_return_val_if_fail (func != NULL, NULL);
 
+  priv = pool->priv;
+
   data.pool = pool;
   data.func = func;
   data.user_data = user_data;
   data.list = NULL;
 
-  g_mutex_lock (&pool->lock);
-  g_hash_table_foreach_remove (pool->sessions, (GHRFunc) filter_func, &data);
-  g_mutex_unlock (&pool->lock);
+  g_mutex_lock (&priv->lock);
+  g_hash_table_foreach_remove (priv->sessions, (GHRFunc) filter_func, &data);
+  g_mutex_unlock (&priv->lock);
 
   return data.list;
 }
@@ -489,15 +535,17 @@ collect_timeout (gchar * sessionid, GstRTSPSession * sess, GstPoolSource * psrc)
 static gboolean
 gst_pool_source_prepare (GSource * source, gint * timeout)
 {
+  GstRTSPSessionPoolPrivate *priv;
   GstPoolSource *psrc;
   gboolean result;
 
   psrc = (GstPoolSource *) source;
   psrc->timeout = -1;
+  priv = psrc->pool->priv;
 
-  g_mutex_lock (&psrc->pool->lock);
-  g_hash_table_foreach (psrc->pool->sessions, (GHFunc) collect_timeout, psrc);
-  g_mutex_unlock (&psrc->pool->lock);
+  g_mutex_lock (&priv->lock);
+  g_hash_table_foreach (priv->sessions, (GHFunc) collect_timeout, psrc);
+  g_mutex_unlock (&priv->lock);
 
   if (timeout)
     *timeout = psrc->timeout;
index ede06ce..ca490de 100644 (file)
@@ -27,6 +27,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPSessionPool GstRTSPSessionPool;
 typedef struct _GstRTSPSessionPoolClass GstRTSPSessionPoolClass;
+typedef struct _GstRTSPSessionPoolPrivate GstRTSPSessionPoolPrivate;
 
 #include "rtsp-session.h"
 
@@ -51,10 +52,7 @@ typedef struct _GstRTSPSessionPoolClass GstRTSPSessionPoolClass;
 struct _GstRTSPSessionPool {
   GObject       parent;
 
-  guint         max_sessions;
-
-  GMutex        lock;
-  GHashTable   *sessions;
+  GstRTSPSessionPoolPrivate *priv;
 };
 
 /**
@@ -83,22 +81,7 @@ struct _GstRTSPSessionPoolClass {
 typedef gboolean (*GstRTSPSessionPoolFunc)  (GstRTSPSessionPool *pool, gpointer user_data);
 
 /**
- * GstRTSPFilterResult:
- * @GST_RTSP_FILTER_REMOVE: Remove session
- * @GST_RTSP_FILTER_KEEP: Keep session in the pool
- * @GST_RTSP_FILTER_REF: Ref session in the result list
- *
- * Possible return values for gst_rtsp_session_pool_filter().
- */
-typedef enum
-{
-  GST_RTSP_FILTER_REMOVE,
-  GST_RTSP_FILTER_KEEP,
-  GST_RTSP_FILTER_REF,
-} GstRTSPFilterResult;
-
-/**
- * GstRTSPSessionFilterFunc:
+ * GstRTSPSessionPoolFilterFunc:
  * @pool: a #GstRTSPSessionPool object
  * @session: a #GstRTSPSession in @pool
  * @user_data: user data that has been given to gst_rtsp_session_pool_filter()
@@ -117,9 +100,9 @@ typedef enum
  *
  * Returns: a #GstRTSPFilterResult.
  */
-typedef GstRTSPFilterResult (*GstRTSPSessionFilterFunc)  (GstRTSPSessionPool *pool,
-                                                          GstRTSPSession *session,
-                                                          gpointer user_data);
+typedef GstRTSPFilterResult (*GstRTSPSessionPoolFilterFunc)  (GstRTSPSessionPool *pool,
+                                                              GstRTSPSession *session,
+                                                              gpointer user_data);
 
 
 GType                 gst_rtsp_session_pool_get_type          (void);
@@ -142,7 +125,7 @@ gboolean              gst_rtsp_session_pool_remove            (GstRTSPSessionPoo
 
 /* perform session maintenance */
 GList *               gst_rtsp_session_pool_filter            (GstRTSPSessionPool *pool,
-                                                               GstRTSPSessionFilterFunc func,
+                                                               GstRTSPSessionPoolFilterFunc func,
                                                                gpointer user_data);
 guint                 gst_rtsp_session_pool_cleanup           (GstRTSPSessionPool *pool);
 GSource *             gst_rtsp_session_pool_create_watch      (GstRTSPSessionPool *pool);
index 7f22026..f50a476 100644 (file)
 
 #include "rtsp-session.h"
 
+#define GST_RTSP_SESSION_GET_PRIVATE(obj)  \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION, GstRTSPSessionPrivate))
+
+struct _GstRTSPSessionPrivate
+{
+  GMutex lock;
+  gchar *sessionid;
+
+  guint timeout;
+  GTimeVal create_time;
+  GTimeVal last_access;
+  gint expire_count;
+
+  GList *medias;
+};
+
 #undef DEBUG
 
 #define DEFAULT_TIMEOUT        60
@@ -48,6 +64,8 @@ gst_rtsp_session_class_init (GstRTSPSessionClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPSessionPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->get_property = gst_rtsp_session_get_property;
@@ -71,9 +89,13 @@ gst_rtsp_session_class_init (GstRTSPSessionClass * klass)
 static void
 gst_rtsp_session_init (GstRTSPSession * session)
 {
-  g_mutex_init (&session->lock);
-  session->timeout = DEFAULT_TIMEOUT;
-  g_get_current_time (&session->create_time);
+  GstRTSPSessionPrivate *priv = GST_RTSP_SESSION_GET_PRIVATE (session);
+
+  session->priv = priv;
+
+  g_mutex_init (&priv->lock);
+  priv->timeout = DEFAULT_TIMEOUT;
+  g_get_current_time (&priv->create_time);
   gst_rtsp_session_touch (session);
 }
 
@@ -81,17 +103,19 @@ static void
 gst_rtsp_session_finalize (GObject * obj)
 {
   GstRTSPSession *session;
+  GstRTSPSessionPrivate *priv;
 
   session = GST_RTSP_SESSION (obj);
+  priv = session->priv;
 
   GST_INFO ("finalize session %p", session);
 
   /* free all media */
-  g_list_free_full (session->medias, g_object_unref);
+  g_list_free_full (priv->medias, g_object_unref);
 
   /* free session id */
-  g_free (session->sessionid);
-  g_mutex_clear (&session->lock);
+  g_free (priv->sessionid);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_session_parent_class)->finalize (obj);
 }
@@ -101,10 +125,11 @@ gst_rtsp_session_get_property (GObject * object, guint propid,
     GValue * value, GParamSpec * pspec)
 {
   GstRTSPSession *session = GST_RTSP_SESSION (object);
+  GstRTSPSessionPrivate *priv = session->priv;
 
   switch (propid) {
     case PROP_SESSIONID:
-      g_value_set_string (value, session->sessionid);
+      g_value_set_string (value, priv->sessionid);
       break;
     case PROP_TIMEOUT:
       g_value_set_uint (value, gst_rtsp_session_get_timeout (session));
@@ -119,11 +144,12 @@ gst_rtsp_session_set_property (GObject * object, guint propid,
     const GValue * value, GParamSpec * pspec)
 {
   GstRTSPSession *session = GST_RTSP_SESSION (object);
+  GstRTSPSessionPrivate *priv = session->priv;
 
   switch (propid) {
     case PROP_SESSIONID:
-      g_free (session->sessionid);
-      session->sessionid = g_value_dup_string (value);
+      g_free (priv->sessionid);
+      priv->sessionid = g_value_dup_string (value);
       break;
     case PROP_TIMEOUT:
       gst_rtsp_session_set_timeout (session, g_value_get_uint (value));
@@ -150,18 +176,22 @@ GstRTSPSessionMedia *
 gst_rtsp_session_manage_media (GstRTSPSession * sess, const GstRTSPUrl * uri,
     GstRTSPMedia * media)
 {
+  GstRTSPSessionPrivate *priv;
   GstRTSPSessionMedia *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
   g_return_val_if_fail (uri != NULL, NULL);
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
-  g_return_val_if_fail (media->status == GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
+  g_return_val_if_fail (gst_rtsp_media_get_status (media) ==
+      GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
+
+  priv = sess->priv;
 
   result = gst_rtsp_session_media_new (uri, media);
 
-  g_mutex_lock (&sess->lock);
-  sess->medias = g_list_prepend (sess->medias, result);
-  g_mutex_unlock (&sess->lock);
+  g_mutex_lock (&priv->lock);
+  priv->medias = g_list_prepend (priv->medias, result);
+  g_mutex_unlock (&priv->lock);
 
   GST_INFO ("manage new media %p in session %p", media, result);
 
@@ -181,18 +211,21 @@ gboolean
 gst_rtsp_session_release_media (GstRTSPSession * sess,
     GstRTSPSessionMedia * media)
 {
+  GstRTSPSessionPrivate *priv;
   GList *find;
   gboolean more;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE);
   g_return_val_if_fail (media != NULL, FALSE);
 
-  g_mutex_lock (&sess->lock);
-  find = g_list_find (sess->medias, media);
+  priv = sess->priv;
+
+  g_mutex_lock (&priv->lock);
+  find = g_list_find (priv->medias, media);
   if (find)
-    sess->medias = g_list_delete_link (sess->medias, find);
-  more = (sess->medias != NULL);
-  g_mutex_unlock (&sess->lock);
+    priv->medias = g_list_delete_link (priv->medias, find);
+  more = (priv->medias != NULL);
+  g_mutex_unlock (&priv->lock);
 
   if (find)
     g_object_unref (media);
@@ -212,24 +245,87 @@ gst_rtsp_session_release_media (GstRTSPSession * sess,
 GstRTSPSessionMedia *
 gst_rtsp_session_get_media (GstRTSPSession * sess, const GstRTSPUrl * url)
 {
+  GstRTSPSessionPrivate *priv;
   GstRTSPSessionMedia *result;
   GList *walk;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
   g_return_val_if_fail (url != NULL, NULL);
 
+  priv = sess->priv;
   result = NULL;
 
-  g_mutex_lock (&sess->lock);
-  for (walk = sess->medias; walk; walk = g_list_next (walk)) {
+  g_mutex_lock (&priv->lock);
+  for (walk = priv->medias; walk; walk = g_list_next (walk)) {
     result = (GstRTSPSessionMedia *) walk->data;
 
-    if (g_str_equal (result->url->abspath, url->abspath))
+    if (gst_rtsp_session_media_matches_url (result, url))
       break;
 
     result = NULL;
   }
-  g_mutex_unlock (&sess->lock);
+  g_mutex_unlock (&priv->lock);
+
+  return result;
+}
+
+/**
+ * gst_rtsp_session_filter:
+ * @sess: a #GstRTSPSession
+ * @func: (scope call): a callback
+ * @user_data: user data passed to @func
+ *
+ * Call @func for each media in @sess. The result value of @func determines
+ * what happens to the media. @func will be called with @sess
+ * locked so no further actions on @sess can be performed from @func.
+ *
+ * If @func returns #GST_RTSP_FILTER_REMOVE, the media will be removed from
+ * @sess.
+ *
+ * If @func returns #GST_RTSP_FILTER_KEEP, the media will remain in @sess.
+ *
+ * If @func returns #GST_RTSP_FILTER_REF, the media will remain in @sess but
+ * will also be added with an additional ref to the result #GList of this
+ * function..
+ *
+ * Returns: (element-type GstRTSPSessionMedia) (transfer full): a GList with all
+ * media for which @func returned #GST_RTSP_FILTER_REF. After usage, each
+ * element in the #GList should be unreffed before the list is freed.
+ */
+GList *
+gst_rtsp_session_filter (GstRTSPSession * sess,
+    GstRTSPSessionFilterFunc func, gpointer user_data)
+{
+  GstRTSPSessionPrivate *priv;
+  GList *result, *walk, *next;
+
+  g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
+  g_return_val_if_fail (func != NULL, NULL);
+
+  priv = sess->priv;
+
+  result = NULL;
+
+  g_mutex_lock (&priv->lock);
+  for (walk = priv->medias; walk; walk = next) {
+    GstRTSPSessionMedia *media = walk->data;
+
+    next = g_list_next (walk);
+
+    switch (func (sess, media, user_data)) {
+      case GST_RTSP_FILTER_REMOVE:
+        g_object_unref (media);
+        priv->medias = g_list_delete_link (priv->medias, walk);
+        break;
+      case GST_RTSP_FILTER_REF:
+        result = g_list_prepend (result, g_object_ref (media));
+        break;
+      case GST_RTSP_FILTER_KEEP:
+      default:
+        break;
+    }
+  }
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -266,7 +362,7 @@ gst_rtsp_session_get_sessionid (GstRTSPSession * session)
 {
   g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL);
 
-  return session->sessionid;
+  return session->priv->sessionid;
 }
 
 /**
@@ -280,17 +376,19 @@ gst_rtsp_session_get_sessionid (GstRTSPSession * session)
 gchar *
 gst_rtsp_session_get_header (GstRTSPSession * session)
 {
+  GstRTSPSessionPrivate *priv;
   gchar *result;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL);
 
-  g_mutex_lock (&session->lock);
-  if (session->timeout != 60)
-    result = g_strdup_printf ("%s; timeout=%d", session->sessionid,
-        session->timeout);
+  priv = session->priv;
+
+  g_mutex_lock (&priv->lock);
+  if (priv->timeout != 60)
+    result = g_strdup_printf ("%s; timeout=%d", priv->sessionid, priv->timeout);
   else
-    result = g_strdup (session->sessionid);
-  g_mutex_unlock (&session->lock);
+    result = g_strdup (priv->sessionid);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -306,11 +404,15 @@ gst_rtsp_session_get_header (GstRTSPSession * session)
 void
 gst_rtsp_session_set_timeout (GstRTSPSession * session, guint timeout)
 {
+  GstRTSPSessionPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_SESSION (session));
 
-  g_mutex_lock (&session->lock);
-  session->timeout = timeout;
-  g_mutex_unlock (&session->lock);
+  priv = session->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->timeout = timeout;
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -324,13 +426,16 @@ gst_rtsp_session_set_timeout (GstRTSPSession * session, guint timeout)
 guint
 gst_rtsp_session_get_timeout (GstRTSPSession * session)
 {
+  GstRTSPSessionPrivate *priv;
   guint res;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION (session), 0);
 
-  g_mutex_lock (&session->lock);
-  res = session->timeout;
-  g_mutex_unlock (&session->lock);
+  priv = session->priv;
+
+  g_mutex_lock (&priv->lock);
+  res = priv->timeout;
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -344,11 +449,15 @@ gst_rtsp_session_get_timeout (GstRTSPSession * session)
 void
 gst_rtsp_session_touch (GstRTSPSession * session)
 {
+  GstRTSPSessionPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_SESSION (session));
 
-  g_mutex_lock (&session->lock);
-  g_get_current_time (&session->last_access);
-  g_mutex_unlock (&session->lock);
+  priv = session->priv;
+
+  g_mutex_lock (&priv->lock);
+  g_get_current_time (&priv->last_access);
+  g_mutex_unlock (&priv->lock);
 }
 
 /**
@@ -362,7 +471,7 @@ gst_rtsp_session_prevent_expire (GstRTSPSession * session)
 {
   g_return_if_fail (GST_IS_RTSP_SESSION (session));
 
-  g_atomic_int_add (&session->expire_count, 1);
+  g_atomic_int_add (&session->priv->expire_count, 1);
 }
 
 /**
@@ -375,7 +484,7 @@ gst_rtsp_session_prevent_expire (GstRTSPSession * session)
 void
 gst_rtsp_session_allow_expire (GstRTSPSession * session)
 {
-  g_atomic_int_add (&session->expire_count, -1);
+  g_atomic_int_add (&session->priv->expire_count, -1);
 }
 
 /**
@@ -390,22 +499,25 @@ gst_rtsp_session_allow_expire (GstRTSPSession * session)
 gint
 gst_rtsp_session_next_timeout (GstRTSPSession * session, GTimeVal * now)
 {
+  GstRTSPSessionPrivate *priv;
   gint res;
   GstClockTime last_access, now_ns;
 
   g_return_val_if_fail (GST_IS_RTSP_SESSION (session), -1);
   g_return_val_if_fail (now != NULL, -1);
 
-  g_mutex_lock (&session->lock);
-  if (g_atomic_int_get (&session->expire_count) != 0) {
+  priv = session->priv;
+
+  g_mutex_lock (&priv->lock);
+  if (g_atomic_int_get (&priv->expire_count) != 0) {
     /* touch session when the expire count is not 0 */
-    g_get_current_time (&session->last_access);
+    g_get_current_time (&priv->last_access);
   }
 
-  last_access = GST_TIMEVAL_TO_TIME (session->last_access);
+  last_access = GST_TIMEVAL_TO_TIME (priv->last_access);
   /* add timeout allow for 5 seconds of extra time */
-  last_access += session->timeout * GST_SECOND + (5 * GST_SECOND);
-  g_mutex_unlock (&session->lock);
+  last_access += priv->timeout * GST_SECOND + (5 * GST_SECOND);
+  g_mutex_unlock (&priv->lock);
 
   now_ns = GST_TIMEVAL_TO_TIME (*now);
 
index f5c4fcd..844795d 100644 (file)
@@ -37,19 +37,28 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPSession GstRTSPSession;
 typedef struct _GstRTSPSessionClass GstRTSPSessionClass;
+typedef struct _GstRTSPSessionPrivate GstRTSPSessionPrivate;
+
+/**
+ * GstRTSPFilterResult:
+ * @GST_RTSP_FILTER_REMOVE: Remove session
+ * @GST_RTSP_FILTER_KEEP: Keep session in the pool
+ * @GST_RTSP_FILTER_REF: Ref session in the result list
+ *
+ * Possible return values for gst_rtsp_session_pool_filter().
+ */
+typedef enum
+{
+  GST_RTSP_FILTER_REMOVE,
+  GST_RTSP_FILTER_KEEP,
+  GST_RTSP_FILTER_REF,
+} GstRTSPFilterResult;
 
 #include "rtsp-media.h"
 #include "rtsp-session-media.h"
 
 /**
  * GstRTSPSession:
- * @parent: the parent GObject
- * @sessionid: the session id of the session
- * @timeout: the timeout of the session
- * @create_time: the time when the session was created
- * @last_access: the time the session was last accessed
- * @expire_count: the expire prevention counter
- * @medias: a list of #GstRTSPSessionMedia managed in this session
  *
  * Session information kept by the server for a specific client.
  * One client session, identified with a session id, can handle multiple medias
@@ -58,15 +67,7 @@ typedef struct _GstRTSPSessionClass GstRTSPSessionClass;
 struct _GstRTSPSession {
   GObject       parent;
 
-  GMutex        lock;
-  gchar        *sessionid;
-
-  guint         timeout;
-  GTimeVal      create_time;
-  GTimeVal      last_access;
-  gint          expire_count;
-
-  GList        *medias;
+  GstRTSPSessionPrivate *priv;
 };
 
 struct _GstRTSPSessionClass {
@@ -102,6 +103,35 @@ gboolean               gst_rtsp_session_release_media        (GstRTSPSession *se
 GstRTSPSessionMedia *  gst_rtsp_session_get_media            (GstRTSPSession *sess,
                                                               const GstRTSPUrl *url);
 
+/**
+ * GstRTSPSessionFilterFunc:
+ * @sess: a #GstRTSPSession object
+ * @media: a #GstRTSPSessionMedia in @sess
+ * @user_data: user data that has been given to gst_rtsp_session_filter()
+ *
+ * This function will be called by the gst_rtsp_session_filter(). An
+ * implementation should return a value of #GstRTSPFilterResult.
+ *
+ * When this function returns #GST_RTSP_FILTER_REMOVE, @media will be removed
+ * from @sess.
+ *
+ * A return value of #GST_RTSP_FILTER_KEEP will leave @media untouched in
+ * @sess.
+ *
+ * A value of GST_RTSP_FILTER_REF will add @media to the result #GList of
+ * gst_rtsp_session_filter().
+ *
+ * Returns: a #GstRTSPFilterResult.
+ */
+typedef GstRTSPFilterResult (*GstRTSPSessionFilterFunc)  (GstRTSPSession *sess,
+                                                          GstRTSPSessionMedia *media,
+                                                          gpointer user_data);
+
+GList *                gst_rtsp_session_filter           (GstRTSPSession *sess,
+                                                          GstRTSPSessionFilterFunc func,
+                                                          gpointer user_data);
+
+
 G_END_DECLS
 
 #endif /* __GST_RTSP_SESSION_H__ */
index 6df8d4d..0859573 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 
-#include <gst/app/gstappsrc.h>
-#include <gst/app/gstappsink.h>
-
 #include "rtsp-stream-transport.h"
 
+#define GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE(obj)  \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM_TRANSPORT, GstRTSPStreamTransportPrivate))
+
+struct _GstRTSPStreamTransportPrivate
+{
+  GstRTSPStream *stream;
+
+  GstRTSPSendFunc send_rtp;
+  GstRTSPSendFunc send_rtcp;
+  gpointer user_data;
+  GDestroyNotify notify;
+
+  GstRTSPKeepAliveFunc keep_alive;
+  gpointer ka_user_data;
+  GDestroyNotify ka_notify;
+  gboolean active;
+  gboolean timed_out;
+
+  GstRTSPTransport *transport;
+
+  GObject *rtpsource;
+};
+
 enum
 {
   PROP_0,
@@ -44,6 +64,8 @@ gst_rtsp_stream_transport_class_init (GstRTSPStreamTransportClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPStreamTransportPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->finalize = gst_rtsp_stream_transport_finalize;
@@ -55,25 +77,31 @@ gst_rtsp_stream_transport_class_init (GstRTSPStreamTransportClass * klass)
 static void
 gst_rtsp_stream_transport_init (GstRTSPStreamTransport * trans)
 {
+  GstRTSPStreamTransportPrivate *priv =
+      GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE (trans);
+
+  trans->priv = priv;
 }
 
 static void
 gst_rtsp_stream_transport_finalize (GObject * obj)
 {
+  GstRTSPStreamTransportPrivate *priv;
   GstRTSPStreamTransport *trans;
 
   trans = GST_RTSP_STREAM_TRANSPORT (obj);
+  priv = trans->priv;
 
   /* remove callbacks now */
   gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
   gst_rtsp_stream_transport_set_keepalive (trans, NULL, NULL, NULL);
 
-  if (trans->transport)
-    gst_rtsp_transport_free (trans->transport);
+  if (priv->transport)
+    gst_rtsp_transport_free (priv->transport);
 
 #if 0
-  if (trans->rtpsource)
-    g_object_set_qdata (trans->rtpsource, ssrc_stream_map_key, NULL);
+  if (priv->rtpsource)
+    g_object_set_qdata (priv->rtpsource, ssrc_stream_map_key, NULL);
 #endif
 
   G_OBJECT_CLASS (gst_rtsp_stream_transport_parent_class)->finalize (obj);
@@ -92,19 +120,37 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
 GstRTSPStreamTransport *
 gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
 {
+  GstRTSPStreamTransportPrivate *priv;
   GstRTSPStreamTransport *trans;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
   g_return_val_if_fail (tr != NULL, NULL);
 
   trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL);
-  trans->stream = stream;
-  trans->transport = tr;
+  priv = trans->priv;
+  priv->stream = stream;
+  priv->transport = tr;
 
   return trans;
 }
 
 /**
+ * gst_rtsp_stream_transport_get_stream:
+ * @trans: a #GstRTSPStreamTransport
+ *
+ * Get the #GstRTSPStream used when constructing @trans.
+ *
+ * Returns: (transfer none): the stream used when constructing @trans.
+ */
+GstRTSPStream *
+gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport * trans)
+{
+  g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
+
+  return trans->priv->stream;
+}
+
+/**
  * gst_rtsp_stream_transport_set_callbacks:
  * @trans: a #GstRTSPStreamTransport
  * @send_rtp: (scope notified): a callback called when RTP should be sent
@@ -120,12 +166,18 @@ gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport * trans,
     GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp,
     gpointer user_data, GDestroyNotify notify)
 {
-  trans->send_rtp = send_rtp;
-  trans->send_rtcp = send_rtcp;
-  if (trans->notify)
-    trans->notify (trans->user_data);
-  trans->user_data = user_data;
-  trans->notify = notify;
+  GstRTSPStreamTransportPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
+
+  priv = trans->priv;
+
+  priv->send_rtp = send_rtp;
+  priv->send_rtcp = send_rtcp;
+  if (priv->notify)
+    priv->notify (priv->user_data);
+  priv->user_data = user_data;
+  priv->notify = notify;
 }
 
 /**
@@ -142,11 +194,17 @@ void
 gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport * trans,
     GstRTSPKeepAliveFunc keep_alive, gpointer user_data, GDestroyNotify notify)
 {
-  trans->keep_alive = keep_alive;
-  if (trans->ka_notify)
-    trans->ka_notify (trans->ka_user_data);
-  trans->ka_user_data = user_data;
-  trans->ka_notify = notify;
+  GstRTSPStreamTransportPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
+
+  priv = trans->priv;
+
+  priv->keep_alive = keep_alive;
+  if (priv->ka_notify)
+    priv->ka_notify (priv->ka_user_data);
+  priv->ka_user_data = user_data;
+  priv->ka_notify = notify;
 }
 
 
@@ -162,13 +220,100 @@ void
 gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
     GstRTSPTransport * tr)
 {
+  GstRTSPStreamTransportPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
   g_return_if_fail (tr != NULL);
 
+  priv = trans->priv;
+
   /* keep track of the transports in the stream. */
-  if (trans->transport)
-    gst_rtsp_transport_free (trans->transport);
-  trans->transport = tr;
+  if (priv->transport)
+    gst_rtsp_transport_free (priv->transport);
+  priv->transport = tr;
+}
+
+/**
+ * gst_rtsp_stream_transport_get_transport:
+ * @trans: a #GstRTSPStreamTransport
+ *
+ * Get the transport configured in @trans.
+ *
+ * Returns: (transfer none): the transport configured in @trans. It remains
+ *     valid for as long as @trans is valid.
+ */
+const GstRTSPTransport *
+gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans)
+{
+  g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
+
+  return trans->priv->transport;
+}
+
+/**
+ * gst_rtsp_stream_transport_set_active:
+ * @trans: a #GstRTSPStreamTransport
+ * @active: new state of @trans
+ *
+ * Activate or deactivate datatransfer configured in @trans.
+ *
+ * Returns: %TRUE when the state was changed.
+ */
+gboolean
+gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans,
+    gboolean active)
+{
+  GstRTSPStreamTransportPrivate *priv;
+  gboolean res;
+
+  g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
+
+  priv = trans->priv;
+
+  if (priv->active == active)
+    return FALSE;
+
+  if (active)
+    res = gst_rtsp_stream_add_transport (priv->stream, trans);
+  else
+    res = gst_rtsp_stream_remove_transport (priv->stream, trans);
+
+  if (res)
+    priv->active = active;
+
+  return res;
+}
+
+/**
+ * gst_rtsp_stream_transport_set_timed_out:
+ * @trans: a #GstRTSPStreamTransport
+ * @timedout: timed out value
+ *
+ * Set the timed out state of @trans to @timedout
+ */
+void
+gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans,
+    gboolean timedout)
+{
+  g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
+
+  trans->priv->timed_out = timedout;
+}
+
+/**
+ * gst_rtsp_stream_transport_is_timed_out:
+ * @trans: a #GstRTSPStreamTransport
+ *
+ * Check if @trans is timed out.
+ *
+ * Returns: %TRUE if @trans timed out.
+ */
+gboolean
+gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
+{
+  g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
+
+  return trans->priv->timed_out;
 }
 
 /**
@@ -184,12 +329,15 @@ gboolean
 gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
     GstBuffer * buffer)
 {
+  GstRTSPStreamTransportPrivate *priv;
   gboolean res = FALSE;
 
-  if (trans->send_rtp)
+  priv = trans->priv;
+
+  if (priv->send_rtp)
     res =
-        trans->send_rtp (buffer, trans->transport->interleaved.min,
-        trans->user_data);
+        priv->send_rtp (buffer, priv->transport->interleaved.min,
+        priv->user_data);
 
   return res;
 }
@@ -207,12 +355,15 @@ gboolean
 gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
     GstBuffer * buffer)
 {
+  GstRTSPStreamTransportPrivate *priv;
   gboolean res = FALSE;
 
-  if (trans->send_rtcp)
+  priv = trans->priv;
+
+  if (priv->send_rtcp)
     res =
-        trans->send_rtcp (buffer, trans->transport->interleaved.max,
-        trans->user_data);
+        priv->send_rtcp (buffer, priv->transport->interleaved.max,
+        priv->user_data);
 
   return res;
 }
@@ -226,6 +377,10 @@ gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
 void
 gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
 {
-  if (trans->keep_alive)
-    trans->keep_alive (trans->ka_user_data);
+  GstRTSPStreamTransportPrivate *priv;
+
+  priv = trans->priv;
+
+  if (priv->keep_alive)
+    priv->keep_alive (priv->ka_user_data);
 }
index 8839267..ed69faa 100644 (file)
@@ -38,9 +38,9 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPStreamTransport GstRTSPStreamTransport;
 typedef struct _GstRTSPStreamTransportClass GstRTSPStreamTransportClass;
+typedef struct _GstRTSPStreamTransportPrivate GstRTSPStreamTransportPrivate;
 
 #include "rtsp-stream.h"
-#include "rtsp-address-pool.h"
 
 typedef gboolean (*GstRTSPSendFunc)      (GstBuffer *buffer, guint8 channel, gpointer user_data);
 typedef void     (*GstRTSPKeepAliveFunc) (gpointer user_data);
@@ -48,41 +48,13 @@ typedef void     (*GstRTSPKeepAliveFunc) (gpointer user_data);
 /**
  * GstRTSPStreamTransport:
  * @parent: parent instance
- * @stream: the GstRTSPStream we manage
- * @send_rtp: callback for sending RTP messages
- * @send_rtcp: callback for sending RTCP messages
- * @user_data: user data passed in the callbacks
- * @notify: free function for the user_data.
- * @keep_alive: keep alive callback
- * @ka_user_data: data passed to @keep_alive
- * @ka_notify: called when @ka_user_data is freed
- * @active: if we are actively sending
- * @timeout: if we timed out
- * @transport: a transport description
- * @addr: an optional address
- * @rtpsource: the receiver rtp source object
  *
- * A Transport description for stream @idx
+ * A Transport description for a stream
  */
 struct _GstRTSPStreamTransport {
   GObject              parent;
 
-  GstRTSPStream       *stream;
-
-  GstRTSPSendFunc      send_rtp;
-  GstRTSPSendFunc      send_rtcp;
-  gpointer             user_data;
-  GDestroyNotify       notify;
-
-  GstRTSPKeepAliveFunc keep_alive;
-  gpointer             ka_user_data;
-  GDestroyNotify       ka_notify;
-  gboolean             active;
-  gboolean             timeout;
-
-  GstRTSPTransport    *transport;
-
-  GObject             *rtpsource;
+  GstRTSPStreamTransportPrivate *priv;
 };
 
 struct _GstRTSPStreamTransportClass {
@@ -94,8 +66,11 @@ GType                    gst_rtsp_stream_transport_get_type (void);
 GstRTSPStreamTransport * gst_rtsp_stream_transport_new           (GstRTSPStream *stream,
                                                                   GstRTSPTransport *tr);
 
+GstRTSPStream *          gst_rtsp_stream_transport_get_stream    (GstRTSPStreamTransport *trans);
+
 void                     gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport *trans,
                                                                   GstRTSPTransport * tr);
+const GstRTSPTransport * gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport *trans);
 
 void                     gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport *trans,
                                                                   GstRTSPSendFunc send_rtp,
@@ -107,6 +82,15 @@ void                     gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamT
                                                                   gpointer user_data,
                                                                   GDestroyNotify  notify);
 
+gboolean                 gst_rtsp_stream_transport_set_active    (GstRTSPStreamTransport *trans,
+                                                                  gboolean active);
+
+void                     gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport *trans,
+                                                                  gboolean timedout);
+gboolean                 gst_rtsp_stream_transport_is_timed_out  (GstRTSPStreamTransport *trans);
+
+
+
 gboolean                 gst_rtsp_stream_transport_send_rtp      (GstRTSPStreamTransport *trans,
                                                                   GstBuffer *buffer);
 gboolean                 gst_rtsp_stream_transport_send_rtcp     (GstRTSPStreamTransport *trans,
index 6e35d8f..d1776e8 100644 (file)
 
 #include "rtsp-stream.h"
 
+#define GST_RTSP_STREAM_GET_PRIVATE(obj)  \
+     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM, GstRTSPStreamPrivate))
+
+struct _GstRTSPStreamPrivate
+{
+  GMutex lock;
+  guint idx;
+  GstPad *srcpad;
+  GstElement *payloader;
+  gboolean is_ipv6;
+  guint buffer_size;
+  gboolean is_joined;
+
+  /* pads on the rtpbin */
+  GstPad *send_rtp_sink;
+  GstPad *recv_sink[2];
+  GstPad *send_src[2];
+
+  /* the RTPSession object */
+  GObject *session;
+
+  /* sinks used for sending and receiving RTP and RTCP, they share
+   * sockets */
+  GstElement *udpsrc[2];
+  GstElement *udpsink[2];
+  /* for TCP transport */
+  GstElement *appsrc[2];
+  GstElement *appqueue[2];
+  GstElement *appsink[2];
+
+  GstElement *tee[2];
+  GstElement *funnel[2];
+
+  /* server ports for sending/receiving */
+  GstRTSPRange server_port;
+
+  /* multicast addresses */
+  GstRTSPAddressPool *pool;
+  GstRTSPAddress *addr;
+
+  /* the caps of the stream */
+  gulong caps_sig;
+  GstCaps *caps;
+
+  /* transports we stream to */
+  guint n_active;
+  GList *transports;
+};
+
+
 enum
 {
   PROP_0,
@@ -47,6 +97,8 @@ gst_rtsp_stream_class_init (GstRTSPStreamClass * klass)
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (GstRTSPStreamPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->finalize = gst_rtsp_stream_finalize;
@@ -59,30 +111,36 @@ gst_rtsp_stream_class_init (GstRTSPStreamClass * klass)
 static void
 gst_rtsp_stream_init (GstRTSPStream * stream)
 {
+  GstRTSPStreamPrivate *priv = GST_RTSP_STREAM_GET_PRIVATE (stream);
+
   GST_DEBUG ("new stream %p", stream);
 
-  g_mutex_init (&stream->lock);
+  stream->priv = priv;
+
+  g_mutex_init (&priv->lock);
 }
 
 static void
 gst_rtsp_stream_finalize (GObject * obj)
 {
   GstRTSPStream *stream;
+  GstRTSPStreamPrivate *priv;
 
   stream = GST_RTSP_STREAM (obj);
+  priv = stream->priv;
 
   GST_DEBUG ("finalize stream %p", stream);
 
   /* we really need to be unjoined now */
-  g_return_if_fail (!stream->is_joined);
+  g_return_if_fail (!priv->is_joined);
 
-  if (stream->addr)
-    gst_rtsp_address_free (stream->addr);
-  if (stream->pool)
-    g_object_unref (stream->pool);
-  gst_object_unref (stream->payloader);
-  gst_object_unref (stream->srcpad);
-  g_mutex_clear (&stream->lock);
+  if (priv->addr)
+    gst_rtsp_address_free (priv->addr);
+  if (priv->pool)
+    g_object_unref (priv->pool);
+  gst_object_unref (priv->payloader);
+  gst_object_unref (priv->srcpad);
+  g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_stream_parent_class)->finalize (obj);
 }
@@ -101,6 +159,7 @@ gst_rtsp_stream_finalize (GObject * obj)
 GstRTSPStream *
 gst_rtsp_stream_new (guint idx, GstElement * payloader, GstPad * srcpad)
 {
+  GstRTSPStreamPrivate *priv;
   GstRTSPStream *stream;
 
   g_return_val_if_fail (GST_IS_ELEMENT (payloader), NULL);
@@ -108,14 +167,31 @@ gst_rtsp_stream_new (guint idx, GstElement * payloader, GstPad * srcpad)
   g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), NULL);
 
   stream = g_object_new (GST_TYPE_RTSP_STREAM, NULL);
-  stream->idx = idx;
-  stream->payloader = gst_object_ref (payloader);
-  stream->srcpad = gst_object_ref (srcpad);
+  priv = stream->priv;
+  priv->idx = idx;
+  priv->payloader = gst_object_ref (payloader);
+  priv->srcpad = gst_object_ref (srcpad);
 
   return stream;
 }
 
 /**
+ * gst_rtsp_stream_get_index:
+ * @stream: a #GstRTSPStream
+ *
+ * Get the stream index.
+ *
+ * Return: the stream index.
+ */
+guint
+gst_rtsp_stream_get_index (GstRTSPStream * stream)
+{
+  g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), -1);
+
+  return stream->priv->idx;
+}
+
+/**
  * gst_rtsp_stream_set_mtu:
  * @stream: a #GstRTSPStream
  * @mtu: a new MTU
@@ -125,11 +201,15 @@ gst_rtsp_stream_new (guint idx, GstElement * payloader, GstPad * srcpad)
 void
 gst_rtsp_stream_set_mtu (GstRTSPStream * stream, guint mtu)
 {
+  GstRTSPStreamPrivate *priv;
+
   g_return_if_fail (GST_IS_RTSP_STREAM (stream));
 
+  priv = stream->priv;
+
   GST_LOG_OBJECT (stream, "set MTU %u", mtu);
 
-  g_object_set (G_OBJECT (stream->payloader), "mtu", mtu, NULL);
+  g_object_set (G_OBJECT (priv->payloader), "mtu", mtu, NULL);
 }
 
 /**
@@ -143,11 +223,14 @@ gst_rtsp_stream_set_mtu (GstRTSPStream * stream, guint mtu)
 guint
 gst_rtsp_stream_get_mtu (GstRTSPStream * stream)
 {
+  GstRTSPStreamPrivate *priv;
   guint mtu;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), 0);
 
-  g_object_get (G_OBJECT (stream->payloader), "mtu", &mtu, NULL);
+  priv = stream->priv;
+
+  g_object_get (G_OBJECT (priv->payloader), "mtu", &mtu, NULL);
 
   return mtu;
 }
@@ -163,18 +246,21 @@ void
 gst_rtsp_stream_set_address_pool (GstRTSPStream * stream,
     GstRTSPAddressPool * pool)
 {
+  GstRTSPStreamPrivate *priv;
   GstRTSPAddressPool *old;
 
   g_return_if_fail (GST_IS_RTSP_STREAM (stream));
 
+  priv = stream->priv;
+
   GST_LOG_OBJECT (stream, "set address pool %p", pool);
 
-  g_mutex_lock (&stream->lock);
-  if ((old = stream->pool) != pool)
-    stream->pool = pool ? g_object_ref (pool) : NULL;
+  g_mutex_lock (&priv->lock);
+  if ((old = priv->pool) != pool)
+    priv->pool = pool ? g_object_ref (pool) : NULL;
   else
     old = NULL;
-  g_mutex_unlock (&stream->lock);
+  g_mutex_unlock (&priv->lock);
 
   if (old)
     g_object_unref (old);
@@ -192,14 +278,17 @@ gst_rtsp_stream_set_address_pool (GstRTSPStream * stream,
 GstRTSPAddressPool *
 gst_rtsp_stream_get_address_pool (GstRTSPStream * stream)
 {
+  GstRTSPStreamPrivate *priv;
   GstRTSPAddressPool *result;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
 
-  g_mutex_lock (&stream->lock);
-  if ((result = stream->pool))
+  priv = stream->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->pool))
     g_object_ref (result);
-  g_mutex_unlock (&stream->lock);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 }
@@ -216,20 +305,25 @@ gst_rtsp_stream_get_address_pool (GstRTSPStream * stream)
 GstRTSPAddress *
 gst_rtsp_stream_get_address (GstRTSPStream * stream)
 {
+  GstRTSPStreamPrivate *priv;
   GstRTSPAddress *result;
 
-  g_mutex_lock (&stream->lock);
-  if (stream->addr == NULL) {
-    if (stream->pool == NULL)
+  g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
+
+  priv = stream->priv;
+
+  g_mutex_lock (&priv->lock);
+  if (priv->addr == NULL) {
+    if (priv->pool == NULL)
       goto no_pool;
 
-    stream->addr = gst_rtsp_address_pool_acquire_address (stream->pool,
+    priv->addr = gst_rtsp_address_pool_acquire_address (priv->pool,
         GST_RTSP_ADDRESS_FLAG_EVEN_PORT, 2);
-    if (stream->addr == NULL)
+    if (priv->addr == NULL)
       goto no_address;
   }
-  result = gst_rtsp_address_copy (stream->addr);
-  g_mutex_unlock (&stream->lock);
+  result = gst_rtsp_address_copy (priv->addr);
+  g_mutex_unlock (&priv->lock);
 
   return result;
 
@@ -237,13 +331,13 @@ gst_rtsp_stream_get_address (GstRTSPStream * stream)
 no_pool:
   {
     GST_ERROR_OBJECT (stream, "no address pool specified");
-    g_mutex_unlock (&stream->lock);
+    g_mutex_unlock (&priv->lock);
     return NULL;
   }
 no_address:
   {
     GST_ERROR_OBJECT (stream, "failed to acquire address from pool");
-    g_mutex_unlock (&stream->lock);
+    g_mutex_unlock (&priv->lock);
     return NULL;
   }
 }
@@ -252,6 +346,7 @@ no_address:
 static gboolean
 alloc_ports (GstRTSPStream * stream)
 {
+  GstRTSPStreamPrivate *priv = stream->priv;
   GstStateChangeReturn ret;
   GstElement *udpsrc0, *udpsrc1;
   GstElement *udpsink0, *udpsink1;
@@ -261,8 +356,6 @@ alloc_ports (GstRTSPStream * stream)
   GSocket *socket;
   const gchar *host;
 
-  g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
-
   udpsrc0 = NULL;
   udpsrc1 = NULL;
   udpsink0 = NULL;
@@ -272,7 +365,7 @@ alloc_ports (GstRTSPStream * stream)
   /* Start with random port */
   tmp_rtp = 0;
 
-  if (stream->is_ipv6)
+  if (priv->is_ipv6)
     host = "udp://[::0]";
   else
     host = "udp://0.0.0.0";
@@ -372,8 +465,7 @@ again:
 
   if (g_object_class_find_property (G_OBJECT_GET_CLASS (udpsink0),
           "buffer-size")) {
-    g_object_set (G_OBJECT (udpsink0), "buffer-size", stream->buffer_size,
-        NULL);
+    g_object_set (G_OBJECT (udpsink0), "buffer-size", priv->buffer_size, NULL);
   } else {
     GST_WARNING ("multiudpsink version found without buffer-size property");
   }
@@ -391,12 +483,12 @@ again:
 
   /* we keep these elements, we will further configure them when the
    * client told us to really use the UDP ports. */
-  stream->udpsrc[0] = udpsrc0;
-  stream->udpsrc[1] = udpsrc1;
-  stream->udpsink[0] = udpsink0;
-  stream->udpsink[1] = udpsink1;
-  stream->server_port.min = rtpport;
-  stream->server_port.max = rtcpport;
+  priv->udpsrc[0] = udpsrc0;
+  priv->udpsrc[1] = udpsrc1;
+  priv->udpsink[0] = udpsink0;
+  priv->udpsink[1] = udpsink1;
+  priv->server_port.min = rtpport;
+  priv->server_port.max = rtcpport;
 
   return TRUE;
 
@@ -439,10 +531,58 @@ cleanup:
   }
 }
 
+/**
+ * gst_rtsp_stream_get_server_port:
+ * @stream: a #GstRTSPStream
+ * @server_port: (out): result server port
+ *
+ * Fill @server_port with the port pair used by the server. This function can
+ * only be called when @stream has been joined.
+ */
+void
+gst_rtsp_stream_get_server_port (GstRTSPStream * stream,
+    GstRTSPRange * server_port)
+{
+  GstRTSPStreamPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_STREAM (stream));
+  priv = stream->priv;
+  g_return_if_fail (priv->is_joined);
+
+  g_mutex_lock (&priv->lock);
+  if (server_port)
+    *server_port = priv->server_port;
+  g_mutex_unlock (&priv->lock);
+}
+
+/**
+ * gst_rtsp_stream_get_ssrc:
+ * @stream: a #GstRTSPStream
+ * @ssrc: (out): result ssrc
+ *
+ * Get the SSRC used by the RTP session of this stream. This function can only
+ * be called when @stream has been joined.
+ */
+void
+gst_rtsp_stream_get_ssrc (GstRTSPStream * stream, guint * ssrc)
+{
+  GstRTSPStreamPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_STREAM (stream));
+  priv = stream->priv;
+  g_return_if_fail (priv->is_joined);
+
+  g_mutex_lock (&priv->lock);
+  if (ssrc && priv->session)
+    g_object_get (priv->session, "internal-ssrc", ssrc, NULL);
+  g_mutex_unlock (&priv->lock);
+}
+
 /* executed from streaming thread */
 static void
 caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPStream * stream)
 {
+  GstRTSPStreamPrivate *priv = stream->priv;
   GstCaps *newcaps, *oldcaps;
 
   newcaps = gst_pad_get_current_caps (pad);
@@ -450,10 +590,10 @@ caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPStream * stream)
   GST_INFO ("stream %p received caps %p, %" GST_PTR_FORMAT, stream, newcaps,
       newcaps);
 
-  g_mutex_lock (&stream->lock);
-  oldcaps = stream->caps;
-  stream->caps = newcaps;
-  g_mutex_unlock (&stream->lock);
+  g_mutex_lock (&priv->lock);
+  oldcaps = priv->caps;
+  priv->caps = newcaps;
+  g_mutex_unlock (&priv->lock);
 
   if (oldcaps)
     gst_caps_unref (oldcaps);
@@ -472,6 +612,7 @@ dump_structure (const GstStructure * s)
 static GstRTSPStreamTransport *
 find_transport (GstRTSPStream * stream, const gchar * rtcp_from)
 {
+  GstRTSPStreamPrivate *priv = stream->priv;
   GList *walk;
   GstRTSPStreamTransport *result = NULL;
   const gchar *tmp;
@@ -488,24 +629,26 @@ find_transport (GstRTSPStream * stream, const gchar * rtcp_from)
   port = atoi (tmp + 1);
   dest = g_strndup (rtcp_from, tmp - rtcp_from);
 
-  g_mutex_lock (&stream->lock);
+  g_mutex_lock (&priv->lock);
   GST_INFO ("finding %s:%d in %d transports", dest, port,
-      g_list_length (stream->transports));
+      g_list_length (priv->transports));
 
-  for (walk = stream->transports; walk; walk = g_list_next (walk)) {
+  for (walk = priv->transports; walk; walk = g_list_next (walk)) {
     GstRTSPStreamTransport *trans = walk->data;
+    const GstRTSPTransport *tr;
     gint min, max;
 
-    min = trans->transport->client_port.min;
-    max = trans->transport->client_port.max;
+    tr = gst_rtsp_stream_transport_get_transport (trans);
+
+    min = tr->client_port.min;
+    max = tr->client_port.max;
 
-    if ((strcmp (trans->transport->destination, dest) == 0) && (min == port
-            || max == port)) {
+    if ((strcmp (tr->destination, dest) == 0) && (min == port || max == port)) {
       result = trans;
       break;
     }
   }
-  g_mutex_unlock (&stream->lock);
+  g_mutex_unlock (&priv->lock);
 
   g_free (dest);
 
@@ -531,16 +674,11 @@ check_transport (GObject * source, GstRTSPStream * stream)
       if ((trans = find_transport (stream, rtcp_from))) {
         GST_INFO ("%p: found transport %p for source  %p", stream, trans,
             source);
-
-        /* keep ref to the source */
-        trans->rtpsource = source;
-
         g_object_set_qdata (source, ssrc_stream_map_key, trans);
       }
       gst_structure_free (stats);
     }
   }
-
   return trans;
 }
 
@@ -601,8 +739,7 @@ on_bye_timeout (GObject * session, GObject * source, GstRTSPStream * stream)
   GST_INFO ("%p: source %p bye timeout", stream, source);
 
   if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) {
-    trans->rtpsource = NULL;
-    trans->timeout = TRUE;
+    gst_rtsp_stream_transport_set_timed_out (trans, TRUE);
   }
 }
 
@@ -614,14 +751,14 @@ on_timeout (GObject * session, GObject * source, GstRTSPStream * stream)
   GST_INFO ("%p: source %p timeout", stream, source);
 
   if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) {
-    trans->rtpsource = NULL;
-    trans->timeout = TRUE;
+    gst_rtsp_stream_transport_set_timed_out (trans, TRUE);
   }
 }
 
 static GstFlowReturn
 handle_new_sample (GstAppSink * sink, gpointer user_data)
 {
+  GstRTSPStreamPrivate *priv;
   GList *walk;
   GstSample *sample;
   GstBuffer *buffer;
@@ -632,19 +769,20 @@ handle_new_sample (GstAppSink * sink, gpointer user_data)
     return GST_FLOW_OK;
 
   stream = (GstRTSPStream *) user_data;
+  priv = stream->priv;
   buffer = gst_sample_get_buffer (sample);
 
-  g_mutex_lock (&stream->lock);
-  for (walk = stream->transports; walk; walk = g_list_next (walk)) {
+  g_mutex_lock (&priv->lock);
+  for (walk = priv->transports; walk; walk = g_list_next (walk)) {
     GstRTSPStreamTransport *tr = (GstRTSPStreamTransport *) walk->data;
 
-    if (GST_ELEMENT_CAST (sink) == stream->appsink[0]) {
+    if (GST_ELEMENT_CAST (sink) == priv->appsink[0]) {
       gst_rtsp_stream_transport_send_rtp (tr, buffer);
     } else {
       gst_rtsp_stream_transport_send_rtcp (tr, buffer);
     }
   }
-  g_mutex_unlock (&stream->lock);
+  g_mutex_unlock (&priv->lock);
 
   gst_sample_unref (sample);
 
@@ -675,6 +813,7 @@ gboolean
 gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
     GstElement * rtpbin, GstState state)
 {
+  GstRTSPStreamPrivate *priv;
   gint i, idx;
   gchar *name;
   GstPad *pad, *teepad, *queuepad, *selpad;
@@ -684,12 +823,14 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
   g_return_val_if_fail (GST_IS_ELEMENT (rtpbin), FALSE);
 
-  g_mutex_lock (&stream->lock);
-  if (stream->is_joined)
+  priv = stream->priv;
+
+  g_mutex_lock (&priv->lock);
+  if (priv->is_joined)
     goto was_joined;
 
   /* create a session with the same index as the stream */
-  idx = stream->idx;
+  idx = priv->idx;
 
   GST_INFO ("stream %p joining bin as session %d", stream, idx);
 
@@ -698,43 +839,43 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
 
   /* get a pad for sending RTP */
   name = g_strdup_printf ("send_rtp_sink_%u", idx);
-  stream->send_rtp_sink = gst_element_get_request_pad (rtpbin, name);
+  priv->send_rtp_sink = gst_element_get_request_pad (rtpbin, name);
   g_free (name);
   /* link the RTP pad to the session manager, it should not really fail unless
    * this is not really an RTP pad */
-  ret = gst_pad_link (stream->srcpad, stream->send_rtp_sink);
+  ret = gst_pad_link (priv->srcpad, priv->send_rtp_sink);
   if (ret != GST_PAD_LINK_OK)
     goto link_failed;
 
   /* get pads from the RTP session element for sending and receiving
    * RTP/RTCP*/
   name = g_strdup_printf ("send_rtp_src_%u", idx);
-  stream->send_src[0] = gst_element_get_static_pad (rtpbin, name);
+  priv->send_src[0] = gst_element_get_static_pad (rtpbin, name);
   g_free (name);
   name = g_strdup_printf ("send_rtcp_src_%u", idx);
-  stream->send_src[1] = gst_element_get_request_pad (rtpbin, name);
+  priv->send_src[1] = gst_element_get_request_pad (rtpbin, name);
   g_free (name);
   name = g_strdup_printf ("recv_rtp_sink_%u", idx);
-  stream->recv_sink[0] = gst_element_get_request_pad (rtpbin, name);
+  priv->recv_sink[0] = gst_element_get_request_pad (rtpbin, name);
   g_free (name);
   name = g_strdup_printf ("recv_rtcp_sink_%u", idx);
-  stream->recv_sink[1] = gst_element_get_request_pad (rtpbin, name);
+  priv->recv_sink[1] = gst_element_get_request_pad (rtpbin, name);
   g_free (name);
 
   /* get the session */
-  g_signal_emit_by_name (rtpbin, "get-internal-session", idx, &stream->session);
+  g_signal_emit_by_name (rtpbin, "get-internal-session", idx, &priv->session);
 
-  g_signal_connect (stream->session, "on-new-ssrc", (GCallback) on_new_ssrc,
+  g_signal_connect (priv->session, "on-new-ssrc", (GCallback) on_new_ssrc,
       stream);
-  g_signal_connect (stream->session, "on-ssrc-sdes", (GCallback) on_ssrc_sdes,
+  g_signal_connect (priv->session, "on-ssrc-sdes", (GCallback) on_ssrc_sdes,
       stream);
-  g_signal_connect (stream->session, "on-ssrc-active",
+  g_signal_connect (priv->session, "on-ssrc-active",
       (GCallback) on_ssrc_active, stream);
-  g_signal_connect (stream->session, "on-bye-ssrc", (GCallback) on_bye_ssrc,
+  g_signal_connect (priv->session, "on-bye-ssrc", (GCallback) on_bye_ssrc,
       stream);
-  g_signal_connect (stream->session, "on-bye-timeout",
+  g_signal_connect (priv->session, "on-bye-timeout",
       (GCallback) on_bye_timeout, stream);
-  g_signal_connect (stream->session, "on-timeout", (GCallback) on_timeout,
+  g_signal_connect (priv->session, "on-timeout", (GCallback) on_timeout,
       stream);
 
   for (i = 0; i < 2; i++) {
@@ -754,44 +895,44 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
      *                 '-----'    '---------'    '---------'
      */
     /* make tee for RTP/RTCP */
-    stream->tee[i] = gst_element_factory_make ("tee", NULL);
-    gst_bin_add (bin, stream->tee[i]);
+    priv->tee[i] = gst_element_factory_make ("tee", NULL);
+    gst_bin_add (bin, priv->tee[i]);
 
     /* and link to rtpbin send pad */
-    pad = gst_element_get_static_pad (stream->tee[i], "sink");
-    gst_pad_link (stream->send_src[i], pad);
+    pad = gst_element_get_static_pad (priv->tee[i], "sink");
+    gst_pad_link (priv->send_src[i], pad);
     gst_object_unref (pad);
 
     /* add udpsink */
-    gst_bin_add (bin, stream->udpsink[i]);
+    gst_bin_add (bin, priv->udpsink[i]);
 
     /* link tee to udpsink */
-    teepad = gst_element_get_request_pad (stream->tee[i], "src_%u");
-    pad = gst_element_get_static_pad (stream->udpsink[i], "sink");
+    teepad = gst_element_get_request_pad (priv->tee[i], "src_%u");
+    pad = gst_element_get_static_pad (priv->udpsink[i], "sink");
     gst_pad_link (teepad, pad);
     gst_object_unref (pad);
     gst_object_unref (teepad);
 
     /* make queue */
-    stream->appqueue[i] = gst_element_factory_make ("queue", NULL);
-    gst_bin_add (bin, stream->appqueue[i]);
+    priv->appqueue[i] = gst_element_factory_make ("queue", NULL);
+    gst_bin_add (bin, priv->appqueue[i]);
     /* and link to tee */
-    teepad = gst_element_get_request_pad (stream->tee[i], "src_%u");
-    pad = gst_element_get_static_pad (stream->appqueue[i], "sink");
+    teepad = gst_element_get_request_pad (priv->tee[i], "src_%u");
+    pad = gst_element_get_static_pad (priv->appqueue[i], "sink");
     gst_pad_link (teepad, pad);
     gst_object_unref (pad);
     gst_object_unref (teepad);
 
     /* make appsink */
-    stream->appsink[i] = gst_element_factory_make ("appsink", NULL);
-    g_object_set (stream->appsink[i], "async", FALSE, "sync", FALSE, NULL);
-    g_object_set (stream->appsink[i], "emit-signals", FALSE, NULL);
-    gst_bin_add (bin, stream->appsink[i]);
-    gst_app_sink_set_callbacks (GST_APP_SINK_CAST (stream->appsink[i]),
+    priv->appsink[i] = gst_element_factory_make ("appsink", NULL);
+    g_object_set (priv->appsink[i], "async", FALSE, "sync", FALSE, NULL);
+    g_object_set (priv->appsink[i], "emit-signals", FALSE, NULL);
+    gst_bin_add (bin, priv->appsink[i]);
+    gst_app_sink_set_callbacks (GST_APP_SINK_CAST (priv->appsink[i]),
         &sink_cb, stream, NULL);
     /* and link to queue */
-    queuepad = gst_element_get_static_pad (stream->appqueue[i], "src");
-    pad = gst_element_get_static_pad (stream->appsink[i], "sink");
+    queuepad = gst_element_get_static_pad (priv->appqueue[i], "src");
+    pad = gst_element_get_static_pad (priv->appsink[i], "sink");
     gst_pad_link (queuepad, pad);
     gst_object_unref (pad);
     gst_object_unref (queuepad);
@@ -810,74 +951,74 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
      * '--------'     '--------'
      */
     /* make funnel for the RTP/RTCP receivers */
-    stream->funnel[i] = gst_element_factory_make ("funnel", NULL);
-    gst_bin_add (bin, stream->funnel[i]);
+    priv->funnel[i] = gst_element_factory_make ("funnel", NULL);
+    gst_bin_add (bin, priv->funnel[i]);
 
-    pad = gst_element_get_static_pad (stream->funnel[i], "src");
-    gst_pad_link (pad, stream->recv_sink[i]);
+    pad = gst_element_get_static_pad (priv->funnel[i], "src");
+    gst_pad_link (pad, priv->recv_sink[i]);
     gst_object_unref (pad);
 
     /* we set and keep these to playing so that they don't cause NO_PREROLL return
      * values */
-    gst_element_set_state (stream->udpsrc[i], GST_STATE_PLAYING);
-    gst_element_set_locked_state (stream->udpsrc[i], TRUE);
+    gst_element_set_state (priv->udpsrc[i], GST_STATE_PLAYING);
+    gst_element_set_locked_state (priv->udpsrc[i], TRUE);
     /* add udpsrc */
-    gst_bin_add (bin, stream->udpsrc[i]);
+    gst_bin_add (bin, priv->udpsrc[i]);
     /* and link to the funnel */
-    selpad = gst_element_get_request_pad (stream->funnel[i], "sink_%u");
-    pad = gst_element_get_static_pad (stream->udpsrc[i], "src");
+    selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
+    pad = gst_element_get_static_pad (priv->udpsrc[i], "src");
     gst_pad_link (pad, selpad);
     gst_object_unref (pad);
     gst_object_unref (selpad);
 
     /* make and add appsrc */
-    stream->appsrc[i] = gst_element_factory_make ("appsrc", NULL);
-    gst_bin_add (bin, stream->appsrc[i]);
+    priv->appsrc[i] = gst_element_factory_make ("appsrc", NULL);
+    gst_bin_add (bin, priv->appsrc[i]);
     /* and link to the funnel */
-    selpad = gst_element_get_request_pad (stream->funnel[i], "sink_%u");
-    pad = gst_element_get_static_pad (stream->appsrc[i], "src");
+    selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
+    pad = gst_element_get_static_pad (priv->appsrc[i], "src");
     gst_pad_link (pad, selpad);
     gst_object_unref (pad);
     gst_object_unref (selpad);
 
     /* check if we need to set to a special state */
     if (state != GST_STATE_NULL) {
-      gst_element_set_state (stream->udpsink[i], state);
-      gst_element_set_state (stream->appsink[i], state);
-      gst_element_set_state (stream->appqueue[i], state);
-      gst_element_set_state (stream->tee[i], state);
-      gst_element_set_state (stream->funnel[i], state);
-      gst_element_set_state (stream->appsrc[i], state);
+      gst_element_set_state (priv->udpsink[i], state);
+      gst_element_set_state (priv->appsink[i], state);
+      gst_element_set_state (priv->appqueue[i], state);
+      gst_element_set_state (priv->tee[i], state);
+      gst_element_set_state (priv->funnel[i], state);
+      gst_element_set_state (priv->appsrc[i], state);
     }
   }
 
   /* be notified of caps changes */
-  stream->caps_sig = g_signal_connect (stream->send_rtp_sink, "notify::caps",
+  priv->caps_sig = g_signal_connect (priv->send_rtp_sink, "notify::caps",
       (GCallback) caps_notify, stream);
 
-  stream->is_joined = TRUE;
-  g_mutex_unlock (&stream->lock);
+  priv->is_joined = TRUE;
+  g_mutex_unlock (&priv->lock);
 
   return TRUE;
 
   /* ERRORS */
 was_joined:
   {
-    g_mutex_unlock (&stream->lock);
+    g_mutex_unlock (&priv->lock);
     return TRUE;
   }
 no_ports:
   {
-    g_mutex_unlock (&stream->lock);
+    g_mutex_unlock (&priv->lock);
     GST_WARNING ("failed to allocate ports %d", idx);
     return FALSE;
   }
 link_failed:
   {
     GST_WARNING ("failed to link stream %d", idx);
-    gst_object_unref (stream->send_rtp_sink);
-    stream->send_rtp_sink = NULL;
-    g_mutex_unlock (&stream->lock);
+    gst_object_unref (priv->send_rtp_sink);
+    priv->send_rtp_sink = NULL;
+    g_mutex_unlock (&priv->lock);
     return FALSE;
   }
 }
@@ -897,67 +1038,70 @@ gboolean
 gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
     GstElement * rtpbin)
 {
+  GstRTSPStreamPrivate *priv;
   gint i;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
   g_return_val_if_fail (GST_IS_ELEMENT (rtpbin), FALSE);
 
-  g_mutex_lock (&stream->lock);
-  if (!stream->is_joined)
+  priv = stream->priv;
+
+  g_mutex_lock (&priv->lock);
+  if (!priv->is_joined)
     goto was_not_joined;
 
   /* all transports must be removed by now */
-  g_return_val_if_fail (stream->transports == NULL, FALSE);
+  g_return_val_if_fail (priv->transports == NULL, FALSE);
 
   GST_INFO ("stream %p leaving bin", stream);
 
-  gst_pad_unlink (stream->srcpad, stream->send_rtp_sink);
-  g_signal_handler_disconnect (stream->send_rtp_sink, stream->caps_sig);
-  gst_element_release_request_pad (rtpbin, stream->send_rtp_sink);
-  gst_object_unref (stream->send_rtp_sink);
-  stream->send_rtp_sink = NULL;
+  gst_pad_unlink (priv->srcpad, priv->send_rtp_sink);
+  g_signal_handler_disconnect (priv->send_rtp_sink, priv->caps_sig);
+  gst_element_release_request_pad (rtpbin, priv->send_rtp_sink);
+  gst_object_unref (priv->send_rtp_sink);
+  priv->send_rtp_sink = NULL;
 
   for (i = 0; i < 2; i++) {
     /* and set udpsrc to NULL now before removing */
-    gst_element_set_locked_state (stream->udpsrc[i], FALSE);
-    gst_element_set_state (stream->udpsrc[i], GST_STATE_NULL);
+    gst_element_set_locked_state (priv->udpsrc[i], FALSE);
+    gst_element_set_state (priv->udpsrc[i], GST_STATE_NULL);
 
     /* removing them should also nicely release the request
      * pads when they finalize */
-    gst_bin_remove (bin, stream->udpsrc[i]);
-    gst_bin_remove (bin, stream->udpsink[i]);
-    gst_bin_remove (bin, stream->appsrc[i]);
-    gst_bin_remove (bin, stream->appsink[i]);
-    gst_bin_remove (bin, stream->appqueue[i]);
-    gst_bin_remove (bin, stream->tee[i]);
-    gst_bin_remove (bin, stream->funnel[i]);
-
-    gst_element_release_request_pad (rtpbin, stream->recv_sink[i]);
-    gst_object_unref (stream->recv_sink[i]);
-    stream->recv_sink[i] = NULL;
-
-    stream->udpsrc[i] = NULL;
-    stream->udpsink[i] = NULL;
-    stream->appsrc[i] = NULL;
-    stream->appsink[i] = NULL;
-    stream->appqueue[i] = NULL;
-    stream->tee[i] = NULL;
-    stream->funnel[i] = NULL;
+    gst_bin_remove (bin, priv->udpsrc[i]);
+    gst_bin_remove (bin, priv->udpsink[i]);
+    gst_bin_remove (bin, priv->appsrc[i]);
+    gst_bin_remove (bin, priv->appsink[i]);
+    gst_bin_remove (bin, priv->appqueue[i]);
+    gst_bin_remove (bin, priv->tee[i]);
+    gst_bin_remove (bin, priv->funnel[i]);
+
+    gst_element_release_request_pad (rtpbin, priv->recv_sink[i]);
+    gst_object_unref (priv->recv_sink[i]);
+    priv->recv_sink[i] = NULL;
+
+    priv->udpsrc[i] = NULL;
+    priv->udpsink[i] = NULL;
+    priv->appsrc[i] = NULL;
+    priv->appsink[i] = NULL;
+    priv->appqueue[i] = NULL;
+    priv->tee[i] = NULL;
+    priv->funnel[i] = NULL;
   }
-  gst_object_unref (stream->send_src[0]);
-  stream->send_src[0] = NULL;
+  gst_object_unref (priv->send_src[0]);
+  priv->send_src[0] = NULL;
 
-  gst_element_release_request_pad (rtpbin, stream->send_src[1]);
-  gst_object_unref (stream->send_src[1]);
-  stream->send_src[1] = NULL;
+  gst_element_release_request_pad (rtpbin, priv->send_src[1]);
+  gst_object_unref (priv->send_src[1]);
+  priv->send_src[1] = NULL;
 
-  g_object_unref (stream->session);
-  if (stream->caps)
-    gst_caps_unref (stream->caps);
+  g_object_unref (priv->session);
+  if (priv->caps)
+    gst_caps_unref (priv->caps);
 
-  stream->is_joined = FALSE;
-  g_mutex_unlock (&stream->lock);
+  priv->is_joined = FALSE;
+  g_mutex_unlock (&priv->lock);
 
   return TRUE;
 
@@ -982,20 +1126,54 @@ gboolean
 gst_rtsp_stream_get_rtpinfo (GstRTSPStream * stream,
     guint * rtptime, guint * seq)
 {
+  GstRTSPStreamPrivate *priv;
   GObjectClass *payobjclass;
 
-  payobjclass = G_OBJECT_GET_CLASS (stream->payloader);
+  g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
+  g_return_val_if_fail (rtptime != NULL, FALSE);
+  g_return_val_if_fail (seq != NULL, FALSE);
+
+  priv = stream->priv;
+
+  payobjclass = G_OBJECT_GET_CLASS (priv->payloader);
 
   if (!g_object_class_find_property (payobjclass, "seqnum") ||
       !g_object_class_find_property (payobjclass, "timestamp"))
     return FALSE;
 
-  g_object_get (stream->payloader, "seqnum", seq, "timestamp", rtptime, NULL);
+  g_object_get (priv->payloader, "seqnum", seq, "timestamp", rtptime, NULL);
 
   return TRUE;
 }
 
 /**
+ * gst_rtsp_stream_get_caps:
+ * @stream: a #GstRTSPStream
+ *
+ * Retrieve the current caps of @stream.
+ *
+ * Returns: (transfer full): the #GstCaps of @stream. use gst_caps_unref()
+ *    after usage.
+ */
+GstCaps *
+gst_rtsp_stream_get_caps (GstRTSPStream * stream)
+{
+  GstRTSPStreamPrivate *priv;
+  GstCaps *result;
+
+  g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
+
+  priv = stream->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->caps))
+    gst_caps_ref (result);
+  g_mutex_unlock (&priv->lock);
+
+  return result;
+}
+
+/**
  * gst_rtsp_stream_recv_rtp:
  * @stream: a #GstRTSPStream
  * @buffer: (transfer full): a #GstBuffer
@@ -1010,16 +1188,18 @@ gst_rtsp_stream_get_rtpinfo (GstRTSPStream * stream,
 GstFlowReturn
 gst_rtsp_stream_recv_rtp (GstRTSPStream * stream, GstBuffer * buffer)
 {
+  GstRTSPStreamPrivate *priv;
   GstFlowReturn ret;
   GstElement *element;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), GST_FLOW_ERROR);
+  priv = stream->priv;
   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
-  g_return_val_if_fail (stream->is_joined, FALSE);
+  g_return_val_if_fail (priv->is_joined, FALSE);
 
-  g_mutex_lock (&stream->lock);
-  element = gst_object_ref (stream->appsrc[0]);
-  g_mutex_unlock (&stream->lock);
+  g_mutex_lock (&priv->lock);
+  element = gst_object_ref (priv->appsrc[0]);
+  g_mutex_unlock (&priv->lock);
 
   ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (element), buffer);
 
@@ -1043,16 +1223,18 @@ gst_rtsp_stream_recv_rtp (GstRTSPStream * stream, GstBuffer * buffer)
 GstFlowReturn
 gst_rtsp_stream_recv_rtcp (GstRTSPStream * stream, GstBuffer * buffer)
 {
+  GstRTSPStreamPrivate *priv;
   GstFlowReturn ret;
   GstElement *element;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), GST_FLOW_ERROR);
+  priv = stream->priv;
   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
-  g_return_val_if_fail (stream->is_joined, FALSE);
+  g_return_val_if_fail (priv->is_joined, FALSE);
 
-  g_mutex_lock (&stream->lock);
-  element = gst_object_ref (stream->appsrc[1]);
-  g_mutex_unlock (&stream->lock);
+  g_mutex_lock (&priv->lock);
+  element = gst_object_ref (priv->appsrc[1]);
+  g_mutex_unlock (&priv->lock);
 
   ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (element), buffer);
 
@@ -1066,12 +1248,10 @@ static gboolean
 update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans,
     gboolean add)
 {
-  GstRTSPTransport *tr;
-  gboolean updated;
+  GstRTSPStreamPrivate *priv = stream->priv;
+  const GstRTSPTransport *tr;
 
-  updated = FALSE;
-
-  tr = trans->transport;
+  tr = gst_rtsp_stream_transport_get_transport (trans);
 
   switch (tr->lower_transport) {
     case GST_RTSP_LOWER_TRANS_UDP:
@@ -1091,46 +1271,44 @@ update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans,
         max = tr->client_port.max;
       }
 
-      if (add && !trans->active) {
+      if (add) {
         GST_INFO ("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);
+        g_signal_emit_by_name (priv->udpsink[0], "add", dest, min, NULL);
+        g_signal_emit_by_name (priv->udpsink[1], "add", dest, max, NULL);
         if (ttl > 0) {
           GST_INFO ("setting ttl-mc %d", ttl);
-          g_object_set (G_OBJECT (stream->udpsink[0]), "ttl-mc", ttl, NULL);
-          g_object_set (G_OBJECT (stream->udpsink[1]), "ttl-mc", ttl, NULL);
+          g_object_set (G_OBJECT (priv->udpsink[0]), "ttl-mc", ttl, NULL);
+          g_object_set (G_OBJECT (priv->udpsink[1]), "ttl-mc", ttl, NULL);
         }
-        stream->transports = g_list_prepend (stream->transports, trans);
-        trans->active = TRUE;
-        updated = TRUE;
-      } else if (trans->active) {
+        priv->transports = g_list_prepend (priv->transports, trans);
+      } else {
         GST_INFO ("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);
-        stream->transports = g_list_remove (stream->transports, trans);
-        trans->active = FALSE;
-        updated = TRUE;
+        g_signal_emit_by_name (priv->udpsink[0], "remove", dest, min, NULL);
+        g_signal_emit_by_name (priv->udpsink[1], "remove", dest, max, NULL);
+        priv->transports = g_list_remove (priv->transports, trans);
       }
       break;
     }
     case GST_RTSP_LOWER_TRANS_TCP:
-      if (add && !trans->active) {
+      if (add) {
         GST_INFO ("adding TCP %s", tr->destination);
-        stream->transports = g_list_prepend (stream->transports, trans);
-        trans->active = TRUE;
-        updated = TRUE;
-      } else if (trans->active) {
+        priv->transports = g_list_prepend (priv->transports, trans);
+      } else {
         GST_INFO ("removing TCP %s", tr->destination);
-        stream->transports = g_list_remove (stream->transports, trans);
-        trans->active = FALSE;
-        updated = TRUE;
+        priv->transports = g_list_remove (priv->transports, trans);
       }
       break;
     default:
-      GST_INFO ("Unknown transport %d", tr->lower_transport);
-      break;
+      goto unknown_transport;
+  }
+  return TRUE;
+
+  /* ERRORS */
+unknown_transport:
+  {
+    GST_INFO ("Unknown transport %d", tr->lower_transport);
+    return FALSE;
   }
-  return updated;
 }
 
 
@@ -1152,16 +1330,17 @@ gboolean
 gst_rtsp_stream_add_transport (GstRTSPStream * stream,
     GstRTSPStreamTransport * trans)
 {
+  GstRTSPStreamPrivate *priv;
   gboolean res;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
+  priv = stream->priv;
   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
-  g_return_val_if_fail (stream->is_joined, FALSE);
-  g_return_val_if_fail (trans->transport != NULL, FALSE);
+  g_return_val_if_fail (priv->is_joined, FALSE);
 
-  g_mutex_lock (&stream->lock);
+  g_mutex_lock (&priv->lock);
   res = update_transport (stream, trans, TRUE);
-  g_mutex_unlock (&stream->lock);
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
@@ -1184,16 +1363,17 @@ gboolean
 gst_rtsp_stream_remove_transport (GstRTSPStream * stream,
     GstRTSPStreamTransport * trans)
 {
+  GstRTSPStreamPrivate *priv;
   gboolean res;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
+  priv = stream->priv;
   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
-  g_return_val_if_fail (stream->is_joined, FALSE);
-  g_return_val_if_fail (trans->transport != NULL, FALSE);
+  g_return_val_if_fail (priv->is_joined, FALSE);
 
-  g_mutex_lock (&stream->lock);
+  g_mutex_lock (&priv->lock);
   res = update_transport (stream, trans, FALSE);
-  g_mutex_unlock (&stream->lock);
+  g_mutex_unlock (&priv->lock);
 
   return res;
 }
index bdb50c2..3367fe2 100644 (file)
@@ -38,6 +38,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstRTSPStream GstRTSPStream;
 typedef struct _GstRTSPStreamClass GstRTSPStreamClass;
+typedef struct _GstRTSPStreamPrivate GstRTSPStreamPrivate;
 
 #include "rtsp-stream-transport.h"
 #include "rtsp-address-pool.h"
@@ -45,79 +46,13 @@ typedef struct _GstRTSPStreamClass GstRTSPStreamClass;
 /**
  * GstRTSPStream:
  * @parent: the parent instance
- * @lock: mutex protecting the stream
- * @idx: the stream index
- * @srcpad: the srcpad of the stream
- * @payloader: the payloader of the format
- * @is_ipv6: should this stream be IPv6
- * @buffer_size: the UDP buffer size
- * @is_joined: if the stream is joined in a bin
- * @send_rtp_sink: sinkpad for sending RTP buffers
- * @recv_sink: sinkpad for receiving RTP/RTCP buffers
- * @send_src: srcpad for sending RTP/RTCP buffers
- * @session: the RTP session object
- * @udpsrc: the udp source elements for RTP/RTCP
- * @udpsink: the udp sink elements for RTP/RTCP
- * @appsrc: the app source elements for RTP/RTCP
- * @appqueue: the app queue elements for RTP/RTCP
- * @appsink: the app sink elements for RTP/RTCP
- * @tee: tee for the sending to udpsink and appsink
- * @funnel: tee for the receiving from udpsrc and appsrc
- * @server_port: the server ports for this stream
- * @pool: the address pool for this stream
- * @addr: the address for this stream
- * @caps_sig: the signal id for detecting caps
- * @caps: the caps of the stream
- * @n_active: the number of active transports in @transports
- * @transports: list of #GstStreamTransport being streamed to
  *
- * The definition of a media stream. The streams are identified by @idx.
+ * The definition of a media stream.
  */
 struct _GstRTSPStream {
   GObject       parent;
 
-  GMutex        lock;
-  guint         idx;
-  GstPad       *srcpad;
-  GstElement   *payloader;
-  gboolean      is_ipv6;
-  guint         buffer_size;
-  gboolean      is_joined;
-
-  /* pads on the rtpbin */
-  GstPad       *send_rtp_sink;
-  GstPad       *recv_sink[2];
-  GstPad       *send_src[2];
-
-  /* the RTPSession object */
-  GObject      *session;
-
-  /* sinks used for sending and receiving RTP and RTCP, they share
-   * sockets */
-  GstElement   *udpsrc[2];
-  GstElement   *udpsink[2];
-  /* for TCP transport */
-  GstElement   *appsrc[2];
-  GstElement   *appqueue[2];
-  GstElement   *appsink[2];
-
-  GstElement   *tee[2];
-  GstElement   *funnel[2];
-
-  /* server ports for sending/receiving */
-  GstRTSPRange  server_port;
-
-  /* multicast addresses */
-  GstRTSPAddressPool *pool;
-  GstRTSPAddress     *addr;
-
-  /* the caps of the stream */
-  gulong        caps_sig;
-  GstCaps      *caps;
-
-  /* transports we stream to */
-  guint         n_active;
-  GList        *transports;
+  GstRTSPStreamPrivate *priv;
 };
 
 struct _GstRTSPStreamClass {
@@ -128,9 +63,10 @@ GType             gst_rtsp_stream_get_type         (void);
 
 GstRTSPStream *   gst_rtsp_stream_new              (guint idx, GstElement *payloader,
                                                     GstPad *srcpad);
+guint             gst_rtsp_stream_get_index        (GstRTSPStream *stream);
 
-void              gst_rtsp_stream_set_mtu          (GstRTSPStream * stream, guint mtu);
-guint             gst_rtsp_stream_get_mtu          (GstRTSPStream * stream);
+void              gst_rtsp_stream_set_mtu          (GstRTSPStream *stream, guint mtu);
+guint             gst_rtsp_stream_get_mtu          (GstRTSPStream *stream);
 
 void              gst_rtsp_stream_set_address_pool (GstRTSPStream *stream, GstRTSPAddressPool *pool);
 GstRTSPAddressPool *
@@ -138,14 +74,20 @@ GstRTSPAddressPool *
 
 GstRTSPAddress *  gst_rtsp_stream_get_address      (GstRTSPStream *stream);
 
-gboolean          gst_rtsp_stream_join_bin         (GstRTSPStream * stream,
+gboolean          gst_rtsp_stream_join_bin         (GstRTSPStream *stream,
                                                     GstBin *bin, GstElement *rtpbin,
                                                     GstState state);
-gboolean          gst_rtsp_stream_leave_bin        (GstRTSPStream * stream,
+gboolean          gst_rtsp_stream_leave_bin        (GstRTSPStream *stream,
                                                     GstBin *bin, GstElement *rtpbin);
 
-gboolean          gst_rtsp_stream_get_rtpinfo      (GstRTSPStream * stream,
-                                                    guint *rtptime, guint * seq);
+void              gst_rtsp_stream_get_server_port  (GstRTSPStream *stream,
+                                                    GstRTSPRange *server_port);
+void              gst_rtsp_stream_get_ssrc         (GstRTSPStream *stream,
+                                                    guint *ssrc);
+
+gboolean          gst_rtsp_stream_get_rtpinfo      (GstRTSPStream *stream,
+                                                    guint *rtptime, guint *seq);
+GstCaps *         gst_rtsp_stream_get_caps         (GstRTSPStream *stream);
 
 GstFlowReturn     gst_rtsp_stream_recv_rtp         (GstRTSPStream *stream,
                                                     GstBuffer *buffer);
index f7bff01..c1115de 100644 (file)
@@ -93,7 +93,7 @@ GST_START_TEST (test_media)
 {
   GstRTSPMedia *media;
 
-  media = gst_rtsp_media_new ();
+  media = gst_rtsp_media_new (NULL);
   fail_unless (GST_IS_RTSP_MEDIA (media));
   g_object_unref (media);
 }