a9aa897cea67ead86d09c24c426f6390eaac8a8c
[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->stream)
122     g_object_unref (priv->stream);
123
124   if (priv->transport)
125     gst_rtsp_transport_free (priv->transport);
126
127   if (priv->url)
128     gst_rtsp_url_free (priv->url);
129
130   G_OBJECT_CLASS (gst_rtsp_stream_transport_parent_class)->finalize (obj);
131 }
132
133 /**
134  * gst_rtsp_stream_transport_new:
135  * @stream: a #GstRTSPStream
136  * @tr: (transfer full): a GstRTSPTransport
137  *
138  * Create a new #GstRTSPStreamTransport that can be used to manage
139  * @stream with transport @tr.
140  *
141  * Returns: (transfer full): a new #GstRTSPStreamTransport
142  */
143 GstRTSPStreamTransport *
144 gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
145 {
146   GstRTSPStreamTransportPrivate *priv;
147   GstRTSPStreamTransport *trans;
148
149   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
150   g_return_val_if_fail (tr != NULL, NULL);
151
152   trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL);
153   priv = trans->priv;
154   priv->stream = stream;
155   priv->stream = g_object_ref (priv->stream);
156   priv->transport = tr;
157
158   return trans;
159 }
160
161 /**
162  * gst_rtsp_stream_transport_get_stream:
163  * @trans: a #GstRTSPStreamTransport
164  *
165  * Get the #GstRTSPStream used when constructing @trans.
166  *
167  * Returns: (transfer none) (nullable): the stream used when constructing @trans.
168  */
169 GstRTSPStream *
170 gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport * trans)
171 {
172   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
173
174   return trans->priv->stream;
175 }
176
177 /**
178  * gst_rtsp_stream_transport_set_callbacks:
179  * @trans: a #GstRTSPStreamTransport
180  * @send_rtp: (scope notified): a callback called when RTP should be sent
181  * @send_rtcp: (scope notified): a callback called when RTCP should be sent
182  * @user_data: (closure): user data passed to callbacks
183  * @notify: (allow-none): called with the user_data when no longer needed.
184  *
185  * Install callbacks that will be called when data for a stream should be sent
186  * to a client. This is usually used when sending RTP/RTCP over TCP.
187  */
188 void
189 gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport * trans,
190     GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp,
191     gpointer user_data, GDestroyNotify notify)
192 {
193   GstRTSPStreamTransportPrivate *priv;
194
195   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
196
197   priv = trans->priv;
198
199   priv->send_rtp = send_rtp;
200   priv->send_rtcp = send_rtcp;
201   if (priv->notify)
202     priv->notify (priv->user_data);
203   priv->user_data = user_data;
204   priv->notify = notify;
205 }
206
207 /**
208  * gst_rtsp_stream_transport_set_keepalive:
209  * @trans: a #GstRTSPStreamTransport
210  * @keep_alive: (scope notified): a callback called when the receiver is active
211  * @user_data: (closure): user data passed to callback
212  * @notify: (allow-none): called with the user_data when no longer needed.
213  *
214  * Install callbacks that will be called when RTCP packets are received from the
215  * receiver of @trans.
216  */
217 void
218 gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport * trans,
219     GstRTSPKeepAliveFunc keep_alive, gpointer user_data, GDestroyNotify notify)
220 {
221   GstRTSPStreamTransportPrivate *priv;
222
223   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
224
225   priv = trans->priv;
226
227   priv->keep_alive = keep_alive;
228   if (priv->ka_notify)
229     priv->ka_notify (priv->ka_user_data);
230   priv->ka_user_data = user_data;
231   priv->ka_notify = notify;
232 }
233
234
235 /**
236  * gst_rtsp_stream_transport_set_transport:
237  * @trans: a #GstRTSPStreamTransport
238  * @tr: (transfer full): a client #GstRTSPTransport
239  *
240  * Set @tr as the client transport. This function takes ownership of the
241  * passed @tr.
242  */
243 void
244 gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
245     GstRTSPTransport * tr)
246 {
247   GstRTSPStreamTransportPrivate *priv;
248
249   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
250   g_return_if_fail (tr != NULL);
251
252   priv = trans->priv;
253
254   /* keep track of the transports in the stream. */
255   if (priv->transport)
256     gst_rtsp_transport_free (priv->transport);
257   priv->transport = tr;
258 }
259
260 /**
261  * gst_rtsp_stream_transport_get_transport:
262  * @trans: a #GstRTSPStreamTransport
263  *
264  * Get the transport configured in @trans.
265  *
266  * Returns: (transfer none) (nullable): the transport configured in @trans. It remains
267  * valid for as long as @trans is valid.
268  */
269 const GstRTSPTransport *
270 gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans)
271 {
272   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
273
274   return trans->priv->transport;
275 }
276
277 /**
278  * gst_rtsp_stream_transport_set_url:
279  * @trans: a #GstRTSPStreamTransport
280  * @url: (transfer none) (nullable): a client #GstRTSPUrl
281  *
282  * Set @url as the client url.
283  */
284 void
285 gst_rtsp_stream_transport_set_url (GstRTSPStreamTransport * trans,
286     const GstRTSPUrl * url)
287 {
288   GstRTSPStreamTransportPrivate *priv;
289
290   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
291
292   priv = trans->priv;
293
294   /* keep track of the transports in the stream. */
295   if (priv->url)
296     gst_rtsp_url_free (priv->url);
297   priv->url = (url ? gst_rtsp_url_copy (url) : NULL);
298 }
299
300 /**
301  * gst_rtsp_stream_transport_get_url:
302  * @trans: a #GstRTSPStreamTransport
303  *
304  * Get the url configured in @trans.
305  *
306  * Returns: (transfer none) (nullable): the url configured in @trans.
307  * It remains valid for as long as @trans is valid.
308  */
309 const GstRTSPUrl *
310 gst_rtsp_stream_transport_get_url (GstRTSPStreamTransport * trans)
311 {
312   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
313
314   return trans->priv->url;
315 }
316
317  /**
318  * gst_rtsp_stream_transport_get_rtpinfo:
319  * @trans: a #GstRTSPStreamTransport
320  * @start_time: a star time
321  *
322  * Get the RTP-Info string for @trans and @start_time.
323  *
324  * Returns: (transfer full) (nullable): the RTPInfo string for @trans
325  * and @start_time or %NULL when the RTP-Info could not be
326  * determined. g_free() after usage.
327  */
328 gchar *
329 gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport * trans,
330     GstClockTime start_time)
331 {
332   GstRTSPStreamTransportPrivate *priv;
333   gchar *url_str;
334   GString *rtpinfo;
335   guint rtptime, seq, clock_rate;
336   GstClockTime running_time = GST_CLOCK_TIME_NONE;
337
338   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
339
340   priv = trans->priv;
341
342   if (!gst_rtsp_stream_get_rtpinfo (priv->stream, &rtptime, &seq, &clock_rate,
343           &running_time))
344     return NULL;
345
346   GST_DEBUG ("RTP time %u, seq %u, rate %u, running-time %" GST_TIME_FORMAT,
347       rtptime, seq, clock_rate, GST_TIME_ARGS (running_time));
348
349   if (GST_CLOCK_TIME_IS_VALID (running_time)
350       && GST_CLOCK_TIME_IS_VALID (start_time)) {
351     if (running_time > start_time) {
352       rtptime -=
353           gst_util_uint64_scale_int (running_time - start_time, clock_rate,
354           GST_SECOND);
355     } else {
356       rtptime +=
357           gst_util_uint64_scale_int (start_time - running_time, clock_rate,
358           GST_SECOND);
359     }
360   }
361   GST_DEBUG ("RTP time %u, for start-time %" GST_TIME_FORMAT,
362       rtptime, GST_TIME_ARGS (start_time));
363
364   rtpinfo = g_string_new ("");
365
366   url_str = gst_rtsp_url_get_request_uri (trans->priv->url);
367   g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u",
368       url_str, seq, rtptime);
369   g_free (url_str);
370
371   return g_string_free (rtpinfo, FALSE);
372 }
373
374 /**
375  * gst_rtsp_stream_transport_set_active:
376  * @trans: a #GstRTSPStreamTransport
377  * @active: new state of @trans
378  *
379  * Activate or deactivate datatransfer configured in @trans.
380  *
381  * Returns: %TRUE when the state was changed.
382  */
383 gboolean
384 gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans,
385     gboolean active)
386 {
387   GstRTSPStreamTransportPrivate *priv;
388   gboolean res;
389
390   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
391
392   priv = trans->priv;
393
394   if (priv->active == active)
395     return FALSE;
396
397   if (active)
398     res = gst_rtsp_stream_add_transport (priv->stream, trans);
399   else
400     res = gst_rtsp_stream_remove_transport (priv->stream, trans);
401
402   if (res)
403     priv->active = active;
404
405   return res;
406 }
407
408 /**
409  * gst_rtsp_stream_transport_set_timed_out:
410  * @trans: a #GstRTSPStreamTransport
411  * @timedout: timed out value
412  *
413  * Set the timed out state of @trans to @timedout
414  */
415 void
416 gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans,
417     gboolean timedout)
418 {
419   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
420
421   trans->priv->timed_out = timedout;
422 }
423
424 /**
425  * gst_rtsp_stream_transport_is_timed_out:
426  * @trans: a #GstRTSPStreamTransport
427  *
428  * Check if @trans is timed out.
429  *
430  * Returns: %TRUE if @trans timed out.
431  */
432 gboolean
433 gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
434 {
435   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
436
437   return trans->priv->timed_out;
438 }
439
440 /**
441  * gst_rtsp_stream_transport_send_rtp:
442  * @trans: a #GstRTSPStreamTransport
443  * @buffer: (transfer none): a #GstBuffer
444  *
445  * Send @buffer to the installed RTP callback for @trans.
446  *
447  * Returns: %TRUE on success
448  */
449 gboolean
450 gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
451     GstBuffer * buffer)
452 {
453   GstRTSPStreamTransportPrivate *priv;
454   gboolean res = FALSE;
455
456   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
457
458   priv = trans->priv;
459
460   if (priv->send_rtp)
461     res =
462         priv->send_rtp (buffer, priv->transport->interleaved.min,
463         priv->user_data);
464
465   if (res)
466     gst_rtsp_stream_transport_keep_alive (trans);
467
468   return res;
469 }
470
471 /**
472  * gst_rtsp_stream_transport_send_rtcp:
473  * @trans: a #GstRTSPStreamTransport
474  * @buffer: (transfer none): a #GstBuffer
475  *
476  * Send @buffer to the installed RTCP callback for @trans.
477  *
478  * Returns: %TRUE on success
479  */
480 gboolean
481 gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
482     GstBuffer * buffer)
483 {
484   GstRTSPStreamTransportPrivate *priv;
485   gboolean res = FALSE;
486
487   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
488
489   priv = trans->priv;
490
491   if (priv->send_rtcp)
492     res =
493         priv->send_rtcp (buffer, priv->transport->interleaved.max,
494         priv->user_data);
495
496   if (res)
497     gst_rtsp_stream_transport_keep_alive (trans);
498
499   return res;
500 }
501
502 /**
503  * gst_rtsp_stream_transport_keep_alive:
504  * @trans: a #GstRTSPStreamTransport
505  *
506  * Signal the installed keep_alive callback for @trans.
507  */
508 void
509 gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
510 {
511   GstRTSPStreamTransportPrivate *priv;
512
513   priv = trans->priv;
514
515   if (priv->keep_alive)
516     priv->keep_alive (priv->ka_user_data);
517 }
518
519 /**
520  * gst_rtsp_stream_transport_recv_data:
521  * @trans: a #GstRTSPStreamTransport
522  * @channel: a channel
523  * @buffer: (transfer full): a #GstBuffer
524  *
525  * Receive @buffer on @channel @trans.
526  *
527  * Returns: a #GstFlowReturn. Returns GST_FLOW_NOT_LINKED when @channel is not
528  *    configured in the transport of @trans.
529  */
530 GstFlowReturn
531 gst_rtsp_stream_transport_recv_data (GstRTSPStreamTransport * trans,
532     guint channel, GstBuffer * buffer)
533 {
534   GstRTSPStreamTransportPrivate *priv;
535   const GstRTSPTransport *tr;
536   GstFlowReturn res;
537
538   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
539
540   priv = trans->priv;
541   tr = priv->transport;
542
543   if (tr->interleaved.min == channel) {
544     res = gst_rtsp_stream_recv_rtp (priv->stream, buffer);
545   } else if (tr->interleaved.max == channel) {
546     res = gst_rtsp_stream_recv_rtcp (priv->stream, buffer);
547   } else {
548     res = GST_FLOW_NOT_LINKED;
549   }
550   return res;
551 }