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  * A #GstRTSPClient will call gst_rtsp_stream_transport_message_sent() when it
39  * has sent a data message for the transport.
40  *
41  * Last reviewed on 2013-07-16 (1.0.0)
42  */
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46 
47 #include <string.h>
48 #include <stdlib.h>
49 
50 #include "rtsp-stream-transport.h"
51 
52 struct _GstRTSPStreamTransportPrivate
53 {
54   GstRTSPStream *stream;
55 
56   GstRTSPSendFunc send_rtp;
57   GstRTSPSendFunc send_rtcp;
58   gpointer user_data;
59   GDestroyNotify notify;
60 
61   GstRTSPSendListFunc send_rtp_list;
62   GstRTSPSendListFunc send_rtcp_list;
63   gpointer list_user_data;
64   GDestroyNotify list_notify;
65 
66   GstRTSPKeepAliveFunc keep_alive;
67   gpointer ka_user_data;
68   GDestroyNotify ka_notify;
69   gboolean active;
70   gboolean timed_out;
71 
72   GstRTSPMessageSentFunc message_sent;
73   gpointer ms_user_data;
74   GDestroyNotify ms_notify;
75 
76   GstRTSPTransport *transport;
77   GstRTSPUrl *url;
78 
79   GObject *rtpsource;
80 };
81 
82 enum
83 {
84   PROP_0,
85   PROP_LAST
86 };
87 
88 GST_DEBUG_CATEGORY_STATIC (rtsp_stream_transport_debug);
89 #define GST_CAT_DEFAULT rtsp_stream_transport_debug
90 
91 static void gst_rtsp_stream_transport_finalize (GObject * obj);
92 
93 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPStreamTransport, gst_rtsp_stream_transport,
94     G_TYPE_OBJECT);
95 
96 static void
gst_rtsp_stream_transport_class_init(GstRTSPStreamTransportClass * klass)97 gst_rtsp_stream_transport_class_init (GstRTSPStreamTransportClass * klass)
98 {
99   GObjectClass *gobject_class;
100 
101   gobject_class = G_OBJECT_CLASS (klass);
102 
103   gobject_class->finalize = gst_rtsp_stream_transport_finalize;
104 
105   GST_DEBUG_CATEGORY_INIT (rtsp_stream_transport_debug, "rtspmediatransport",
106       0, "GstRTSPStreamTransport");
107 }
108 
109 static void
gst_rtsp_stream_transport_init(GstRTSPStreamTransport * trans)110 gst_rtsp_stream_transport_init (GstRTSPStreamTransport * trans)
111 {
112   trans->priv = gst_rtsp_stream_transport_get_instance_private (trans);
113 }
114 
115 static void
gst_rtsp_stream_transport_finalize(GObject * obj)116 gst_rtsp_stream_transport_finalize (GObject * obj)
117 {
118   GstRTSPStreamTransportPrivate *priv;
119   GstRTSPStreamTransport *trans;
120 
121   trans = GST_RTSP_STREAM_TRANSPORT (obj);
122   priv = trans->priv;
123 
124   /* remove callbacks now */
125   gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
126   gst_rtsp_stream_transport_set_keepalive (trans, NULL, NULL, NULL);
127   gst_rtsp_stream_transport_set_message_sent (trans, NULL, NULL, NULL);
128 
129   if (priv->stream)
130     g_object_unref (priv->stream);
131 
132   if (priv->transport)
133     gst_rtsp_transport_free (priv->transport);
134 
135   if (priv->url)
136     gst_rtsp_url_free (priv->url);
137 
138   G_OBJECT_CLASS (gst_rtsp_stream_transport_parent_class)->finalize (obj);
139 }
140 
141 /**
142  * gst_rtsp_stream_transport_new:
143  * @stream: a #GstRTSPStream
144  * @tr: (transfer full): a GstRTSPTransport
145  *
146  * Create a new #GstRTSPStreamTransport that can be used to manage
147  * @stream with transport @tr.
148  *
149  * Returns: (transfer full): a new #GstRTSPStreamTransport
150  */
151 GstRTSPStreamTransport *
gst_rtsp_stream_transport_new(GstRTSPStream * stream,GstRTSPTransport * tr)152 gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
153 {
154   GstRTSPStreamTransportPrivate *priv;
155   GstRTSPStreamTransport *trans;
156 
157   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
158   g_return_val_if_fail (tr != NULL, NULL);
159 
160   trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL);
161   priv = trans->priv;
162   priv->stream = stream;
163   priv->stream = g_object_ref (priv->stream);
164   priv->transport = tr;
165 
166   return trans;
167 }
168 
169 /**
170  * gst_rtsp_stream_transport_get_stream:
171  * @trans: a #GstRTSPStreamTransport
172  *
173  * Get the #GstRTSPStream used when constructing @trans.
174  *
175  * Returns: (transfer none) (nullable): the stream used when constructing @trans.
176  */
177 GstRTSPStream *
gst_rtsp_stream_transport_get_stream(GstRTSPStreamTransport * trans)178 gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport * trans)
179 {
180   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
181 
182   return trans->priv->stream;
183 }
184 
185 /**
186  * gst_rtsp_stream_transport_set_callbacks:
187  * @trans: a #GstRTSPStreamTransport
188  * @send_rtp: (scope notified): a callback called when RTP should be sent
189  * @send_rtcp: (scope notified): a callback called when RTCP should be sent
190  * @user_data: (closure): user data passed to callbacks
191  * @notify: (allow-none): called with the user_data when no longer needed.
192  *
193  * Install callbacks that will be called when data for a stream should be sent
194  * to a client. This is usually used when sending RTP/RTCP over TCP.
195  */
196 void
gst_rtsp_stream_transport_set_callbacks(GstRTSPStreamTransport * trans,GstRTSPSendFunc send_rtp,GstRTSPSendFunc send_rtcp,gpointer user_data,GDestroyNotify notify)197 gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport * trans,
198     GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp,
199     gpointer user_data, GDestroyNotify notify)
200 {
201   GstRTSPStreamTransportPrivate *priv;
202 
203   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
204 
205   priv = trans->priv;
206 
207   priv->send_rtp = send_rtp;
208   priv->send_rtcp = send_rtcp;
209   if (priv->notify)
210     priv->notify (priv->user_data);
211   priv->user_data = user_data;
212   priv->notify = notify;
213 }
214 
215 /**
216  * gst_rtsp_stream_transport_set_list_callbacks:
217  * @trans: a #GstRTSPStreamTransport
218  * @send_rtp_list: (scope notified): a callback called when RTP should be sent
219  * @send_rtcp_list: (scope notified): a callback called when RTCP should be sent
220  * @user_data: (closure): user data passed to callbacks
221  * @notify: (allow-none): called with the user_data when no longer needed.
222  *
223  * Install callbacks that will be called when data for a stream should be sent
224  * to a client. This is usually used when sending RTP/RTCP over TCP.
225  *
226  * Since: 1.16
227  */
228 void
gst_rtsp_stream_transport_set_list_callbacks(GstRTSPStreamTransport * trans,GstRTSPSendListFunc send_rtp_list,GstRTSPSendListFunc send_rtcp_list,gpointer user_data,GDestroyNotify notify)229 gst_rtsp_stream_transport_set_list_callbacks (GstRTSPStreamTransport * trans,
230     GstRTSPSendListFunc send_rtp_list, GstRTSPSendListFunc send_rtcp_list,
231     gpointer user_data, GDestroyNotify notify)
232 {
233   GstRTSPStreamTransportPrivate *priv;
234 
235   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
236 
237   priv = trans->priv;
238 
239   priv->send_rtp_list = send_rtp_list;
240   priv->send_rtcp_list = send_rtcp_list;
241   if (priv->list_notify)
242     priv->list_notify (priv->list_user_data);
243   priv->list_user_data = user_data;
244   priv->list_notify = notify;
245 }
246 
247 /**
248  * gst_rtsp_stream_transport_set_keepalive:
249  * @trans: a #GstRTSPStreamTransport
250  * @keep_alive: (scope notified): a callback called when the receiver is active
251  * @user_data: (closure): user data passed to callback
252  * @notify: (allow-none): called with the user_data when no longer needed.
253  *
254  * Install callbacks that will be called when RTCP packets are received from the
255  * receiver of @trans.
256  */
257 void
gst_rtsp_stream_transport_set_keepalive(GstRTSPStreamTransport * trans,GstRTSPKeepAliveFunc keep_alive,gpointer user_data,GDestroyNotify notify)258 gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport * trans,
259     GstRTSPKeepAliveFunc keep_alive, gpointer user_data, GDestroyNotify notify)
260 {
261   GstRTSPStreamTransportPrivate *priv;
262 
263   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
264 
265   priv = trans->priv;
266 
267   priv->keep_alive = keep_alive;
268   if (priv->ka_notify)
269     priv->ka_notify (priv->ka_user_data);
270   priv->ka_user_data = user_data;
271   priv->ka_notify = notify;
272 }
273 
274 /**
275  * gst_rtsp_stream_transport_set_message_sent:
276  * @trans: a #GstRTSPStreamTransport
277  * @message_sent: (scope notified): a callback called when a message has been sent
278  * @user_data: (closure): user data passed to callback
279  * @notify: (allow-none): called with the user_data when no longer needed
280  *
281  * Install a callback that will be called when a message has been sent on @trans.
282  */
283 void
gst_rtsp_stream_transport_set_message_sent(GstRTSPStreamTransport * trans,GstRTSPMessageSentFunc message_sent,gpointer user_data,GDestroyNotify notify)284 gst_rtsp_stream_transport_set_message_sent (GstRTSPStreamTransport * trans,
285     GstRTSPMessageSentFunc message_sent, gpointer user_data,
286     GDestroyNotify notify)
287 {
288   GstRTSPStreamTransportPrivate *priv;
289 
290   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
291 
292   priv = trans->priv;
293 
294   priv->message_sent = message_sent;
295   if (priv->ms_notify)
296     priv->ms_notify (priv->ms_user_data);
297   priv->ms_user_data = user_data;
298   priv->ms_notify = notify;
299 }
300 
301 
302 /**
303  * gst_rtsp_stream_transport_set_transport:
304  * @trans: a #GstRTSPStreamTransport
305  * @tr: (transfer full): a client #GstRTSPTransport
306  *
307  * Set @tr as the client transport. This function takes ownership of the
308  * passed @tr.
309  */
310 void
gst_rtsp_stream_transport_set_transport(GstRTSPStreamTransport * trans,GstRTSPTransport * tr)311 gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
312     GstRTSPTransport * tr)
313 {
314   GstRTSPStreamTransportPrivate *priv;
315 
316   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
317   g_return_if_fail (tr != NULL);
318 
319   priv = trans->priv;
320 
321   /* keep track of the transports in the stream. */
322   if (priv->transport)
323     gst_rtsp_transport_free (priv->transport);
324   priv->transport = tr;
325 }
326 
327 /**
328  * gst_rtsp_stream_transport_get_transport:
329  * @trans: a #GstRTSPStreamTransport
330  *
331  * Get the transport configured in @trans.
332  *
333  * Returns: (transfer none) (nullable): the transport configured in @trans. It remains
334  * valid for as long as @trans is valid.
335  */
336 const GstRTSPTransport *
gst_rtsp_stream_transport_get_transport(GstRTSPStreamTransport * trans)337 gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans)
338 {
339   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
340 
341   return trans->priv->transport;
342 }
343 
344 /**
345  * gst_rtsp_stream_transport_set_url:
346  * @trans: a #GstRTSPStreamTransport
347  * @url: (transfer none) (nullable): a client #GstRTSPUrl
348  *
349  * Set @url as the client url.
350  */
351 void
gst_rtsp_stream_transport_set_url(GstRTSPStreamTransport * trans,const GstRTSPUrl * url)352 gst_rtsp_stream_transport_set_url (GstRTSPStreamTransport * trans,
353     const GstRTSPUrl * url)
354 {
355   GstRTSPStreamTransportPrivate *priv;
356 
357   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
358 
359   priv = trans->priv;
360 
361   /* keep track of the transports in the stream. */
362   if (priv->url)
363     gst_rtsp_url_free (priv->url);
364   priv->url = (url ? gst_rtsp_url_copy (url) : NULL);
365 }
366 
367 /**
368  * gst_rtsp_stream_transport_get_url:
369  * @trans: a #GstRTSPStreamTransport
370  *
371  * Get the url configured in @trans.
372  *
373  * Returns: (transfer none) (nullable): the url configured in @trans.
374  * It remains valid for as long as @trans is valid.
375  */
376 const GstRTSPUrl *
gst_rtsp_stream_transport_get_url(GstRTSPStreamTransport * trans)377 gst_rtsp_stream_transport_get_url (GstRTSPStreamTransport * trans)
378 {
379   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
380 
381   return trans->priv->url;
382 }
383 
384  /**
385  * gst_rtsp_stream_transport_get_rtpinfo:
386  * @trans: a #GstRTSPStreamTransport
387  * @start_time: a star time
388  *
389  * Get the RTP-Info string for @trans and @start_time.
390  *
391  * Returns: (transfer full) (nullable): the RTPInfo string for @trans
392  * and @start_time or %NULL when the RTP-Info could not be
393  * determined. g_free() after usage.
394  */
395 gchar *
gst_rtsp_stream_transport_get_rtpinfo(GstRTSPStreamTransport * trans,GstClockTime start_time)396 gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport * trans,
397     GstClockTime start_time)
398 {
399   GstRTSPStreamTransportPrivate *priv;
400   gchar *url_str;
401   GString *rtpinfo;
402   guint rtptime, seq, clock_rate;
403   GstClockTime running_time = GST_CLOCK_TIME_NONE;
404 
405   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
406 
407   priv = trans->priv;
408 
409   if (!gst_rtsp_stream_is_sender (priv->stream))
410     return NULL;
411   if (!gst_rtsp_stream_get_rtpinfo (priv->stream, &rtptime, &seq, &clock_rate,
412           &running_time))
413     return NULL;
414 
415   GST_DEBUG ("RTP time %u, seq %u, rate %u, running-time %" GST_TIME_FORMAT,
416       rtptime, seq, clock_rate, GST_TIME_ARGS (running_time));
417 
418   if (GST_CLOCK_TIME_IS_VALID (running_time)
419       && GST_CLOCK_TIME_IS_VALID (start_time)) {
420     if (running_time > start_time) {
421       rtptime -=
422           gst_util_uint64_scale_int (running_time - start_time, clock_rate,
423           GST_SECOND);
424     } else {
425       rtptime +=
426           gst_util_uint64_scale_int (start_time - running_time, clock_rate,
427           GST_SECOND);
428     }
429   }
430   GST_DEBUG ("RTP time %u, for start-time %" GST_TIME_FORMAT,
431       rtptime, GST_TIME_ARGS (start_time));
432 
433   rtpinfo = g_string_new ("");
434 
435   url_str = gst_rtsp_url_get_request_uri (trans->priv->url);
436   g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u",
437       url_str, seq, rtptime);
438   g_free (url_str);
439 
440   return g_string_free (rtpinfo, FALSE);
441 }
442 
443 /**
444  * gst_rtsp_stream_transport_set_active:
445  * @trans: a #GstRTSPStreamTransport
446  * @active: new state of @trans
447  *
448  * Activate or deactivate datatransfer configured in @trans.
449  *
450  * Returns: %TRUE when the state was changed.
451  */
452 gboolean
gst_rtsp_stream_transport_set_active(GstRTSPStreamTransport * trans,gboolean active)453 gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans,
454     gboolean active)
455 {
456   GstRTSPStreamTransportPrivate *priv;
457   gboolean res;
458 
459   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
460 
461   priv = trans->priv;
462 
463   if (priv->active == active)
464     return FALSE;
465 
466   if (active)
467     res = gst_rtsp_stream_add_transport (priv->stream, trans);
468   else
469     res = gst_rtsp_stream_remove_transport (priv->stream, trans);
470 
471   if (res)
472     priv->active = active;
473 
474   return res;
475 }
476 
477 /**
478  * gst_rtsp_stream_transport_set_timed_out:
479  * @trans: a #GstRTSPStreamTransport
480  * @timedout: timed out value
481  *
482  * Set the timed out state of @trans to @timedout
483  */
484 void
gst_rtsp_stream_transport_set_timed_out(GstRTSPStreamTransport * trans,gboolean timedout)485 gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans,
486     gboolean timedout)
487 {
488   g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
489 
490   trans->priv->timed_out = timedout;
491 }
492 
493 /**
494  * gst_rtsp_stream_transport_is_timed_out:
495  * @trans: a #GstRTSPStreamTransport
496  *
497  * Check if @trans is timed out.
498  *
499  * Returns: %TRUE if @trans timed out.
500  */
501 gboolean
gst_rtsp_stream_transport_is_timed_out(GstRTSPStreamTransport * trans)502 gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
503 {
504   g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
505 
506   return trans->priv->timed_out;
507 }
508 
509 /**
510  * gst_rtsp_stream_transport_send_rtp:
511  * @trans: a #GstRTSPStreamTransport
512  * @buffer: (transfer none): a #GstBuffer
513  *
514  * Send @buffer to the installed RTP callback for @trans.
515  *
516  * Returns: %TRUE on success
517  */
518 gboolean
gst_rtsp_stream_transport_send_rtp(GstRTSPStreamTransport * trans,GstBuffer * buffer)519 gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
520     GstBuffer * buffer)
521 {
522   GstRTSPStreamTransportPrivate *priv;
523   gboolean res = FALSE;
524 
525   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
526 
527   priv = trans->priv;
528 
529   if (priv->send_rtp)
530     res =
531         priv->send_rtp (buffer, priv->transport->interleaved.min,
532         priv->user_data);
533 
534   if (res)
535     gst_rtsp_stream_transport_keep_alive (trans);
536 
537   return res;
538 }
539 
540 /**
541  * gst_rtsp_stream_transport_send_rtcp:
542  * @trans: a #GstRTSPStreamTransport
543  * @buffer: (transfer none): a #GstBuffer
544  *
545  * Send @buffer to the installed RTCP callback for @trans.
546  *
547  * Returns: %TRUE on success
548  */
549 gboolean
gst_rtsp_stream_transport_send_rtcp(GstRTSPStreamTransport * trans,GstBuffer * buffer)550 gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
551     GstBuffer * buffer)
552 {
553   GstRTSPStreamTransportPrivate *priv;
554   gboolean res = FALSE;
555 
556   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
557 
558   priv = trans->priv;
559 
560   if (priv->send_rtcp)
561     res =
562         priv->send_rtcp (buffer, priv->transport->interleaved.max,
563         priv->user_data);
564 
565   if (res)
566     gst_rtsp_stream_transport_keep_alive (trans);
567 
568   return res;
569 }
570 
571 /**
572  * gst_rtsp_stream_transport_send_rtp_list:
573  * @trans: a #GstRTSPStreamTransport
574  * @buffer_list: (transfer none): a #GstBufferList
575  *
576  * Send @buffer_list to the installed RTP callback for @trans.
577  *
578  * Returns: %TRUE on success
579  *
580  * Since: 1.16
581  */
582 gboolean
gst_rtsp_stream_transport_send_rtp_list(GstRTSPStreamTransport * trans,GstBufferList * buffer_list)583 gst_rtsp_stream_transport_send_rtp_list (GstRTSPStreamTransport * trans,
584     GstBufferList * buffer_list)
585 {
586   GstRTSPStreamTransportPrivate *priv;
587   gboolean res = FALSE;
588 
589   g_return_val_if_fail (GST_IS_BUFFER_LIST (buffer_list), FALSE);
590 
591   priv = trans->priv;
592 
593   if (priv->send_rtp_list) {
594     res =
595         priv->send_rtp_list (buffer_list, priv->transport->interleaved.min,
596         priv->list_user_data);
597   } else if (priv->send_rtp) {
598     guint n = gst_buffer_list_length (buffer_list), i;
599 
600     for (i = 0; i < n; i++) {
601       GstBuffer *buffer = gst_buffer_list_get (buffer_list, i);
602 
603       res =
604           priv->send_rtp (buffer, priv->transport->interleaved.min,
605           priv->user_data);
606       if (!res)
607         break;
608     }
609   }
610 
611   if (res)
612     gst_rtsp_stream_transport_keep_alive (trans);
613 
614   return res;
615 }
616 
617 /**
618  * gst_rtsp_stream_transport_send_rtcp_list:
619  * @trans: a #GstRTSPStreamTransport
620  * @buffer_list: (transfer none): a #GstBuffer
621  *
622  * Send @buffer_list to the installed RTCP callback for @trans.
623  *
624  * Returns: %TRUE on success
625  *
626  * Since: 1.16
627  */
628 gboolean
gst_rtsp_stream_transport_send_rtcp_list(GstRTSPStreamTransport * trans,GstBufferList * buffer_list)629 gst_rtsp_stream_transport_send_rtcp_list (GstRTSPStreamTransport * trans,
630     GstBufferList * buffer_list)
631 {
632   GstRTSPStreamTransportPrivate *priv;
633   gboolean res = FALSE;
634 
635   g_return_val_if_fail (GST_IS_BUFFER_LIST (buffer_list), FALSE);
636 
637   priv = trans->priv;
638 
639   if (priv->send_rtcp_list) {
640     res =
641         priv->send_rtcp_list (buffer_list, priv->transport->interleaved.max,
642         priv->list_user_data);
643   } else if (priv->send_rtcp) {
644     guint n = gst_buffer_list_length (buffer_list), i;
645 
646     for (i = 0; i < n; i++) {
647       GstBuffer *buffer = gst_buffer_list_get (buffer_list, i);
648 
649       res =
650           priv->send_rtcp (buffer, priv->transport->interleaved.max,
651           priv->user_data);
652       if (!res)
653         break;
654     }
655   }
656 
657   if (res)
658     gst_rtsp_stream_transport_keep_alive (trans);
659 
660   return res;
661 }
662 
663 /**
664  * gst_rtsp_stream_transport_keep_alive:
665  * @trans: a #GstRTSPStreamTransport
666  *
667  * Signal the installed keep_alive callback for @trans.
668  */
669 void
gst_rtsp_stream_transport_keep_alive(GstRTSPStreamTransport * trans)670 gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
671 {
672   GstRTSPStreamTransportPrivate *priv;
673 
674   priv = trans->priv;
675 
676   if (priv->keep_alive)
677     priv->keep_alive (priv->ka_user_data);
678 }
679 
680 /**
681  * gst_rtsp_stream_transport_message_sent:
682  * @trans: a #GstRTSPStreamTransport
683  *
684  * Signal the installed message_sent callback for @trans.
685  *
686  * Since: 1.16
687  */
688 void
gst_rtsp_stream_transport_message_sent(GstRTSPStreamTransport * trans)689 gst_rtsp_stream_transport_message_sent (GstRTSPStreamTransport * trans)
690 {
691   GstRTSPStreamTransportPrivate *priv;
692 
693   priv = trans->priv;
694 
695   if (priv->message_sent)
696     priv->message_sent (priv->ms_user_data);
697 }
698 
699 /**
700  * gst_rtsp_stream_transport_recv_data:
701  * @trans: a #GstRTSPStreamTransport
702  * @channel: a channel
703  * @buffer: (transfer full): a #GstBuffer
704  *
705  * Receive @buffer on @channel @trans.
706  *
707  * Returns: a #GstFlowReturn. Returns GST_FLOW_NOT_LINKED when @channel is not
708  *    configured in the transport of @trans.
709  */
710 GstFlowReturn
gst_rtsp_stream_transport_recv_data(GstRTSPStreamTransport * trans,guint channel,GstBuffer * buffer)711 gst_rtsp_stream_transport_recv_data (GstRTSPStreamTransport * trans,
712     guint channel, GstBuffer * buffer)
713 {
714   GstRTSPStreamTransportPrivate *priv;
715   const GstRTSPTransport *tr;
716   GstFlowReturn res;
717 
718   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
719 
720   priv = trans->priv;
721   tr = priv->transport;
722 
723   if (tr->interleaved.min == channel) {
724     res = gst_rtsp_stream_recv_rtp (priv->stream, buffer);
725   } else if (tr->interleaved.max == channel) {
726     res = gst_rtsp_stream_recv_rtcp (priv->stream, buffer);
727   } else {
728     res = GST_FLOW_NOT_LINKED;
729   }
730   return res;
731 }
732