Get payloader stats only for the sending streams
[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_is_sender (priv->stream))
343     return NULL;
344   if (!gst_rtsp_stream_get_rtpinfo (priv->stream, &rtptime, &seq, &clock_rate,
345           &running_time))
346     return NULL;
347
348   GST_DEBUG ("RTP time %u, seq %u, rate %u, running-time %" GST_TIME_FORMAT,
349       rtptime, seq, clock_rate, GST_TIME_ARGS (running_time));
350
351   if (GST_CLOCK_TIME_IS_VALID (running_time)
352       && GST_CLOCK_TIME_IS_VALID (start_time)) {
353     if (running_time > start_time) {
354       rtptime -=
355           gst_util_uint64_scale_int (running_time - start_time, clock_rate,
356           GST_SECOND);
357     } else {
358       rtptime +=
359           gst_util_uint64_scale_int (start_time - running_time, clock_rate,
360           GST_SECOND);
361     }
362   }
363   GST_DEBUG ("RTP time %u, for start-time %" GST_TIME_FORMAT,
364       rtptime, GST_TIME_ARGS (start_time));
365
366   rtpinfo = g_string_new ("");
367
368   url_str = gst_rtsp_url_get_request_uri (trans->priv->url);
369   g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u",
370       url_str, seq, rtptime);
371   g_free (url_str);
372
373   return g_string_free (rtpinfo, FALSE);
374 }
375
376 /**
377  * gst_rtsp_stream_transport_set_active:
378  * @trans: a #GstRTSPStreamTransport
379  * @active: new state of @trans
380  *
381  * Activate or deactivate datatransfer configured in @trans.
382  *
383  * Returns: %TRUE when the state was changed.
384  */
385 gboolean
386 gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans,
387     gboolean active)
388 {
389   GstRTSPStreamTransportPrivate *priv;
390   gboolean res;
391
392   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
393
394   priv = trans->priv;
395
396   if (priv->active == active)
397     return FALSE;
398
399   if (active)
400     res = gst_rtsp_stream_add_transport (priv->stream, trans);
401   else
402     res = gst_rtsp_stream_remove_transport (priv->stream, trans);
403
404   if (res)
405     priv->active = active;
406
407   return res;
408 }
409
410 /**
411  * gst_rtsp_stream_transport_set_timed_out:
412  * @trans: a #GstRTSPStreamTransport
413  * @timedout: timed out value
414  *
415  * Set the timed out state of @trans to @timedout
416  */
417 void
418 gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans,
419     gboolean timedout)
420 {
421   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
422
423   trans->priv->timed_out = timedout;
424 }
425
426 /**
427  * gst_rtsp_stream_transport_is_timed_out:
428  * @trans: a #GstRTSPStreamTransport
429  *
430  * Check if @trans is timed out.
431  *
432  * Returns: %TRUE if @trans timed out.
433  */
434 gboolean
435 gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
436 {
437   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
438
439   return trans->priv->timed_out;
440 }
441
442 /**
443  * gst_rtsp_stream_transport_send_rtp:
444  * @trans: a #GstRTSPStreamTransport
445  * @buffer: (transfer none): a #GstBuffer
446  *
447  * Send @buffer to the installed RTP callback for @trans.
448  *
449  * Returns: %TRUE on success
450  */
451 gboolean
452 gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
453     GstBuffer * buffer)
454 {
455   GstRTSPStreamTransportPrivate *priv;
456   gboolean res = FALSE;
457
458   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
459
460   priv = trans->priv;
461
462   if (priv->send_rtp)
463     res =
464         priv->send_rtp (buffer, priv->transport->interleaved.min,
465         priv->user_data);
466
467   if (res)
468     gst_rtsp_stream_transport_keep_alive (trans);
469
470   return res;
471 }
472
473 /**
474  * gst_rtsp_stream_transport_send_rtcp:
475  * @trans: a #GstRTSPStreamTransport
476  * @buffer: (transfer none): a #GstBuffer
477  *
478  * Send @buffer to the installed RTCP callback for @trans.
479  *
480  * Returns: %TRUE on success
481  */
482 gboolean
483 gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
484     GstBuffer * buffer)
485 {
486   GstRTSPStreamTransportPrivate *priv;
487   gboolean res = FALSE;
488
489   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
490
491   priv = trans->priv;
492
493   if (priv->send_rtcp)
494     res =
495         priv->send_rtcp (buffer, priv->transport->interleaved.max,
496         priv->user_data);
497
498   if (res)
499     gst_rtsp_stream_transport_keep_alive (trans);
500
501   return res;
502 }
503
504 /**
505  * gst_rtsp_stream_transport_keep_alive:
506  * @trans: a #GstRTSPStreamTransport
507  *
508  * Signal the installed keep_alive callback for @trans.
509  */
510 void
511 gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
512 {
513   GstRTSPStreamTransportPrivate *priv;
514
515   priv = trans->priv;
516
517   if (priv->keep_alive)
518     priv->keep_alive (priv->ka_user_data);
519 }
520
521 /**
522  * gst_rtsp_stream_transport_recv_data:
523  * @trans: a #GstRTSPStreamTransport
524  * @channel: a channel
525  * @buffer: (transfer full): a #GstBuffer
526  *
527  * Receive @buffer on @channel @trans.
528  *
529  * Returns: a #GstFlowReturn. Returns GST_FLOW_NOT_LINKED when @channel is not
530  *    configured in the transport of @trans.
531  */
532 GstFlowReturn
533 gst_rtsp_stream_transport_recv_data (GstRTSPStreamTransport * trans,
534     guint channel, GstBuffer * buffer)
535 {
536   GstRTSPStreamTransportPrivate *priv;
537   const GstRTSPTransport *tr;
538   GstFlowReturn res;
539
540   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
541
542   priv = trans->priv;
543   tr = priv->transport;
544
545   if (tr->interleaved.min == channel) {
546     res = gst_rtsp_stream_recv_rtp (priv->stream, buffer);
547   } else if (tr->interleaved.max == channel) {
548     res = gst_rtsp_stream_recv_rtcp (priv->stream, buffer);
549   } else {
550     res = GST_FLOW_NOT_LINKED;
551   }
552   return res;
553 }