media: disconnect from signal handlers in unprepare()
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-session-media.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #include <string.h>
20
21 #include "rtsp-session.h"
22
23 #define GST_RTSP_SESSION_MEDIA_GET_PRIVATE(obj)  \
24     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION_MEDIA, GstRTSPSessionMediaPrivate))
25
26 struct _GstRTSPSessionMediaPrivate
27 {
28   GMutex lock;
29   GstRTSPUrl *url;              /* unmutable */
30   GstRTSPMedia *media;          /* unmutable */
31   GstRTSPState state;           /* protected by lock */
32   guint counter;                /* protected by lock */
33
34   GPtrArray *transports;        /* protected by lock */
35 };
36
37 enum
38 {
39   PROP_0,
40   PROP_LAST
41 };
42
43 GST_DEBUG_CATEGORY_STATIC (rtsp_session_media_debug);
44 #define GST_CAT_DEFAULT rtsp_session_media_debug
45
46 static void gst_rtsp_session_media_finalize (GObject * obj);
47
48 G_DEFINE_TYPE (GstRTSPSessionMedia, gst_rtsp_session_media, G_TYPE_OBJECT);
49
50 static void
51 gst_rtsp_session_media_class_init (GstRTSPSessionMediaClass * klass)
52 {
53   GObjectClass *gobject_class;
54
55   g_type_class_add_private (klass, sizeof (GstRTSPSessionMediaPrivate));
56
57   gobject_class = G_OBJECT_CLASS (klass);
58
59   gobject_class->finalize = gst_rtsp_session_media_finalize;
60
61   GST_DEBUG_CATEGORY_INIT (rtsp_session_media_debug, "rtspsessionmedia", 0,
62       "GstRTSPSessionMedia");
63 }
64
65 static void
66 gst_rtsp_session_media_init (GstRTSPSessionMedia * media)
67 {
68   GstRTSPSessionMediaPrivate *priv = GST_RTSP_SESSION_MEDIA_GET_PRIVATE (media);
69
70   media->priv = priv;
71
72   g_mutex_init (&priv->lock);
73   priv->state = GST_RTSP_STATE_INIT;
74 }
75
76 static void
77 gst_rtsp_session_media_finalize (GObject * obj)
78 {
79   GstRTSPSessionMedia *media;
80   GstRTSPSessionMediaPrivate *priv;
81
82   media = GST_RTSP_SESSION_MEDIA (obj);
83   priv = media->priv;
84
85   GST_INFO ("free session media %p", media);
86
87   gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
88
89   g_ptr_array_unref (priv->transports);
90
91   gst_rtsp_url_free (priv->url);
92   g_object_unref (priv->media);
93   g_mutex_clear (&priv->lock);
94
95   G_OBJECT_CLASS (gst_rtsp_session_media_parent_class)->finalize (obj);
96 }
97
98 static void
99 free_session_media (gpointer data)
100 {
101   if (data)
102     g_object_unref (data);
103 }
104
105 /**
106  * gst_rtsp_session_media_new:
107  * @url: the #GstRTSPUrl
108  * @media: the #GstRTSPMedia
109  *
110  * Create a new #GstRTPSessionMedia that manages the streams
111  * in @media for @url. @media should be prepared.
112  *
113  * Ownership is taken of @media.
114  *
115  * Returns: a new #GstRTSPSessionMedia.
116  */
117 GstRTSPSessionMedia *
118 gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media)
119 {
120   GstRTSPSessionMediaPrivate *priv;
121   GstRTSPSessionMedia *result;
122   guint n_streams;
123
124   g_return_val_if_fail (url != NULL, NULL);
125   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
126   g_return_val_if_fail (gst_rtsp_media_get_status (media) ==
127       GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
128
129   result = g_object_new (GST_TYPE_RTSP_SESSION_MEDIA, NULL);
130   priv = result->priv;
131
132   priv->url = gst_rtsp_url_copy ((GstRTSPUrl *) url);
133   priv->media = media;
134
135   /* prealloc the streams now, filled with NULL */
136   n_streams = gst_rtsp_media_n_streams (media);
137   priv->transports = g_ptr_array_new_full (n_streams, free_session_media);
138   g_ptr_array_set_size (priv->transports, n_streams);
139
140   return result;
141 }
142
143 /**
144  * gst_rtsp_session_media_matches_url:
145  * @media: a #GstRTSPSessionMedia
146  * @url: a #GstRTSPUrl
147  *
148  * Check if the url of @media matches @url.
149  *
150  * Returns: %TRUE when @url matches the url of @media.
151  */
152 gboolean
153 gst_rtsp_session_media_matches_url (GstRTSPSessionMedia * media,
154     const GstRTSPUrl * url)
155 {
156   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
157   g_return_val_if_fail (url != NULL, FALSE);
158
159   return g_str_equal (media->priv->url->abspath, url->abspath);
160 }
161
162 /**
163  * gst_rtsp_session_media_get_media:
164  * @media: a #GstRTSPSessionMedia
165  *
166  * Get the #GstRTSPMedia that was used when constructing @media
167  *
168  * Returns: (transfer none): the #GstRTSPMedia of @media. Remains valid as long
169  *         as @media is valid.
170  */
171 GstRTSPMedia *
172 gst_rtsp_session_media_get_media (GstRTSPSessionMedia * media)
173 {
174   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
175
176   return media->priv->media;
177 }
178
179 /**
180  * gst_rtsp_session_media_get_base_time:
181  * @media: a #GstRTSPSessionMedia
182  *
183  * Get the base_time of the #GstRTSPMedia in @media
184  *
185  * Returns: the base_time of the media.
186  */
187 GstClockTime
188 gst_rtsp_session_media_get_base_time (GstRTSPSessionMedia * media)
189 {
190   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), GST_CLOCK_TIME_NONE);
191
192   return gst_rtsp_media_get_base_time (media->priv->media);
193 }
194
195 /**
196  * gst_rtsp_session_media_set_transport:
197  * @media: a #GstRTSPSessionMedia
198  * @stream: a #GstRTSPStream
199  * @tr: a #GstRTSPTransport
200  *
201  * Configure the transport for @stream to @tr in @media.
202  *
203  * Returns: (transfer none): the new or updated #GstRTSPStreamTransport for @stream.
204  */
205 GstRTSPStreamTransport *
206 gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
207     GstRTSPStream * stream, GstRTSPTransport * tr)
208 {
209   GstRTSPSessionMediaPrivate *priv;
210   GstRTSPStreamTransport *result;
211   guint idx;
212
213   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
214   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
215   g_return_val_if_fail (tr != NULL, NULL);
216   priv = media->priv;
217   idx = gst_rtsp_stream_get_index (stream);
218   g_return_val_if_fail (idx < priv->transports->len, NULL);
219
220   g_mutex_lock (&priv->lock);
221   result = g_ptr_array_index (priv->transports, idx);
222   if (result == NULL) {
223     result = gst_rtsp_stream_transport_new (stream, tr);
224     g_ptr_array_index (priv->transports, idx) = result;
225     g_mutex_unlock (&priv->lock);
226   } else {
227     gst_rtsp_stream_transport_set_transport (result, tr);
228     g_mutex_unlock (&priv->lock);
229   }
230
231   return result;
232 }
233
234 /**
235  * gst_rtsp_session_media_get_transport:
236  * @media: a #GstRTSPSessionMedia
237  * @idx: the stream index
238  *
239  * Get a previously created #GstRTSPStreamTransport for the stream at @idx.
240  *
241  * Returns: (transfer none): a #GstRTSPStreamTransport that is valid until the
242  * session of @media is unreffed.
243  */
244 GstRTSPStreamTransport *
245 gst_rtsp_session_media_get_transport (GstRTSPSessionMedia * media, guint idx)
246 {
247   GstRTSPSessionMediaPrivate *priv;
248   GstRTSPStreamTransport *result;
249
250   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
251   priv = media->priv;
252   g_return_val_if_fail (idx < priv->transports->len, NULL);
253
254   g_mutex_lock (&priv->lock);
255   result = g_ptr_array_index (priv->transports, idx);
256   g_mutex_unlock (&priv->lock);
257
258   return result;
259 }
260
261 /**
262  * gst_rtsp_session_media_alloc_channels:
263  * @media: a #GstRTSPSessionMedia
264  * @range: a #GstRTSPRange
265  *
266  * Fill @range with the next available min and max channels for
267  * interleaved transport.
268  *
269  * Returns: %TRUE on success.
270  */
271 gboolean
272 gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia * media,
273     GstRTSPRange * range)
274 {
275   GstRTSPSessionMediaPrivate *priv;
276
277   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
278
279   priv = media->priv;
280
281   g_mutex_lock (&priv->lock);
282   range->min = priv->counter++;
283   range->max = priv->counter++;
284   g_mutex_unlock (&priv->lock);
285
286   return TRUE;
287 }
288
289 /**
290  * gst_rtsp_session_media_set_state:
291  * @media: a #GstRTSPSessionMedia
292  * @state: the new state
293  *
294  * Tell the media object @media to change to @state.
295  *
296  * Returns: %TRUE on success.
297  */
298 gboolean
299 gst_rtsp_session_media_set_state (GstRTSPSessionMedia * media, GstState state)
300 {
301   GstRTSPSessionMediaPrivate *priv;
302   gboolean ret;
303
304   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
305
306   priv = media->priv;
307
308   g_mutex_lock (&priv->lock);
309   ret = gst_rtsp_media_set_state (priv->media, state, priv->transports);
310   g_mutex_unlock (&priv->lock);
311
312   return ret;
313 }
314
315 /**
316  * gst_rtsp_session_media_set_rtsp_state:
317  * @media: a #GstRTSPSessionMedia
318  * @state: a #GstRTSPState
319  *
320  * Set the RTSP state of @media to @state.
321  */
322 void
323 gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia * media,
324     GstRTSPState state)
325 {
326   GstRTSPSessionMediaPrivate *priv;
327
328   g_return_if_fail (GST_IS_RTSP_SESSION_MEDIA (media));
329
330   priv = media->priv;
331
332   g_mutex_lock (&priv->lock);
333   priv->state = state;
334   g_mutex_unlock (&priv->lock);
335 }
336
337 /**
338  * gst_rtsp_session_media_set_rtsp_state:
339  * @media: a #GstRTSPSessionMedia
340  *
341  * Get the current RTSP state of @media.
342  *
343  * Returns: the current RTSP state of @media.
344  */
345 GstRTSPState
346 gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia * media)
347 {
348   GstRTSPSessionMediaPrivate *priv;
349   GstRTSPState ret;
350
351   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media),
352       GST_RTSP_STATE_INVALID);
353
354   priv = media->priv;
355
356   g_mutex_lock (&priv->lock);
357   ret = priv->state;
358   g_mutex_unlock (&priv->lock);
359
360   return ret;
361 }