Initial release including wifi display based on gst-rtsp-server-1.4.1
[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: (transfer full): 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: (closure): user data passed to callbacks
179  * @notify: (allow-none): 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: (scope notified): a callback called when the receiver is active
207  * @user_data: (closure): user data passed to callback
208  * @notify: (allow-none): 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  * @start_time: a star time
317  *
318  * Get the RTP-Info string for @trans and @start_time.
319  *
320  * Returns: (transfer full) (nullable): the RTPInfo string for @trans
321  * and @start_time or %NULL when the RTP-Info could not be
322  * determined. g_free() after usage.
323  */
324 gchar *
325 gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport * trans,
326     GstClockTime start_time)
327 {
328   GstRTSPStreamTransportPrivate *priv;
329   gchar *url_str;
330   GString *rtpinfo;
331   guint rtptime, seq, clock_rate;
332   GstClockTime running_time = GST_CLOCK_TIME_NONE;
333
334   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
335
336   priv = trans->priv;
337
338   if (!gst_rtsp_stream_get_rtpinfo (priv->stream, &rtptime, &seq, &clock_rate,
339           &running_time))
340     return NULL;
341
342   GST_DEBUG ("RTP time %u, seq %u, rate %u, running-time %" GST_TIME_FORMAT,
343       rtptime, seq, clock_rate, GST_TIME_ARGS (running_time));
344
345   if (GST_CLOCK_TIME_IS_VALID (running_time)
346       && GST_CLOCK_TIME_IS_VALID (start_time)) {
347     if (running_time > start_time) {
348       rtptime -=
349           gst_util_uint64_scale_int (running_time - start_time, clock_rate,
350           GST_SECOND);
351     } else {
352       rtptime +=
353           gst_util_uint64_scale_int (start_time - running_time, clock_rate,
354           GST_SECOND);
355     }
356   }
357   GST_DEBUG ("RTP time %u, for start-time %" GST_TIME_FORMAT,
358       rtptime, GST_TIME_ARGS (start_time));
359
360   rtpinfo = g_string_new ("");
361
362   url_str = gst_rtsp_url_get_request_uri (trans->priv->url);
363   g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u",
364       url_str, seq, rtptime);
365   g_free (url_str);
366
367   return g_string_free (rtpinfo, FALSE);
368 }
369
370 /**
371  * gst_rtsp_stream_transport_set_active:
372  * @trans: a #GstRTSPStreamTransport
373  * @active: new state of @trans
374  *
375  * Activate or deactivate datatransfer configured in @trans.
376  *
377  * Returns: %TRUE when the state was changed.
378  */
379 gboolean
380 gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans,
381     gboolean active)
382 {
383   GstRTSPStreamTransportPrivate *priv;
384   gboolean res;
385
386   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
387
388   priv = trans->priv;
389
390   if (priv->active == active)
391     return FALSE;
392
393   if (active)
394     res = gst_rtsp_stream_add_transport (priv->stream, trans);
395   else
396     res = gst_rtsp_stream_remove_transport (priv->stream, trans);
397
398   if (res)
399     priv->active = active;
400
401   return res;
402 }
403
404 /**
405  * gst_rtsp_stream_transport_set_timed_out:
406  * @trans: a #GstRTSPStreamTransport
407  * @timedout: timed out value
408  *
409  * Set the timed out state of @trans to @timedout
410  */
411 void
412 gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans,
413     gboolean timedout)
414 {
415   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
416
417   trans->priv->timed_out = timedout;
418 }
419
420 /**
421  * gst_rtsp_stream_transport_is_timed_out:
422  * @trans: a #GstRTSPStreamTransport
423  *
424  * Check if @trans is timed out.
425  *
426  * Returns: %TRUE if @trans timed out.
427  */
428 gboolean
429 gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
430 {
431   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
432
433   return trans->priv->timed_out;
434 }
435
436 /**
437  * gst_rtsp_stream_transport_send_rtp:
438  * @trans: a #GstRTSPStreamTransport
439  * @buffer: (transfer none): a #GstBuffer
440  *
441  * Send @buffer to the installed RTP callback for @trans.
442  *
443  * Returns: %TRUE on success
444  */
445 gboolean
446 gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
447     GstBuffer * buffer)
448 {
449   GstRTSPStreamTransportPrivate *priv;
450   gboolean res = FALSE;
451
452   priv = trans->priv;
453
454   if (priv->send_rtp)
455     res =
456         priv->send_rtp (buffer, priv->transport->interleaved.min,
457         priv->user_data);
458
459   return res;
460 }
461
462 /**
463  * gst_rtsp_stream_transport_send_rtcp:
464  * @trans: a #GstRTSPStreamTransport
465  * @buffer: (transfer none): a #GstBuffer
466  *
467  * Send @buffer to the installed RTCP callback for @trans.
468  *
469  * Returns: %TRUE on success
470  */
471 gboolean
472 gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
473     GstBuffer * buffer)
474 {
475   GstRTSPStreamTransportPrivate *priv;
476   gboolean res = FALSE;
477
478   priv = trans->priv;
479
480   if (priv->send_rtcp)
481     res =
482         priv->send_rtcp (buffer, priv->transport->interleaved.max,
483         priv->user_data);
484
485   return res;
486 }
487
488 /**
489  * gst_rtsp_stream_transport_keep_alive:
490  * @trans: a #GstRTSPStreamTransport
491  *
492  * Signal the installed keep_alive callback for @trans.
493  */
494 void
495 gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
496 {
497   GstRTSPStreamTransportPrivate *priv;
498
499   priv = trans->priv;
500
501   if (priv->keep_alive)
502     priv->keep_alive (priv->ka_user_data);
503 }