docs: update docs
[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   gchar *path;                  /* unmutable */
30   gint path_len;                /* unmutable */
31   GstRTSPMedia *media;          /* unmutable */
32   GstRTSPState state;           /* protected by lock */
33   guint counter;                /* protected by lock */
34
35   GPtrArray *transports;        /* protected by lock */
36 };
37
38 enum
39 {
40   PROP_0,
41   PROP_LAST
42 };
43
44 GST_DEBUG_CATEGORY_STATIC (rtsp_session_media_debug);
45 #define GST_CAT_DEFAULT rtsp_session_media_debug
46
47 static void gst_rtsp_session_media_finalize (GObject * obj);
48
49 G_DEFINE_TYPE (GstRTSPSessionMedia, gst_rtsp_session_media, G_TYPE_OBJECT);
50
51 static void
52 gst_rtsp_session_media_class_init (GstRTSPSessionMediaClass * klass)
53 {
54   GObjectClass *gobject_class;
55
56   g_type_class_add_private (klass, sizeof (GstRTSPSessionMediaPrivate));
57
58   gobject_class = G_OBJECT_CLASS (klass);
59
60   gobject_class->finalize = gst_rtsp_session_media_finalize;
61
62   GST_DEBUG_CATEGORY_INIT (rtsp_session_media_debug, "rtspsessionmedia", 0,
63       "GstRTSPSessionMedia");
64 }
65
66 static void
67 gst_rtsp_session_media_init (GstRTSPSessionMedia * media)
68 {
69   GstRTSPSessionMediaPrivate *priv = GST_RTSP_SESSION_MEDIA_GET_PRIVATE (media);
70
71   media->priv = priv;
72
73   g_mutex_init (&priv->lock);
74   priv->state = GST_RTSP_STATE_INIT;
75 }
76
77 static void
78 gst_rtsp_session_media_finalize (GObject * obj)
79 {
80   GstRTSPSessionMedia *media;
81   GstRTSPSessionMediaPrivate *priv;
82
83   media = GST_RTSP_SESSION_MEDIA (obj);
84   priv = media->priv;
85
86   GST_INFO ("free session media %p", media);
87
88   gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
89
90   g_ptr_array_unref (priv->transports);
91
92   g_free (priv->path);
93   g_object_unref (priv->media);
94   g_mutex_clear (&priv->lock);
95
96   G_OBJECT_CLASS (gst_rtsp_session_media_parent_class)->finalize (obj);
97 }
98
99 static void
100 free_session_media (gpointer data)
101 {
102   if (data)
103     g_object_unref (data);
104 }
105
106 /**
107  * gst_rtsp_session_media_new:
108  * @path: the path
109  * @media: the #GstRTSPMedia
110  *
111  * Create a new #GstRTPSessionMedia that manages the streams
112  * in @media for @path. @media should be prepared.
113  *
114  * Ownership is taken of @media.
115  *
116  * Returns: a new #GstRTSPSessionMedia.
117  */
118 GstRTSPSessionMedia *
119 gst_rtsp_session_media_new (const gchar * path, GstRTSPMedia * media)
120 {
121   GstRTSPSessionMediaPrivate *priv;
122   GstRTSPSessionMedia *result;
123   guint n_streams;
124
125   g_return_val_if_fail (path != NULL, NULL);
126   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
127   g_return_val_if_fail (gst_rtsp_media_get_status (media) ==
128       GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
129
130   result = g_object_new (GST_TYPE_RTSP_SESSION_MEDIA, NULL);
131   priv = result->priv;
132
133   priv->path = g_strdup (path);
134   priv->path_len = strlen (path);
135   priv->media = media;
136
137   /* prealloc the streams now, filled with NULL */
138   n_streams = gst_rtsp_media_n_streams (media);
139   priv->transports = g_ptr_array_new_full (n_streams, free_session_media);
140   g_ptr_array_set_size (priv->transports, n_streams);
141
142   return result;
143 }
144
145 /**
146  * gst_rtsp_session_media_matches:
147  * @media: a #GstRTSPSessionMedia
148  * @path: a path
149  * @matched: the amount of matched characters of @path
150  *
151  * Check if the path of @media matches @path. It @path matches, the amount of
152  * matched characters is returned in @matched.
153  *
154  * Returns: %TRUE when @path matches the path of @media.
155  */
156 gboolean
157 gst_rtsp_session_media_matches (GstRTSPSessionMedia * media,
158     const gchar * path, gint * matched)
159 {
160   GstRTSPSessionMediaPrivate *priv;
161   gint len;
162
163   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
164   g_return_val_if_fail (path != NULL, FALSE);
165   g_return_val_if_fail (matched != NULL, FALSE);
166
167   priv = media->priv;
168   len = strlen (path);
169
170   /* path needs to be smaller than the media path */
171   if (len < priv->path_len)
172     return FALSE;
173
174   /* if media path is larger, it there should be a / following the path */
175   if (len > priv->path_len && path[priv->path_len] != '/')
176     return FALSE;
177
178   *matched = priv->path_len;
179
180   return strncmp (path, priv->path, priv->path_len) == 0;
181 }
182
183 /**
184  * gst_rtsp_session_media_get_media:
185  * @media: a #GstRTSPSessionMedia
186  *
187  * Get the #GstRTSPMedia that was used when constructing @media
188  *
189  * Returns: (transfer none): the #GstRTSPMedia of @media. Remains valid as long
190  *         as @media is valid.
191  */
192 GstRTSPMedia *
193 gst_rtsp_session_media_get_media (GstRTSPSessionMedia * media)
194 {
195   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
196
197   return media->priv->media;
198 }
199
200 /**
201  * gst_rtsp_session_media_get_base_time:
202  * @media: a #GstRTSPSessionMedia
203  *
204  * Get the base_time of the #GstRTSPMedia in @media
205  *
206  * Returns: the base_time of the media.
207  */
208 GstClockTime
209 gst_rtsp_session_media_get_base_time (GstRTSPSessionMedia * media)
210 {
211   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), GST_CLOCK_TIME_NONE);
212
213   return gst_rtsp_media_get_base_time (media->priv->media);
214 }
215
216 /**
217  * gst_rtsp_session_media_set_transport:
218  * @media: a #GstRTSPSessionMedia
219  * @stream: a #GstRTSPStream
220  * @tr: a #GstRTSPTransport
221  *
222  * Configure the transport for @stream to @tr in @media.
223  *
224  * Returns: (transfer none): the new or updated #GstRTSPStreamTransport for @stream.
225  */
226 GstRTSPStreamTransport *
227 gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
228     GstRTSPStream * stream, GstRTSPTransport * tr)
229 {
230   GstRTSPSessionMediaPrivate *priv;
231   GstRTSPStreamTransport *result;
232   guint idx;
233
234   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
235   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
236   g_return_val_if_fail (tr != NULL, NULL);
237   priv = media->priv;
238   idx = gst_rtsp_stream_get_index (stream);
239   g_return_val_if_fail (idx < priv->transports->len, NULL);
240
241   g_mutex_lock (&priv->lock);
242   result = g_ptr_array_index (priv->transports, idx);
243   if (result == NULL) {
244     result = gst_rtsp_stream_transport_new (stream, tr);
245     g_ptr_array_index (priv->transports, idx) = result;
246     g_mutex_unlock (&priv->lock);
247   } else {
248     gst_rtsp_stream_transport_set_transport (result, tr);
249     g_mutex_unlock (&priv->lock);
250   }
251
252   return result;
253 }
254
255 /**
256  * gst_rtsp_session_media_get_transport:
257  * @media: a #GstRTSPSessionMedia
258  * @idx: the stream index
259  *
260  * Get a previously created #GstRTSPStreamTransport for the stream at @idx.
261  *
262  * Returns: (transfer none): a #GstRTSPStreamTransport that is valid until the
263  * session of @media is unreffed.
264  */
265 GstRTSPStreamTransport *
266 gst_rtsp_session_media_get_transport (GstRTSPSessionMedia * media, guint idx)
267 {
268   GstRTSPSessionMediaPrivate *priv;
269   GstRTSPStreamTransport *result;
270
271   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
272   priv = media->priv;
273   g_return_val_if_fail (idx < priv->transports->len, NULL);
274
275   g_mutex_lock (&priv->lock);
276   result = g_ptr_array_index (priv->transports, idx);
277   g_mutex_unlock (&priv->lock);
278
279   return result;
280 }
281
282 /**
283  * gst_rtsp_session_media_alloc_channels:
284  * @media: a #GstRTSPSessionMedia
285  * @range: a #GstRTSPRange
286  *
287  * Fill @range with the next available min and max channels for
288  * interleaved transport.
289  *
290  * Returns: %TRUE on success.
291  */
292 gboolean
293 gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia * media,
294     GstRTSPRange * range)
295 {
296   GstRTSPSessionMediaPrivate *priv;
297
298   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
299
300   priv = media->priv;
301
302   g_mutex_lock (&priv->lock);
303   range->min = priv->counter++;
304   range->max = priv->counter++;
305   g_mutex_unlock (&priv->lock);
306
307   return TRUE;
308 }
309
310 /**
311  * gst_rtsp_session_media_set_state:
312  * @media: a #GstRTSPSessionMedia
313  * @state: the new state
314  *
315  * Tell the media object @media to change to @state.
316  *
317  * Returns: %TRUE on success.
318  */
319 gboolean
320 gst_rtsp_session_media_set_state (GstRTSPSessionMedia * media, GstState state)
321 {
322   GstRTSPSessionMediaPrivate *priv;
323   gboolean ret;
324
325   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
326
327   priv = media->priv;
328
329   g_mutex_lock (&priv->lock);
330   ret = gst_rtsp_media_set_state (priv->media, state, priv->transports);
331   g_mutex_unlock (&priv->lock);
332
333   return ret;
334 }
335
336 /**
337  * gst_rtsp_session_media_set_rtsp_state:
338  * @media: a #GstRTSPSessionMedia
339  * @state: a #GstRTSPState
340  *
341  * Set the RTSP state of @media to @state.
342  */
343 void
344 gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia * media,
345     GstRTSPState state)
346 {
347   GstRTSPSessionMediaPrivate *priv;
348
349   g_return_if_fail (GST_IS_RTSP_SESSION_MEDIA (media));
350
351   priv = media->priv;
352
353   g_mutex_lock (&priv->lock);
354   priv->state = state;
355   g_mutex_unlock (&priv->lock);
356 }
357
358 /**
359  * gst_rtsp_session_media_get_rtsp_state:
360  * @media: a #GstRTSPSessionMedia
361  *
362  * Get the current RTSP state of @media.
363  *
364  * Returns: the current RTSP state of @media.
365  */
366 GstRTSPState
367 gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia * media)
368 {
369   GstRTSPSessionMediaPrivate *priv;
370   GstRTSPState ret;
371
372   g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media),
373       GST_RTSP_STATE_INVALID);
374
375   priv = media->priv;
376
377   g_mutex_lock (&priv->lock);
378   ret = priv->state;
379   g_mutex_unlock (&priv->lock);
380
381   return ret;
382 }