faacc4a6538d9e2e3a9e6a06e919867c19924a4b
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-stream-transport.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 /**
20  * SECTION:rtsp-stream-transport
21  * @short_description: A media stream transport configuration
22  * @see_also: #GstRTSPStream, #GstRTSPSessionMedia
23  *
24  * The #GstRTSPStreamTransport configures the transport used by a
25  * #GstRTSPStream. It is usually manages by a #GstRTSPSessionMedia object.
26  *
27  * With gst_rtsp_stream_transport_set_callbacks(), callbacks can be configured
28  * to handle the RTP and RTCP packets from the stream, for example when they
29  * need to be sent over TCP.
30  *
31  * With  gst_rtsp_stream_transport_set_active() the transports are added and
32  * removed from the stream.
33  *
34  * A #GstRTSPStream will call gst_rtsp_stream_transport_keep_alive() when RTCP
35  * is received from the client. It will also call
36  * gst_rtsp_stream_transport_set_timed_out() when a receiver has timed out.
37  *
38  * Last reviewed on 2013-07-16 (1.0.0)
39  */
40
41 #include <string.h>
42 #include <stdlib.h>
43
44 #include "rtsp-stream-transport.h"
45
46 #define GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE(obj)  \
47        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM_TRANSPORT, GstRTSPStreamTransportPrivate))
48
49 struct _GstRTSPStreamTransportPrivate
50 {
51   GstRTSPStream *stream;
52
53   GstRTSPSendFunc send_rtp;
54   GstRTSPSendFunc send_rtcp;
55   gpointer user_data;
56   GDestroyNotify notify;
57
58   GstRTSPKeepAliveFunc keep_alive;
59   gpointer ka_user_data;
60   GDestroyNotify ka_notify;
61   gboolean active;
62   gboolean timed_out;
63
64   GstRTSPTransport *transport;
65   GstRTSPUrl *url;
66
67   GObject *rtpsource;
68 };
69
70 enum
71 {
72   PROP_0,
73   PROP_LAST
74 };
75
76 GST_DEBUG_CATEGORY_STATIC (rtsp_stream_transport_debug);
77 #define GST_CAT_DEFAULT rtsp_stream_transport_debug
78
79 static void gst_rtsp_stream_transport_finalize (GObject * obj);
80
81 G_DEFINE_TYPE (GstRTSPStreamTransport, gst_rtsp_stream_transport,
82     G_TYPE_OBJECT);
83
84 static void
85 gst_rtsp_stream_transport_class_init (GstRTSPStreamTransportClass * klass)
86 {
87   GObjectClass *gobject_class;
88
89   g_type_class_add_private (klass, sizeof (GstRTSPStreamTransportPrivate));
90
91   gobject_class = G_OBJECT_CLASS (klass);
92
93   gobject_class->finalize = gst_rtsp_stream_transport_finalize;
94
95   GST_DEBUG_CATEGORY_INIT (rtsp_stream_transport_debug, "rtspmediatransport",
96       0, "GstRTSPStreamTransport");
97 }
98
99 static void
100 gst_rtsp_stream_transport_init (GstRTSPStreamTransport * trans)
101 {
102   GstRTSPStreamTransportPrivate *priv =
103       GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE (trans);
104
105   trans->priv = priv;
106 }
107
108 static void
109 gst_rtsp_stream_transport_finalize (GObject * obj)
110 {
111   GstRTSPStreamTransportPrivate *priv;
112   GstRTSPStreamTransport *trans;
113
114   trans = GST_RTSP_STREAM_TRANSPORT (obj);
115   priv = trans->priv;
116
117   /* remove callbacks now */
118   gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
119   gst_rtsp_stream_transport_set_keepalive (trans, NULL, NULL, NULL);
120
121   if (priv->transport)
122     gst_rtsp_transport_free (priv->transport);
123
124   if (priv->url)
125     gst_rtsp_url_free (priv->url);
126
127   G_OBJECT_CLASS (gst_rtsp_stream_transport_parent_class)->finalize (obj);
128 }
129
130 /**
131  * gst_rtsp_stream_transport_new:
132  * @stream: a #GstRTSPStream
133  * @tr: (transfer full): a GstRTSPTransport
134  *
135  * Create a new #GstRTSPStreamTransport that can be used to manage
136  * @stream with transport @tr.
137  *
138  * Returns: a new #GstRTSPStreamTransport
139  */
140 GstRTSPStreamTransport *
141 gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
142 {
143   GstRTSPStreamTransportPrivate *priv;
144   GstRTSPStreamTransport *trans;
145
146   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
147   g_return_val_if_fail (tr != NULL, NULL);
148
149   trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL);
150   priv = trans->priv;
151   priv->stream = stream;
152   priv->transport = tr;
153
154   return trans;
155 }
156
157 /**
158  * gst_rtsp_stream_transport_get_stream:
159  * @trans: a #GstRTSPStreamTransport
160  *
161  * Get the #GstRTSPStream used when constructing @trans.
162  *
163  * Returns: (transfer none): the stream used when constructing @trans.
164  */
165 GstRTSPStream *
166 gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport * trans)
167 {
168   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
169
170   return trans->priv->stream;
171 }
172
173 /**
174  * gst_rtsp_stream_transport_set_callbacks:
175  * @trans: a #GstRTSPStreamTransport
176  * @send_rtp: (scope notified): a callback called when RTP should be sent
177  * @send_rtcp: (scope notified): a callback called when RTCP should be sent
178  * @user_data: user data passed to callbacks
179  * @notify: called with the user_data when no longer needed.
180  *
181  * Install callbacks that will be called when data for a stream should be sent
182  * to a client. This is usually used when sending RTP/RTCP over TCP.
183  */
184 void
185 gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport * trans,
186     GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp,
187     gpointer user_data, GDestroyNotify notify)
188 {
189   GstRTSPStreamTransportPrivate *priv;
190
191   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
192
193   priv = trans->priv;
194
195   priv->send_rtp = send_rtp;
196   priv->send_rtcp = send_rtcp;
197   if (priv->notify)
198     priv->notify (priv->user_data);
199   priv->user_data = user_data;
200   priv->notify = notify;
201 }
202
203 /**
204  * gst_rtsp_stream_transport_set_keepalive:
205  * @trans: a #GstRTSPStreamTransport
206  * @keep_alive: a callback called when the receiver is active
207  * @user_data: user data passed to callback
208  * @notify: called with the user_data when no longer needed.
209  *
210  * Install callbacks that will be called when RTCP packets are received from the
211  * receiver of @trans.
212  */
213 void
214 gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport * trans,
215     GstRTSPKeepAliveFunc keep_alive, gpointer user_data, GDestroyNotify notify)
216 {
217   GstRTSPStreamTransportPrivate *priv;
218
219   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
220
221   priv = trans->priv;
222
223   priv->keep_alive = keep_alive;
224   if (priv->ka_notify)
225     priv->ka_notify (priv->ka_user_data);
226   priv->ka_user_data = user_data;
227   priv->ka_notify = notify;
228 }
229
230
231 /**
232  * gst_rtsp_stream_transport_set_transport:
233  * @trans: a #GstRTSPStreamTransport
234  * @tr: (transfer full): a client #GstRTSPTransport
235  *
236  * Set @tr as the client transport. This function takes ownership of the
237  * passed @tr.
238  */
239 void
240 gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
241     GstRTSPTransport * tr)
242 {
243   GstRTSPStreamTransportPrivate *priv;
244
245   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
246   g_return_if_fail (tr != NULL);
247
248   priv = trans->priv;
249
250   /* keep track of the transports in the stream. */
251   if (priv->transport)
252     gst_rtsp_transport_free (priv->transport);
253   priv->transport = tr;
254 }
255
256 /**
257  * gst_rtsp_stream_transport_get_transport:
258  * @trans: a #GstRTSPStreamTransport
259  *
260  * Get the transport configured in @trans.
261  *
262  * Returns: (transfer none): the transport configured in @trans. It remains
263  *     valid for as long as @trans is valid.
264  */
265 const GstRTSPTransport *
266 gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans)
267 {
268   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
269
270   return trans->priv->transport;
271 }
272
273 /**
274  * gst_rtsp_stream_transport_set_url:
275  * @trans: a #GstRTSPStreamTransport
276  * @url: (transfer none): a client #GstRTSPUrl
277  *
278  * Set @url as the client url.
279  */
280 void
281 gst_rtsp_stream_transport_set_url (GstRTSPStreamTransport * trans,
282     const GstRTSPUrl * url)
283 {
284   GstRTSPStreamTransportPrivate *priv;
285
286   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
287
288   priv = trans->priv;
289
290   /* keep track of the transports in the stream. */
291   if (priv->url)
292     gst_rtsp_url_free (priv->url);
293   priv->url = (url ? gst_rtsp_url_copy (url) : NULL);
294 }
295
296 /**
297  * gst_rtsp_stream_transport_get_url:
298  * @trans: a #GstRTSPStreamTransport
299  *
300  * Get the url configured in @trans.
301  *
302  * Returns: (transfer none): the url configured in @trans. It remains
303  *     valid for as long as @trans is valid.
304  */
305 const GstRTSPUrl *
306 gst_rtsp_stream_transport_get_url (GstRTSPStreamTransport * trans)
307 {
308   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
309
310   return trans->priv->url;
311 }
312
313  /**
314  * gst_rtsp_stream_transport_get_rtpinfo:
315  * @trans: a #GstRTSPStreamTransport
316  *
317  * Get the RTPInfo string for @trans.
318  *
319  * Returns: the RTPInfo string for @trans. g_free() after
320  * usage.
321  */
322 gchar *
323 gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport * trans)
324 {
325   GstRTSPStreamTransportPrivate *priv;
326   gchar *url_str;
327   GString *rtpinfo;
328   guint rtptime, seq;
329
330   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
331
332   priv = trans->priv;
333
334   if (!gst_rtsp_stream_get_rtpinfo (priv->stream, &rtptime, &seq, NULL))
335     return NULL;
336
337   rtpinfo = g_string_new ("");
338
339   url_str = gst_rtsp_url_get_request_uri (trans->priv->url);
340   g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u",
341       url_str, seq, rtptime);
342   g_free (url_str);
343
344   return g_string_free (rtpinfo, FALSE);
345 }
346
347 /**
348  * gst_rtsp_stream_transport_set_active:
349  * @trans: a #GstRTSPStreamTransport
350  * @active: new state of @trans
351  *
352  * Activate or deactivate datatransfer configured in @trans.
353  *
354  * Returns: %TRUE when the state was changed.
355  */
356 gboolean
357 gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans,
358     gboolean active)
359 {
360   GstRTSPStreamTransportPrivate *priv;
361   gboolean res;
362
363   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
364
365   priv = trans->priv;
366
367   if (priv->active == active)
368     return FALSE;
369
370   if (active)
371     res = gst_rtsp_stream_add_transport (priv->stream, trans);
372   else
373     res = gst_rtsp_stream_remove_transport (priv->stream, trans);
374
375   if (res)
376     priv->active = active;
377
378   return res;
379 }
380
381 /**
382  * gst_rtsp_stream_transport_set_timed_out:
383  * @trans: a #GstRTSPStreamTransport
384  * @timedout: timed out value
385  *
386  * Set the timed out state of @trans to @timedout
387  */
388 void
389 gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans,
390     gboolean timedout)
391 {
392   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
393
394   trans->priv->timed_out = timedout;
395 }
396
397 /**
398  * gst_rtsp_stream_transport_is_timed_out:
399  * @trans: a #GstRTSPStreamTransport
400  *
401  * Check if @trans is timed out.
402  *
403  * Returns: %TRUE if @trans timed out.
404  */
405 gboolean
406 gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
407 {
408   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
409
410   return trans->priv->timed_out;
411 }
412
413 /**
414  * gst_rtsp_stream_transport_send_rtp:
415  * @trans: a #GstRTSPStreamTransport
416  * @buffer: a #GstBuffer
417  *
418  * Send @buffer to the installed RTP callback for @trans.
419  *
420  * Returns: %TRUE on success
421  */
422 gboolean
423 gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
424     GstBuffer * buffer)
425 {
426   GstRTSPStreamTransportPrivate *priv;
427   gboolean res = FALSE;
428
429   priv = trans->priv;
430
431   if (priv->send_rtp)
432     res =
433         priv->send_rtp (buffer, priv->transport->interleaved.min,
434         priv->user_data);
435
436   return res;
437 }
438
439 /**
440  * gst_rtsp_stream_transport_send_rtcp:
441  * @trans: a #GstRTSPStreamTransport
442  * @buffer: a #GstBuffer
443  *
444  * Send @buffer to the installed RTCP callback for @trans.
445  *
446  * Returns: %TRUE on success
447  */
448 gboolean
449 gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
450     GstBuffer * buffer)
451 {
452   GstRTSPStreamTransportPrivate *priv;
453   gboolean res = FALSE;
454
455   priv = trans->priv;
456
457   if (priv->send_rtcp)
458     res =
459         priv->send_rtcp (buffer, priv->transport->interleaved.max,
460         priv->user_data);
461
462   return res;
463 }
464
465 /**
466  * gst_rtsp_stream_transport_keep_alive:
467  * @trans: a #GstRTSPStreamTransport
468  *
469  * Signal the installed keep_alive callback for @trans.
470  */
471 void
472 gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
473 {
474   GstRTSPStreamTransportPrivate *priv;
475
476   priv = trans->priv;
477
478   if (priv->keep_alive)
479     priv->keep_alive (priv->ka_user_data);
480 }