2 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
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.
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.
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
23 #include <gst/app/gstappsrc.h>
24 #include <gst/app/gstappsink.h>
26 #include "rtsp-media.h"
28 #define DEFAULT_SHARED FALSE
29 #define DEFAULT_REUSABLE FALSE
30 #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
31 //#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP_MCAST
32 #define DEFAULT_EOS_SHUTDOWN FALSE
34 /* define to dump received RTCP packets */
53 GST_DEBUG_CATEGORY_EXTERN (rtsp_media_debug);
54 #define GST_CAT_DEFAULT rtsp_media_debug
56 static GQuark ssrc_stream_map_key;
58 static void gst_rtsp_media_get_property (GObject * object, guint propid,
59 GValue * value, GParamSpec * pspec);
60 static void gst_rtsp_media_set_property (GObject * object, guint propid,
61 const GValue * value, GParamSpec * pspec);
62 static void gst_rtsp_media_finalize (GObject * obj);
64 static gpointer do_loop (GstRTSPMediaClass * klass);
65 static gboolean default_handle_message (GstRTSPMedia * media,
66 GstMessage * message);
67 static gboolean default_unprepare (GstRTSPMedia * media);
68 static void unlock_streams (GstRTSPMedia * media);
70 static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
72 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
75 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
77 GObjectClass *gobject_class;
80 gobject_class = G_OBJECT_CLASS (klass);
82 gobject_class->get_property = gst_rtsp_media_get_property;
83 gobject_class->set_property = gst_rtsp_media_set_property;
84 gobject_class->finalize = gst_rtsp_media_finalize;
86 g_object_class_install_property (gobject_class, PROP_SHARED,
87 g_param_spec_boolean ("shared", "Shared",
88 "If this media pipeline can be shared", DEFAULT_SHARED,
89 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
91 g_object_class_install_property (gobject_class, PROP_REUSABLE,
92 g_param_spec_boolean ("reusable", "Reusable",
93 "If this media pipeline can be reused after an unprepare",
94 DEFAULT_REUSABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
96 g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
97 g_param_spec_flags ("protocols", "Protocols",
98 "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
99 DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
101 g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
102 g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
103 "Send an EOS event to the pipeline before unpreparing",
104 DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
106 gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
107 g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
108 G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
109 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
111 klass->context = g_main_context_new ();
112 klass->loop = g_main_loop_new (klass->context, TRUE);
114 klass->thread = g_thread_create ((GThreadFunc) do_loop, klass, TRUE, &error);
116 g_critical ("could not start bus thread: %s", error->message);
118 klass->handle_message = default_handle_message;
119 klass->unprepare = default_unprepare;
121 ssrc_stream_map_key = g_quark_from_static_string ("GstRTSPServer.stream");
125 gst_rtsp_media_init (GstRTSPMedia * media)
127 media->streams = g_array_new (FALSE, TRUE, sizeof (GstRTSPMediaStream *));
128 media->lock = g_mutex_new ();
129 media->cond = g_cond_new ();
131 media->shared = DEFAULT_SHARED;
132 media->reusable = DEFAULT_REUSABLE;
133 media->protocols = DEFAULT_PROTOCOLS;
134 media->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
137 /* FIXME. this should be done in multiudpsink */
146 dest_compare (RTSPDestination * a, RTSPDestination * b)
148 if ((a->min == b->min) && (a->max == b->max)
149 && (strcmp (a->dest, b->dest) == 0))
155 static RTSPDestination *
156 create_destination (const gchar * dest, gint min, gint max)
158 RTSPDestination *res;
160 res = g_slice_new (RTSPDestination);
162 res->dest = g_strdup (dest);
170 free_destination (RTSPDestination * dest)
173 g_slice_free (RTSPDestination, dest);
177 gst_rtsp_media_trans_cleanup (GstRTSPMediaTrans * trans)
179 if (trans->transport) {
180 gst_rtsp_transport_free (trans->transport);
181 trans->transport = NULL;
183 if (trans->rtpsource) {
184 g_object_set_qdata (trans->rtpsource, ssrc_stream_map_key, NULL);
185 trans->rtpsource = NULL;
190 gst_rtsp_media_stream_free (GstRTSPMediaStream * stream)
193 g_object_unref (stream->session);
196 gst_caps_unref (stream->caps);
198 if (stream->send_rtp_sink)
199 gst_object_unref (stream->send_rtp_sink);
200 if (stream->send_rtp_src)
201 gst_object_unref (stream->send_rtp_src);
202 if (stream->send_rtcp_src)
203 gst_object_unref (stream->send_rtcp_src);
204 if (stream->recv_rtcp_sink)
205 gst_object_unref (stream->recv_rtcp_sink);
206 if (stream->recv_rtp_sink)
207 gst_object_unref (stream->recv_rtp_sink);
209 g_list_free (stream->transports);
211 g_list_foreach (stream->destinations, (GFunc) free_destination, NULL);
212 g_list_free (stream->destinations);
218 gst_rtsp_media_finalize (GObject * obj)
223 media = GST_RTSP_MEDIA (obj);
225 GST_INFO ("finalize media %p", media);
227 if (media->pipeline) {
228 unlock_streams (media);
229 gst_element_set_state (media->pipeline, GST_STATE_NULL);
230 gst_object_unref (media->pipeline);
233 for (i = 0; i < media->streams->len; i++) {
234 GstRTSPMediaStream *stream;
236 stream = g_array_index (media->streams, GstRTSPMediaStream *, i);
238 gst_rtsp_media_stream_free (stream);
240 g_array_free (media->streams, TRUE);
242 g_list_foreach (media->dynamic, (GFunc) gst_object_unref, NULL);
243 g_list_free (media->dynamic);
246 g_source_destroy (media->source);
247 g_source_unref (media->source);
249 g_mutex_free (media->lock);
250 g_cond_free (media->cond);
252 G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
256 gst_rtsp_media_get_property (GObject * object, guint propid,
257 GValue * value, GParamSpec * pspec)
259 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
263 g_value_set_boolean (value, gst_rtsp_media_is_shared (media));
266 g_value_set_boolean (value, gst_rtsp_media_is_reusable (media));
269 g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
271 case PROP_EOS_SHUTDOWN:
272 g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
275 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
280 gst_rtsp_media_set_property (GObject * object, guint propid,
281 const GValue * value, GParamSpec * pspec)
283 GstRTSPMedia *media = GST_RTSP_MEDIA (object);
287 gst_rtsp_media_set_shared (media, g_value_get_boolean (value));
290 gst_rtsp_media_set_reusable (media, g_value_get_boolean (value));
293 gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
295 case PROP_EOS_SHUTDOWN:
296 gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
299 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
304 do_loop (GstRTSPMediaClass * klass)
306 GST_INFO ("enter mainloop");
307 g_main_loop_run (klass->loop);
308 GST_INFO ("exit mainloop");
314 collect_media_stats (GstRTSPMedia * media)
317 gint64 position, duration;
319 media->range.unit = GST_RTSP_RANGE_NPT;
321 if (media->is_live) {
322 media->range.min.type = GST_RTSP_TIME_NOW;
323 media->range.min.seconds = -1;
324 media->range.max.type = GST_RTSP_TIME_END;
325 media->range.max.seconds = -1;
327 /* get the position */
328 format = GST_FORMAT_TIME;
329 if (!gst_element_query_position (media->pipeline, &format, &position)) {
330 GST_INFO ("position query failed");
334 /* get the duration */
335 format = GST_FORMAT_TIME;
336 if (!gst_element_query_duration (media->pipeline, &format, &duration)) {
337 GST_INFO ("duration query failed");
341 GST_INFO ("stats: position %" GST_TIME_FORMAT ", duration %"
342 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
344 if (position == -1) {
345 media->range.min.type = GST_RTSP_TIME_NOW;
346 media->range.min.seconds = -1;
348 media->range.min.type = GST_RTSP_TIME_SECONDS;
349 media->range.min.seconds = ((gdouble) position) / GST_SECOND;
351 if (duration == -1) {
352 media->range.max.type = GST_RTSP_TIME_END;
353 media->range.max.seconds = -1;
355 media->range.max.type = GST_RTSP_TIME_SECONDS;
356 media->range.max.seconds = ((gdouble) duration) / GST_SECOND;
362 * gst_rtsp_media_new:
364 * Create a new #GstRTSPMedia instance. The #GstRTSPMedia object contains the
365 * element to produde RTP data for one or more related (audio/video/..)
368 * Returns: a new #GstRTSPMedia object.
371 gst_rtsp_media_new (void)
373 GstRTSPMedia *result;
375 result = g_object_new (GST_TYPE_RTSP_MEDIA, NULL);
381 * gst_rtsp_media_set_shared:
382 * @media: a #GstRTSPMedia
383 * @shared: the new value
385 * Set or unset if the pipeline for @media can be shared will multiple clients.
386 * When @shared is %TRUE, client requests for this media will share the media
390 gst_rtsp_media_set_shared (GstRTSPMedia * media, gboolean shared)
392 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
394 media->shared = shared;
398 * gst_rtsp_media_is_shared:
399 * @media: a #GstRTSPMedia
401 * Check if the pipeline for @media can be shared between multiple clients.
403 * Returns: %TRUE if the media can be shared between clients.
406 gst_rtsp_media_is_shared (GstRTSPMedia * media)
408 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
410 return media->shared;
414 * gst_rtsp_media_set_reusable:
415 * @media: a #GstRTSPMedia
416 * @reusable: the new value
418 * Set or unset if the pipeline for @media can be reused after the pipeline has
422 gst_rtsp_media_set_reusable (GstRTSPMedia * media, gboolean reusable)
424 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
426 media->reusable = reusable;
430 * gst_rtsp_media_is_reusable:
431 * @media: a #GstRTSPMedia
433 * Check if the pipeline for @media can be reused after an unprepare.
435 * Returns: %TRUE if the media can be reused
438 gst_rtsp_media_is_reusable (GstRTSPMedia * media)
440 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
442 return media->reusable;
446 * gst_rtsp_media_set_protocols:
447 * @media: a #GstRTSPMedia
448 * @protocols: the new flags
450 * Configure the allowed lower transport for @media.
453 gst_rtsp_media_set_protocols (GstRTSPMedia * media, GstRTSPLowerTrans protocols)
455 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
457 media->protocols = protocols;
461 * gst_rtsp_media_get_protocols:
462 * @media: a #GstRTSPMedia
464 * Get the allowed protocols of @media.
466 * Returns: a #GstRTSPLowerTrans
469 gst_rtsp_media_get_protocols (GstRTSPMedia * media)
471 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media),
472 GST_RTSP_LOWER_TRANS_UNKNOWN);
474 return media->protocols;
478 * gst_rtsp_media_set_eos_shutdown:
479 * @media: a #GstRTSPMedia
480 * @eos_shutdown: the new value
482 * Set or unset if an EOS event will be sent to the pipeline for @media before
486 gst_rtsp_media_set_eos_shutdown (GstRTSPMedia * media, gboolean eos_shutdown)
488 g_return_if_fail (GST_IS_RTSP_MEDIA (media));
490 media->eos_shutdown = eos_shutdown;
494 * gst_rtsp_media_is_eos_shutdown:
495 * @media: a #GstRTSPMedia
497 * Check if the pipeline for @media will send an EOS down the pipeline before
500 * Returns: %TRUE if the media will send EOS before unpreparing.
503 gst_rtsp_media_is_eos_shutdown (GstRTSPMedia * media)
505 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
507 return media->eos_shutdown;
511 * gst_rtsp_media_n_streams:
512 * @media: a #GstRTSPMedia
514 * Get the number of streams in this media.
516 * Returns: The number of streams.
519 gst_rtsp_media_n_streams (GstRTSPMedia * media)
521 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
523 return media->streams->len;
527 * gst_rtsp_media_get_stream:
528 * @media: a #GstRTSPMedia
529 * @idx: the stream index
531 * Retrieve the stream with index @idx from @media.
533 * Returns: the #GstRTSPMediaStream at index @idx or %NULL when a stream with
534 * that index did not exist.
537 gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
539 GstRTSPMediaStream *res;
541 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
543 if (idx < media->streams->len)
544 res = g_array_index (media->streams, GstRTSPMediaStream *, idx);
552 * gst_rtsp_media_seek:
553 * @media: a #GstRTSPMedia
554 * @range: a #GstRTSPTimeRange
556 * Seek the pipeline to @range.
558 * Returns: %TRUE on success.
561 gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
566 GstSeekType start_type, stop_type;
568 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
569 g_return_val_if_fail (range != NULL, FALSE);
571 if (range->unit != GST_RTSP_RANGE_NPT)
574 /* depends on the current playing state of the pipeline. We might need to
575 * queue this until we get EOS. */
576 flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT;
578 start_type = stop_type = GST_SEEK_TYPE_NONE;
580 switch (range->min.type) {
581 case GST_RTSP_TIME_NOW:
584 case GST_RTSP_TIME_SECONDS:
585 /* only seek when something changed */
586 if (media->range.min.seconds == range->min.seconds) {
589 start = range->min.seconds * GST_SECOND;
590 start_type = GST_SEEK_TYPE_SET;
593 case GST_RTSP_TIME_END:
597 switch (range->max.type) {
598 case GST_RTSP_TIME_SECONDS:
599 /* only seek when something changed */
600 if (media->range.max.seconds == range->max.seconds) {
603 stop = range->max.seconds * GST_SECOND;
604 stop_type = GST_SEEK_TYPE_SET;
607 case GST_RTSP_TIME_END:
609 stop_type = GST_SEEK_TYPE_SET;
611 case GST_RTSP_TIME_NOW:
616 if (start != -1 || stop != -1) {
617 GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
618 GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
620 res = gst_element_seek (media->pipeline, 1.0, GST_FORMAT_TIME,
621 flags, start_type, start, stop_type, stop);
623 /* and block for the seek to complete */
624 GST_INFO ("done seeking %d", res);
625 gst_element_get_state (media->pipeline, NULL, NULL, -1);
626 GST_INFO ("prerolled again");
628 collect_media_stats (media);
630 GST_INFO ("no seek needed");
639 GST_WARNING ("seek unit %d not supported", range->unit);
644 GST_WARNING ("weird range type %d not supported", range->min.type);
650 * gst_rtsp_media_stream_rtp:
651 * @stream: a #GstRTSPMediaStream
652 * @buffer: a #GstBuffer
654 * Handle an RTP buffer for the stream. This method is usually called when a
655 * message has been received from a client using the TCP transport.
657 * This function takes ownership of @buffer.
659 * Returns: a GstFlowReturn.
662 gst_rtsp_media_stream_rtp (GstRTSPMediaStream * stream, GstBuffer * buffer)
666 ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (stream->appsrc[0]), buffer);
672 * gst_rtsp_media_stream_rtcp:
673 * @stream: a #GstRTSPMediaStream
674 * @buffer: a #GstBuffer
676 * Handle an RTCP buffer for the stream. This method is usually called when a
677 * message has been received from a client using the TCP transport.
679 * This function takes ownership of @buffer.
681 * Returns: a GstFlowReturn.
684 gst_rtsp_media_stream_rtcp (GstRTSPMediaStream * stream, GstBuffer * buffer)
688 ret = gst_app_src_push_buffer (GST_APP_SRC_CAST (stream->appsrc[1]), buffer);
693 /* Allocate the udp ports and sockets */
695 alloc_udp_ports (GstRTSPMedia * media, GstRTSPMediaStream * stream)
697 GstStateChangeReturn ret;
698 GstElement *udpsrc0, *udpsrc1;
699 GstElement *udpsink0, *udpsink1;
700 gint tmp_rtp, tmp_rtcp;
702 gint rtpport, rtcpport, sockfd;
711 /* Start with random port */
715 host = "udp://[::0]";
717 host = "udp://0.0.0.0";
719 /* try to allocate 2 UDP ports, the RTP port should be an even
720 * number and the RTCP port should be the next (uneven) port */
722 udpsrc0 = gst_element_make_from_uri (GST_URI_SRC, host, NULL);
724 goto no_udp_protocol;
725 g_object_set (G_OBJECT (udpsrc0), "port", tmp_rtp, NULL);
727 ret = gst_element_set_state (udpsrc0, GST_STATE_PAUSED);
728 if (ret == GST_STATE_CHANGE_FAILURE) {
734 gst_element_set_state (udpsrc0, GST_STATE_NULL);
735 gst_object_unref (udpsrc0);
739 goto no_udp_protocol;
742 g_object_get (G_OBJECT (udpsrc0), "port", &tmp_rtp, NULL);
744 /* check if port is even */
745 if ((tmp_rtp & 1) != 0) {
746 /* port not even, close and allocate another */
750 gst_element_set_state (udpsrc0, GST_STATE_NULL);
751 gst_object_unref (udpsrc0);
757 /* allocate port+1 for RTCP now */
758 udpsrc1 = gst_element_make_from_uri (GST_URI_SRC, host, NULL);
760 goto no_udp_rtcp_protocol;
763 tmp_rtcp = tmp_rtp + 1;
764 g_object_set (G_OBJECT (udpsrc1), "port", tmp_rtcp, NULL);
766 ret = gst_element_set_state (udpsrc1, GST_STATE_PAUSED);
767 /* tmp_rtcp port is busy already : retry to make rtp/rtcp pair */
768 if (ret == GST_STATE_CHANGE_FAILURE) {
773 gst_element_set_state (udpsrc0, GST_STATE_NULL);
774 gst_object_unref (udpsrc0);
776 gst_element_set_state (udpsrc1, GST_STATE_NULL);
777 gst_object_unref (udpsrc1);
783 /* all fine, do port check */
784 g_object_get (G_OBJECT (udpsrc0), "port", &rtpport, NULL);
785 g_object_get (G_OBJECT (udpsrc1), "port", &rtcpport, NULL);
787 /* this should not happen... */
788 if (rtpport != tmp_rtp || rtcpport != tmp_rtcp)
791 udpsink0 = gst_element_factory_make ("multiudpsink", NULL);
793 goto no_udp_protocol;
795 g_object_get (G_OBJECT (udpsrc0), "sock", &sockfd, NULL);
796 g_object_set (G_OBJECT (udpsink0), "sockfd", sockfd, NULL);
797 g_object_set (G_OBJECT (udpsink0), "closefd", FALSE, NULL);
799 udpsink1 = gst_element_factory_make ("multiudpsink", NULL);
801 goto no_udp_protocol;
803 if (g_object_class_find_property (G_OBJECT_GET_CLASS (udpsink0),
804 "send-duplicates")) {
805 g_object_set (G_OBJECT (udpsink0), "send-duplicates", FALSE, NULL);
806 g_object_set (G_OBJECT (udpsink1), "send-duplicates", FALSE, NULL);
807 stream->filter_duplicates = FALSE;
809 GST_WARNING ("multiudpsink version found without send-duplicates property");
810 stream->filter_duplicates = TRUE;
813 g_object_get (G_OBJECT (udpsrc1), "sock", &sockfd, NULL);
814 g_object_set (G_OBJECT (udpsink1), "sockfd", sockfd, NULL);
815 g_object_set (G_OBJECT (udpsink1), "closefd", FALSE, NULL);
816 g_object_set (G_OBJECT (udpsink1), "sync", FALSE, NULL);
817 g_object_set (G_OBJECT (udpsink1), "async", FALSE, NULL);
819 g_object_set (G_OBJECT (udpsink0), "auto-multicast", FALSE, NULL);
820 g_object_set (G_OBJECT (udpsink0), "loop", FALSE, NULL);
821 g_object_set (G_OBJECT (udpsink1), "auto-multicast", FALSE, NULL);
822 g_object_set (G_OBJECT (udpsink1), "loop", FALSE, NULL);
824 /* we keep these elements, we configure all in configure_transport when the
825 * server told us to really use the UDP ports. */
826 stream->udpsrc[0] = udpsrc0;
827 stream->udpsrc[1] = udpsrc1;
828 stream->udpsink[0] = udpsink0;
829 stream->udpsink[1] = udpsink1;
830 stream->server_port.min = rtpport;
831 stream->server_port.max = rtcpport;
844 no_udp_rtcp_protocol:
855 gst_element_set_state (udpsrc0, GST_STATE_NULL);
856 gst_object_unref (udpsrc0);
859 gst_element_set_state (udpsrc1, GST_STATE_NULL);
860 gst_object_unref (udpsrc1);
863 gst_element_set_state (udpsink0, GST_STATE_NULL);
864 gst_object_unref (udpsink0);
867 gst_element_set_state (udpsink1, GST_STATE_NULL);
868 gst_object_unref (udpsink1);
874 /* executed from streaming thread */
876 caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPMediaStream * stream)
879 GstCaps *newcaps, *oldcaps;
881 if ((newcaps = GST_PAD_CAPS (pad)))
882 gst_caps_ref (newcaps);
884 oldcaps = stream->caps;
885 stream->caps = newcaps;
888 gst_caps_unref (oldcaps);
890 capsstr = gst_caps_to_string (newcaps);
891 GST_INFO ("stream %p received caps %p, %s", stream, newcaps, capsstr);
896 dump_structure (const GstStructure * s)
900 sstr = gst_structure_to_string (s);
901 GST_INFO ("structure: %s", sstr);
905 static GstRTSPMediaTrans *
906 find_transport (GstRTSPMediaStream * stream, const gchar * rtcp_from)
909 GstRTSPMediaTrans *result = NULL;
914 if (rtcp_from == NULL)
917 tmp = g_strrstr (rtcp_from, ":");
921 port = atoi (tmp + 1);
922 dest = g_strndup (rtcp_from, tmp - rtcp_from);
924 GST_INFO ("finding %s:%d", dest, port);
926 for (walk = stream->transports; walk; walk = g_list_next (walk)) {
927 GstRTSPMediaTrans *trans = walk->data;
930 min = trans->transport->client_port.min;
931 max = trans->transport->client_port.max;
933 if ((strcmp (trans->transport->destination, dest) == 0) && (min == port
945 on_new_ssrc (GObject * session, GObject * source, GstRTSPMediaStream * stream)
948 GstRTSPMediaTrans *trans;
950 GST_INFO ("%p: new source %p", stream, source);
952 /* see if we have a stream to match with the origin of the RTCP packet */
953 trans = g_object_get_qdata (source, ssrc_stream_map_key);
955 g_object_get (source, "stats", &stats, NULL);
957 const gchar *rtcp_from;
959 dump_structure (stats);
961 rtcp_from = gst_structure_get_string (stats, "rtcp-from");
962 if ((trans = find_transport (stream, rtcp_from))) {
963 GST_INFO ("%p: found transport %p for source %p", stream, trans,
966 /* keep ref to the source */
967 trans->rtpsource = source;
969 g_object_set_qdata (source, ssrc_stream_map_key, trans);
971 gst_structure_free (stats);
974 GST_INFO ("%p: source %p for transport %p", stream, source, trans);
979 on_ssrc_sdes (GObject * session, GObject * source, GstRTSPMediaStream * stream)
981 GST_INFO ("%p: new SDES %p", stream, source);
985 on_ssrc_active (GObject * session, GObject * source,
986 GstRTSPMediaStream * stream)
988 GstRTSPMediaTrans *trans;
990 trans = g_object_get_qdata (source, ssrc_stream_map_key);
992 GST_INFO ("%p: source %p in transport %p is active", stream, source, trans);
994 if (trans && trans->keep_alive)
995 trans->keep_alive (trans->ka_user_data);
1000 g_object_get (source, "stats", &stats, NULL);
1002 dump_structure (stats);
1003 gst_structure_free (stats);
1010 on_bye_ssrc (GObject * session, GObject * source, GstRTSPMediaStream * stream)
1012 GST_INFO ("%p: source %p bye", stream, source);
1016 on_bye_timeout (GObject * session, GObject * source,
1017 GstRTSPMediaStream * stream)
1019 GstRTSPMediaTrans *trans;
1021 GST_INFO ("%p: source %p bye timeout", stream, source);
1023 if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) {
1024 trans->rtpsource = NULL;
1025 trans->timeout = TRUE;
1030 on_timeout (GObject * session, GObject * source, GstRTSPMediaStream * stream)
1032 GstRTSPMediaTrans *trans;
1034 GST_INFO ("%p: source %p timeout", stream, source);
1036 if ((trans = g_object_get_qdata (source, ssrc_stream_map_key))) {
1037 trans->rtpsource = NULL;
1038 trans->timeout = TRUE;
1042 static GstFlowReturn
1043 handle_new_buffer (GstAppSink * sink, gpointer user_data)
1047 GstRTSPMediaStream *stream;
1049 buffer = gst_app_sink_pull_buffer (sink);
1053 stream = (GstRTSPMediaStream *) user_data;
1055 for (walk = stream->transports; walk; walk = g_list_next (walk)) {
1056 GstRTSPMediaTrans *tr = (GstRTSPMediaTrans *) walk->data;
1058 if (GST_ELEMENT_CAST (sink) == stream->appsink[0]) {
1060 tr->send_rtp (buffer, tr->transport->interleaved.min, tr->user_data);
1063 tr->send_rtcp (buffer, tr->transport->interleaved.max, tr->user_data);
1066 gst_buffer_unref (buffer);
1071 static GstAppSinkCallbacks sink_cb = {
1072 NULL, /* not interested in EOS */
1073 NULL, /* not interested in preroll buffers */
1077 /* prepare the pipeline objects to handle @stream in @media */
1079 setup_stream (GstRTSPMediaStream * stream, guint idx, GstRTSPMedia * media)
1082 GstPad *pad, *teepad, *selpad;
1083 GstPadLinkReturn ret;
1086 /* allocate udp ports, we will have 4 of them, 2 for receiving RTP/RTCP and 2
1087 * for sending RTP/RTCP. The sender and receiver ports are shared between the
1089 if (!alloc_udp_ports (media, stream))
1092 /* add the ports to the pipeline */
1093 for (i = 0; i < 2; i++) {
1094 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->udpsink[i]);
1095 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->udpsrc[i]);
1098 /* create elements for the TCP transfer */
1099 for (i = 0; i < 2; i++) {
1100 stream->appsrc[i] = gst_element_factory_make ("appsrc", NULL);
1101 stream->appsink[i] = gst_element_factory_make ("appsink", NULL);
1102 g_object_set (stream->appsink[i], "async", FALSE, "sync", FALSE, NULL);
1103 g_object_set (stream->appsink[i], "emit-signals", FALSE, NULL);
1104 g_object_set (stream->appsink[i], "preroll-queue-len", 1, NULL);
1105 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->appsink[i]);
1106 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->appsrc[i]);
1107 gst_app_sink_set_callbacks (GST_APP_SINK_CAST (stream->appsink[i]),
1108 &sink_cb, stream, NULL);
1111 /* hook up the stream to the RTP session elements. */
1112 name = g_strdup_printf ("send_rtp_sink_%d", idx);
1113 stream->send_rtp_sink = gst_element_get_request_pad (media->rtpbin, name);
1115 name = g_strdup_printf ("send_rtp_src_%d", idx);
1116 stream->send_rtp_src = gst_element_get_static_pad (media->rtpbin, name);
1118 name = g_strdup_printf ("send_rtcp_src_%d", idx);
1119 stream->send_rtcp_src = gst_element_get_request_pad (media->rtpbin, name);
1121 name = g_strdup_printf ("recv_rtcp_sink_%d", idx);
1122 stream->recv_rtcp_sink = gst_element_get_request_pad (media->rtpbin, name);
1124 name = g_strdup_printf ("recv_rtp_sink_%d", idx);
1125 stream->recv_rtp_sink = gst_element_get_request_pad (media->rtpbin, name);
1128 /* get the session */
1129 g_signal_emit_by_name (media->rtpbin, "get-internal-session", idx,
1132 g_signal_connect (stream->session, "on-new-ssrc", (GCallback) on_new_ssrc,
1134 g_signal_connect (stream->session, "on-ssrc-sdes", (GCallback) on_ssrc_sdes,
1136 g_signal_connect (stream->session, "on-ssrc-active",
1137 (GCallback) on_ssrc_active, stream);
1138 g_signal_connect (stream->session, "on-bye-ssrc", (GCallback) on_bye_ssrc,
1140 g_signal_connect (stream->session, "on-bye-timeout",
1141 (GCallback) on_bye_timeout, stream);
1142 g_signal_connect (stream->session, "on-timeout", (GCallback) on_timeout,
1145 /* link the RTP pad to the session manager */
1146 ret = gst_pad_link (stream->srcpad, stream->send_rtp_sink);
1147 if (ret != GST_PAD_LINK_OK)
1150 /* make tee for RTP and link to stream */
1151 stream->tee[0] = gst_element_factory_make ("tee", NULL);
1152 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->tee[0]);
1154 pad = gst_element_get_static_pad (stream->tee[0], "sink");
1155 gst_pad_link (stream->send_rtp_src, pad);
1156 gst_object_unref (pad);
1158 /* link RTP sink, we're pretty sure this will work. */
1159 teepad = gst_element_get_request_pad (stream->tee[0], "src%d");
1160 pad = gst_element_get_static_pad (stream->udpsink[0], "sink");
1161 gst_pad_link (teepad, pad);
1162 gst_object_unref (pad);
1163 gst_object_unref (teepad);
1165 teepad = gst_element_get_request_pad (stream->tee[0], "src%d");
1166 pad = gst_element_get_static_pad (stream->appsink[0], "sink");
1167 gst_pad_link (teepad, pad);
1168 gst_object_unref (pad);
1169 gst_object_unref (teepad);
1171 /* make tee for RTCP */
1172 stream->tee[1] = gst_element_factory_make ("tee", NULL);
1173 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->tee[1]);
1175 pad = gst_element_get_static_pad (stream->tee[1], "sink");
1176 gst_pad_link (stream->send_rtcp_src, pad);
1177 gst_object_unref (pad);
1179 /* link RTCP elements */
1180 teepad = gst_element_get_request_pad (stream->tee[1], "src%d");
1181 pad = gst_element_get_static_pad (stream->udpsink[1], "sink");
1182 gst_pad_link (teepad, pad);
1183 gst_object_unref (pad);
1184 gst_object_unref (teepad);
1186 teepad = gst_element_get_request_pad (stream->tee[1], "src%d");
1187 pad = gst_element_get_static_pad (stream->appsink[1], "sink");
1188 gst_pad_link (teepad, pad);
1189 gst_object_unref (pad);
1190 gst_object_unref (teepad);
1192 /* make selector for the RTP receivers */
1193 stream->selector[0] = gst_element_factory_make ("input-selector", NULL);
1194 g_object_set (stream->selector[0], "select-all", TRUE, NULL);
1195 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->selector[0]);
1197 pad = gst_element_get_static_pad (stream->selector[0], "src");
1198 gst_pad_link (pad, stream->recv_rtp_sink);
1199 gst_object_unref (pad);
1201 selpad = gst_element_get_request_pad (stream->selector[0], "sink%d");
1202 pad = gst_element_get_static_pad (stream->udpsrc[0], "src");
1203 gst_pad_link (pad, selpad);
1204 gst_object_unref (pad);
1205 gst_object_unref (selpad);
1207 selpad = gst_element_get_request_pad (stream->selector[0], "sink%d");
1208 pad = gst_element_get_static_pad (stream->appsrc[0], "src");
1209 gst_pad_link (pad, selpad);
1210 gst_object_unref (pad);
1211 gst_object_unref (selpad);
1213 /* make selector for the RTCP receivers */
1214 stream->selector[1] = gst_element_factory_make ("input-selector", NULL);
1215 g_object_set (stream->selector[1], "select-all", TRUE, NULL);
1216 gst_bin_add (GST_BIN_CAST (media->pipeline), stream->selector[1]);
1218 pad = gst_element_get_static_pad (stream->selector[1], "src");
1219 gst_pad_link (pad, stream->recv_rtcp_sink);
1220 gst_object_unref (pad);
1222 selpad = gst_element_get_request_pad (stream->selector[1], "sink%d");
1223 pad = gst_element_get_static_pad (stream->udpsrc[1], "src");
1224 gst_pad_link (pad, selpad);
1225 gst_object_unref (pad);
1226 gst_object_unref (selpad);
1228 selpad = gst_element_get_request_pad (stream->selector[1], "sink%d");
1229 pad = gst_element_get_static_pad (stream->appsrc[1], "src");
1230 gst_pad_link (pad, selpad);
1231 gst_object_unref (pad);
1232 gst_object_unref (selpad);
1234 /* we set and keep these to playing so that they don't cause NO_PREROLL return
1236 gst_element_set_state (stream->udpsrc[0], GST_STATE_PLAYING);
1237 gst_element_set_state (stream->udpsrc[1], GST_STATE_PLAYING);
1238 gst_element_set_locked_state (stream->udpsrc[0], TRUE);
1239 gst_element_set_locked_state (stream->udpsrc[1], TRUE);
1241 /* be notified of caps changes */
1242 stream->caps_sig = g_signal_connect (stream->send_rtp_sink, "notify::caps",
1243 (GCallback) caps_notify, stream);
1245 stream->prepared = TRUE;
1252 GST_WARNING ("failed to link stream %d", idx);
1258 unlock_streams (GstRTSPMedia * media)
1262 /* unlock the udp src elements */
1263 n_streams = gst_rtsp_media_n_streams (media);
1264 for (i = 0; i < n_streams; i++) {
1265 GstRTSPMediaStream *stream;
1267 stream = gst_rtsp_media_get_stream (media, i);
1269 gst_element_set_locked_state (stream->udpsrc[0], FALSE);
1270 gst_element_set_locked_state (stream->udpsrc[1], FALSE);
1275 gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
1277 g_mutex_lock (media->lock);
1278 /* never overwrite the error status */
1279 if (media->status != GST_RTSP_MEDIA_STATUS_ERROR)
1280 media->status = status;
1281 GST_DEBUG ("setting new status to %d", status);
1282 g_cond_broadcast (media->cond);
1283 g_mutex_unlock (media->lock);
1286 static GstRTSPMediaStatus
1287 gst_rtsp_media_get_status (GstRTSPMedia * media)
1289 GstRTSPMediaStatus result;
1292 g_mutex_lock (media->lock);
1293 g_get_current_time (&timeout);
1294 g_time_val_add (&timeout, 20 * G_USEC_PER_SEC);
1295 /* while we are preparing, wait */
1296 while (media->status == GST_RTSP_MEDIA_STATUS_PREPARING) {
1297 GST_DEBUG ("waiting for status change");
1298 if (!g_cond_timed_wait (media->cond, media->lock, &timeout)) {
1299 GST_DEBUG ("timeout, assuming error status");
1300 media->status = GST_RTSP_MEDIA_STATUS_ERROR;
1303 /* could be success or error */
1304 result = media->status;
1305 GST_DEBUG ("got status %d", result);
1306 g_mutex_unlock (media->lock);
1312 default_handle_message (GstRTSPMedia * media, GstMessage * message)
1314 GstMessageType type;
1316 type = GST_MESSAGE_TYPE (message);
1319 case GST_MESSAGE_STATE_CHANGED:
1321 case GST_MESSAGE_BUFFERING:
1325 gst_message_parse_buffering (message, &percent);
1327 /* no state management needed for live pipelines */
1331 if (percent == 100) {
1332 /* a 100% message means buffering is done */
1333 media->buffering = FALSE;
1334 /* if the desired state is playing, go back */
1335 if (media->target_state == GST_STATE_PLAYING) {
1336 GST_INFO ("Buffering done, setting pipeline to PLAYING");
1337 gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1339 GST_INFO ("Buffering done");
1342 /* buffering busy */
1343 if (media->buffering == FALSE) {
1344 if (media->target_state == GST_STATE_PLAYING) {
1345 /* we were not buffering but PLAYING, PAUSE the pipeline. */
1346 GST_INFO ("Buffering, setting pipeline to PAUSED ...");
1347 gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
1349 GST_INFO ("Buffering ...");
1352 media->buffering = TRUE;
1356 case GST_MESSAGE_LATENCY:
1358 gst_bin_recalculate_latency (GST_BIN_CAST (media->pipeline));
1361 case GST_MESSAGE_ERROR:
1366 gst_message_parse_error (message, &gerror, &debug);
1367 GST_WARNING ("%p: got error %s (%s)", media, gerror->message, debug);
1368 g_error_free (gerror);
1371 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
1374 case GST_MESSAGE_WARNING:
1379 gst_message_parse_warning (message, &gerror, &debug);
1380 GST_WARNING ("%p: got warning %s (%s)", media, gerror->message, debug);
1381 g_error_free (gerror);
1385 case GST_MESSAGE_ELEMENT:
1387 case GST_MESSAGE_STREAM_STATUS:
1389 case GST_MESSAGE_ASYNC_DONE:
1390 GST_INFO ("%p: got ASYNC_DONE", media);
1391 collect_media_stats (media);
1393 gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
1395 case GST_MESSAGE_EOS:
1396 GST_INFO ("%p: got EOS", media);
1397 if (media->eos_pending) {
1398 GST_DEBUG ("shutting down after EOS");
1399 gst_element_set_state (media->pipeline, GST_STATE_NULL);
1400 media->eos_pending = FALSE;
1401 g_object_unref (media);
1405 GST_INFO ("%p: got message type %s", media,
1406 gst_message_type_get_name (type));
1413 bus_message (GstBus * bus, GstMessage * message, GstRTSPMedia * media)
1415 GstRTSPMediaClass *klass;
1418 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1420 if (klass->handle_message)
1421 ret = klass->handle_message (media, message);
1428 /* called from streaming threads */
1430 pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media)
1432 GstRTSPMediaStream *stream;
1436 i = media->streams->len + 1;
1438 GST_INFO ("pad added %s:%s, stream %d", GST_DEBUG_PAD_NAME (pad), i);
1440 stream = g_new0 (GstRTSPMediaStream, 1);
1441 stream->payloader = element;
1443 name = g_strdup_printf ("dynpay%d", i);
1445 /* ghost the pad of the payloader to the element */
1446 stream->srcpad = gst_ghost_pad_new (name, pad);
1447 gst_pad_set_active (stream->srcpad, TRUE);
1448 gst_element_add_pad (media->element, stream->srcpad);
1451 /* add stream now */
1452 g_array_append_val (media->streams, stream);
1454 setup_stream (stream, i, media);
1456 for (i = 0; i < 2; i++) {
1457 gst_element_set_state (stream->udpsink[i], GST_STATE_PAUSED);
1458 gst_element_set_state (stream->appsink[i], GST_STATE_PAUSED);
1459 gst_element_set_state (stream->tee[i], GST_STATE_PAUSED);
1460 gst_element_set_state (stream->selector[i], GST_STATE_PAUSED);
1461 gst_element_set_state (stream->appsrc[i], GST_STATE_PAUSED);
1466 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
1468 GST_INFO ("no more pads");
1469 if (media->fakesink) {
1470 gst_object_ref (media->fakesink);
1471 gst_bin_remove (GST_BIN (media->pipeline), media->fakesink);
1472 gst_element_set_state (media->fakesink, GST_STATE_NULL);
1473 gst_object_unref (media->fakesink);
1474 media->fakesink = NULL;
1475 GST_INFO ("removed fakesink");
1480 * gst_rtsp_media_prepare:
1481 * @media: a #GstRTSPMedia
1483 * Prepare @media for streaming. This function will create the pipeline and
1484 * other objects to manage the streaming.
1486 * It will preroll the pipeline and collect vital information about the streams
1487 * such as the duration.
1489 * Returns: %TRUE on success.
1492 gst_rtsp_media_prepare (GstRTSPMedia * media)
1494 GstStateChangeReturn ret;
1495 GstRTSPMediaStatus status;
1497 GstRTSPMediaClass *klass;
1501 if (media->status == GST_RTSP_MEDIA_STATUS_PREPARED)
1504 if (!media->reusable && media->reused)
1507 GST_INFO ("preparing media %p", media);
1509 /* reset some variables */
1510 media->is_live = FALSE;
1511 media->buffering = FALSE;
1512 /* we're preparing now */
1513 media->status = GST_RTSP_MEDIA_STATUS_PREPARING;
1515 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (media->pipeline));
1517 /* add the pipeline bus to our custom mainloop */
1518 media->source = gst_bus_create_watch (bus);
1519 gst_object_unref (bus);
1521 g_source_set_callback (media->source, (GSourceFunc) bus_message, media, NULL);
1523 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1524 media->id = g_source_attach (media->source, klass->context);
1526 media->rtpbin = gst_element_factory_make ("gstrtpbin", NULL);
1528 /* add stuff to the bin */
1529 gst_bin_add (GST_BIN (media->pipeline), media->rtpbin);
1531 /* link streams we already have, other streams might appear when we have
1532 * dynamic elements */
1533 n_streams = gst_rtsp_media_n_streams (media);
1534 for (i = 0; i < n_streams; i++) {
1535 GstRTSPMediaStream *stream;
1537 stream = gst_rtsp_media_get_stream (media, i);
1539 setup_stream (stream, i, media);
1542 for (walk = media->dynamic; walk; walk = g_list_next (walk)) {
1543 GstElement *elem = walk->data;
1545 g_signal_connect (elem, "pad-added", (GCallback) pad_added_cb, media);
1546 g_signal_connect (elem, "no-more-pads", (GCallback) no_more_pads_cb, media);
1548 /* we add a fakesink here in order to make the state change async. We remove
1549 * the fakesink again in the no-more-pads callback. */
1550 media->fakesink = gst_element_factory_make ("fakesink", "fakesink");
1551 gst_bin_add (GST_BIN (media->pipeline), media->fakesink);
1554 GST_INFO ("setting pipeline to PAUSED for media %p", media);
1555 /* first go to PAUSED */
1556 ret = gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
1557 media->target_state = GST_STATE_PAUSED;
1560 case GST_STATE_CHANGE_SUCCESS:
1561 GST_INFO ("SUCCESS state change for media %p", media);
1563 case GST_STATE_CHANGE_ASYNC:
1564 GST_INFO ("ASYNC state change for media %p", media);
1566 case GST_STATE_CHANGE_NO_PREROLL:
1567 /* we need to go to PLAYING */
1568 GST_INFO ("NO_PREROLL state change: live media %p", media);
1569 media->is_live = TRUE;
1570 ret = gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1571 if (ret == GST_STATE_CHANGE_FAILURE)
1574 case GST_STATE_CHANGE_FAILURE:
1578 /* now wait for all pads to be prerolled */
1579 status = gst_rtsp_media_get_status (media);
1580 if (status == GST_RTSP_MEDIA_STATUS_ERROR)
1583 GST_INFO ("object %p is prerolled", media);
1595 GST_WARNING ("can not reuse media %p", media);
1600 GST_WARNING ("failed to preroll pipeline");
1601 unlock_streams (media);
1602 gst_element_set_state (media->pipeline, GST_STATE_NULL);
1603 gst_rtsp_media_unprepare (media);
1609 * gst_rtsp_media_unprepare:
1610 * @media: a #GstRTSPMedia
1612 * Unprepare @media. After this call, the media should be prepared again before
1613 * it can be used again. If the media is set to be non-reusable, a new instance
1616 * Returns: %TRUE on success.
1619 gst_rtsp_media_unprepare (GstRTSPMedia * media)
1621 GstRTSPMediaClass *klass;
1624 if (media->status == GST_RTSP_MEDIA_STATUS_UNPREPARED)
1627 GST_INFO ("unprepare media %p", media);
1628 media->target_state = GST_STATE_NULL;
1630 klass = GST_RTSP_MEDIA_GET_CLASS (media);
1631 if (klass->unprepare)
1632 success = klass->unprepare (media);
1636 media->status = GST_RTSP_MEDIA_STATUS_UNPREPARED;
1637 media->reused = TRUE;
1639 /* when the media is not reusable, this will effectively unref the media and
1641 g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARED], 0, NULL);
1647 default_unprepare (GstRTSPMedia * media)
1649 if (media->eos_shutdown) {
1650 GST_DEBUG ("sending EOS for shutdown");
1651 /* ref so that we don't disappear */
1652 g_object_ref (media);
1653 media->eos_pending = TRUE;
1654 gst_element_send_event (media->pipeline, gst_event_new_eos ());
1655 /* we need to go to playing again for the EOS to propagate, normally in this
1656 * state, nothing is receiving data from us anymore so this is ok. */
1657 gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
1659 GST_DEBUG ("shutting down");
1660 gst_element_set_state (media->pipeline, GST_STATE_NULL);
1666 add_udp_destination (GstRTSPMedia * media, GstRTSPMediaStream * stream,
1667 gchar * dest, gint min, gint max)
1669 gboolean do_add = TRUE;
1670 RTSPDestination *ndest;
1672 if (stream->filter_duplicates) {
1673 RTSPDestination fdest;
1680 /* first see if we already added this destination */
1682 g_list_find_custom (stream->destinations, &fdest,
1683 (GCompareFunc) dest_compare);
1685 ndest = (RTSPDestination *) find->data;
1687 GST_INFO ("already streaming to %s:%d-%d with %d clients", dest, min, max,
1695 GST_INFO ("adding %s:%d-%d", dest, min, max);
1696 g_signal_emit_by_name (stream->udpsink[0], "add", dest, min, NULL);
1697 g_signal_emit_by_name (stream->udpsink[1], "add", dest, max, NULL);
1699 if (stream->filter_duplicates) {
1700 ndest = create_destination (dest, min, max);
1701 stream->destinations = g_list_prepend (stream->destinations, ndest);
1707 remove_udp_destination (GstRTSPMedia * media, GstRTSPMediaStream * stream,
1708 gchar * dest, gint min, gint max)
1710 gboolean do_remove = TRUE;
1711 RTSPDestination *ndest = NULL;
1714 if (stream->filter_duplicates) {
1715 RTSPDestination fdest;
1721 /* first see if we already added this destination */
1723 g_list_find_custom (stream->destinations, &fdest,
1724 (GCompareFunc) dest_compare);
1728 ndest = (RTSPDestination *) find->data;
1729 if (--ndest->count > 0) {
1731 GST_INFO ("still streaming to %s:%d-%d with %d clients", dest, min, max,
1737 GST_INFO ("removing %s:%d-%d", dest, min, max);
1738 g_signal_emit_by_name (stream->udpsink[0], "remove", dest, min, NULL);
1739 g_signal_emit_by_name (stream->udpsink[1], "remove", dest, max, NULL);
1741 if (stream->filter_duplicates) {
1742 stream->destinations = g_list_delete_link (stream->destinations, find);
1743 free_destination (ndest);
1749 * gst_rtsp_media_set_state:
1750 * @media: a #GstRTSPMedia
1751 * @state: the target state of the media
1752 * @transports: a #GArray of #GstRTSPMediaTrans pointers
1754 * Set the state of @media to @state and for the transports in @transports.
1756 * Returns: %TRUE on success.
1759 gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state,
1760 GArray * transports)
1763 GstStateChangeReturn ret;
1764 gboolean add, remove, do_state;
1767 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
1768 g_return_val_if_fail (transports != NULL, FALSE);
1770 /* NULL and READY are the same */
1771 if (state == GST_STATE_READY)
1772 state = GST_STATE_NULL;
1774 add = remove = FALSE;
1776 GST_INFO ("going to state %s media %p", gst_element_state_get_name (state),
1780 case GST_STATE_NULL:
1781 /* unlock the streams so that they follow the state changes from now on */
1782 unlock_streams (media);
1784 case GST_STATE_PAUSED:
1785 /* we're going from PLAYING to PAUSED, READY or NULL, remove */
1786 if (media->target_state == GST_STATE_PLAYING)
1789 case GST_STATE_PLAYING:
1790 /* we're going to PLAYING, add */
1796 old_active = media->active;
1798 for (i = 0; i < transports->len; i++) {
1799 GstRTSPMediaTrans *tr;
1800 GstRTSPMediaStream *stream;
1801 GstRTSPTransport *trans;
1803 /* we need a non-NULL entry in the array */
1804 tr = g_array_index (transports, GstRTSPMediaTrans *, i);
1808 /* we need a transport */
1809 if (!(trans = tr->transport))
1812 /* get the stream and add the destinations */
1813 stream = gst_rtsp_media_get_stream (media, tr->idx);
1814 switch (trans->lower_transport) {
1815 case GST_RTSP_LOWER_TRANS_UDP:
1816 case GST_RTSP_LOWER_TRANS_UDP_MCAST:
1821 dest = trans->destination;
1822 if (trans->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
1823 min = trans->port.min;
1824 max = trans->port.max;
1826 min = trans->client_port.min;
1827 max = trans->client_port.max;
1830 if (add && !tr->active) {
1831 add_udp_destination (media, stream, dest, min, max);
1832 stream->transports = g_list_prepend (stream->transports, tr);
1835 } else if (remove && tr->active) {
1836 remove_udp_destination (media, stream, dest, min, max);
1837 stream->transports = g_list_remove (stream->transports, tr);
1843 case GST_RTSP_LOWER_TRANS_TCP:
1844 if (add && !tr->active) {
1845 GST_INFO ("adding TCP %s", trans->destination);
1846 stream->transports = g_list_prepend (stream->transports, tr);
1849 } else if (remove && tr->active) {
1850 GST_INFO ("removing TCP %s", trans->destination);
1851 stream->transports = g_list_remove (stream->transports, tr);
1857 GST_INFO ("Unknown transport %d", trans->lower_transport);
1862 /* we just added the first media, do the playing state change */
1863 if (old_active == 0 && add)
1865 /* if we have no more active media, do the downward state changes */
1866 else if (media->active == 0)
1871 GST_INFO ("active %d media %p", media->active, media);
1873 if (do_state && media->target_state != state) {
1874 if (state == GST_STATE_NULL) {
1875 gst_rtsp_media_unprepare (media);
1877 GST_INFO ("state %s media %p", gst_element_state_get_name (state), media);
1878 media->target_state = state;
1879 ret = gst_element_set_state (media->pipeline, state);
1883 /* remember where we are */
1884 if (state == GST_STATE_PAUSED)
1885 collect_media_stats (media);
1891 * gst_rtsp_media_remove_elements:
1892 * @media: a #GstRTSPMedia
1894 * Remove all elements and the pipeline controlled by @media.
1897 gst_rtsp_media_remove_elements (GstRTSPMedia * media)
1901 unlock_streams (media);
1903 for (i = 0; i < media->streams->len; i++) {
1904 GstRTSPMediaStream *stream;
1906 GST_INFO ("Removing elements of stream %d from pipeline", i);
1908 stream = g_array_index (media->streams, GstRTSPMediaStream *, i);
1910 gst_pad_unlink (stream->srcpad, stream->send_rtp_sink);
1912 g_signal_handler_disconnect (stream->send_rtp_sink, stream->caps_sig);
1914 for (j = 0; j < 2; j++) {
1915 gst_element_set_state (stream->udpsrc[j], GST_STATE_NULL);
1916 gst_element_set_state (stream->udpsink[j], GST_STATE_NULL);
1917 gst_element_set_state (stream->appsrc[j], GST_STATE_NULL);
1918 gst_element_set_state (stream->appsink[j], GST_STATE_NULL);
1919 gst_element_set_state (stream->tee[j], GST_STATE_NULL);
1920 gst_element_set_state (stream->selector[j], GST_STATE_NULL);
1922 gst_bin_remove (GST_BIN (media->pipeline), stream->udpsrc[j]);
1923 gst_bin_remove (GST_BIN (media->pipeline), stream->udpsink[j]);
1924 gst_bin_remove (GST_BIN (media->pipeline), stream->appsrc[j]);
1925 gst_bin_remove (GST_BIN (media->pipeline), stream->appsink[j]);
1926 gst_bin_remove (GST_BIN (media->pipeline), stream->tee[j]);
1927 gst_bin_remove (GST_BIN (media->pipeline), stream->selector[j]);
1930 gst_caps_unref (stream->caps);
1931 stream->caps = NULL;
1932 gst_rtsp_media_stream_free (stream);
1934 g_array_remove_range (media->streams, 0, media->streams->len);
1936 gst_element_set_state (media->rtpbin, GST_STATE_NULL);
1937 gst_bin_remove (GST_BIN (media->pipeline), media->rtpbin);
1939 gst_object_unref (media->pipeline);
1940 media->pipeline = NULL;