4 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * Alternatively, the contents of this file may be used under the
27 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
28 * which case the following provisions apply instead of the ones
31 * This library is free software; you can redistribute it and/or
32 * modify it under the terms of the GNU Library General Public
33 * License as published by the Free Software Foundation; either
34 * version 2 of the License, or (at your option) any later version.
36 * This library is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 * Library General Public License for more details.
41 * You should have received a copy of the GNU Library General Public
42 * License along with this library; if not, write to the
43 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
44 * Boston, MA 02111-1307, USA.
48 * SECTION:element-wfdtizensrc
50 * Makes a connection to an RTSP server and read the data.
51 * Device recognition is through wifi direct.
52 * wfdtizensrc strictly follows Wifi display specification.
54 * RTSP supports transport over TCP or UDP in unicast or multicast mode. By
55 * default wfdtizensrc will negotiate a connection in the following order:
56 * UDP unicast/UDP multicast/TCP. The order cannot be changed but the allowed
57 * protocols can be controlled with the #GstWFDTizenSrc:protocols property.
59 * wfdtizensrc currently understands WFD capability negotiation messages
61 * wfdtizensrc will internally instantiate an RTP session manager element
62 * that will handle the RTCP messages to and from the server, jitter removal,
63 * packet reordering along with providing a clock for the pipeline.
64 * This feature is implemented using the gstrtpbin element.
66 * wfdtizensrc acts like a live source and will therefore only generate data in the
70 * <title>Example launch line</title>
72 * gst-launch wfdtizensrc location=rtsp://some.server/url ! fakesink
73 * ]| Establish a connection to an RTSP server and send the raw RTP packets to a
82 #include <sys/ioctl.h>
84 #include <sys/socket.h>
86 #include <netinet/in.h>
88 #include "gstwfdtizensrc.h"
90 GST_DEBUG_CATEGORY_STATIC (wfdtizensrc_debug);
91 #define GST_CAT_DEFAULT (wfdtizensrc_debug)
93 /* signals and args */
104 PROP_UDP_BUFFER_SIZE,
111 PROP_FEC_SYMBOL_LENGTH,
115 #define DEFAULT_DO_RTCP TRUE
116 #define DEFAULT_LATENCY_MS 2000
117 #define DEFAULT_UDP_BUFFER_SIZE 0x80000
118 #define DEFAULT_UDP_TIMEOUT 10000000
119 #define DEFAULT_LATENCY_MODE WFD_TIZEN_LATENCY_NONE
120 #define DEFAULT_DO_REQUEST TRUE
121 #define DEFAULT_DO_FEC TRUE
122 #define DEFAULT_FEC_MAX_K 10
123 #define DEFAULT_FEC_MAX_P 10
124 #define DEFAULT_FEC_SYMBOL_LENGTH 1500
127 static void gst_wfd_tizen_src_set_property (GObject * object, guint prop_id,
128 const GValue * value, GParamSpec * pspec);
129 static void gst_wfd_tizen_src_get_property (GObject * object, guint prop_id,
130 GValue * value, GParamSpec * pspec);
133 static GstRTSPResult gst_wfd_tizen_src_handle_set_parameter (GstWFDBaseSrc *
134 bsrc, GstRTSPMessage * request, GstRTSPMessage * response);
135 static GstRTSPResult gst_wfd_tizen_src_handle_get_parameter (GstWFDBaseSrc *
136 bsrc, GstRTSPMessage * request, GstRTSPMessage * response);
137 static GstRTSPResult gst_wfd_tizen_src_configure_transport (GstWFDBaseSrc *
138 bsrc, GstRTSPTransport * transport);
139 static GstRTSPResult gst_wfd_tizen_src_prepare_transport (GstWFDBaseSrc * bsrc,
140 gint rtpport, gint rtcpport);
141 static gboolean gst_wfd_tizen_src_push_event (GstWFDBaseSrc * bsrc,
143 static void gst_wfd_tizen_src_set_state (GstWFDBaseSrc * src, GstState state);
144 static void gst_wfd_tizen_src_cleanup (GstWFDBaseSrc * bsrc);
146 //static guint gst_wfd_ext_srcext_signals[LAST_SIGNAL] = { 0 };
149 wfd_tizen_latency_mode_get_type (void)
151 static GType wfd_tizen_latency_mode_type = 0;
152 static const GEnumValue tizen_latency_modes[] = {
153 {WFD_TIZEN_LATENCY_NONE, "none", "none"},
154 {WFD_TIZEN_LATENCY_LOW, "Low latency mode", "low"},
155 {WFD_TIZEN_LATENCY_MID, "Mid latency mode", "mid"},
156 {WFD_TIZEN_LATENCY_HIGH, "High latency mode", "high"},
160 if (!wfd_tizen_latency_mode_type) {
161 wfd_tizen_latency_mode_type =
162 g_enum_register_static ("WFDTizenLatencyMode", tizen_latency_modes);
164 return wfd_tizen_latency_mode_type;
168 GST_DEBUG_CATEGORY_INIT (wfdtizensrc_debug, "wfdtizensrc", 0, "Wi-Fi Display Sink Tizen source");
170 #define gst_wfd_tizen_src_parent_class parent_class
171 G_DEFINE_TYPE_WITH_CODE (GstWFDTizenSrc, gst_wfd_tizen_src,
172 GST_TYPE_WFD_BASE_SRC, _do_init);
175 gst_wfd_tizen_src_class_init (GstWFDTizenSrcClass * klass)
177 GObjectClass *gobject_class;
178 GstElementClass *gstelement_class;
179 GstWFDBaseSrcClass *gstwfdbasesrc_class;
181 gobject_class = (GObjectClass *) klass;
182 gstelement_class = (GstElementClass *) klass;
183 gstwfdbasesrc_class = (GstWFDBaseSrcClass *) klass;
185 gobject_class->set_property = gst_wfd_tizen_src_set_property;
186 gobject_class->get_property = gst_wfd_tizen_src_get_property;
188 g_object_class_install_property (gobject_class, PROP_DO_RTCP,
189 g_param_spec_boolean ("do-rtcp", "Do RTCP",
190 "Send RTCP packets, disable for old incompatible server.",
191 DEFAULT_DO_RTCP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193 g_object_class_install_property (gobject_class, PROP_LATENCY,
194 g_param_spec_uint ("latency", "Buffer latency in ms",
195 "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS,
196 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198 g_object_class_install_property (gobject_class, PROP_UDP_BUFFER_SIZE,
199 g_param_spec_int ("udp-buffer-size", "UDP Buffer Size",
200 "Size of the kernel UDP receive buffer in bytes, 0=default",
201 0, G_MAXINT, DEFAULT_UDP_BUFFER_SIZE,
202 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
204 g_object_class_install_property (gobject_class, PROP_UDP_TIMEOUT,
205 g_param_spec_uint64 ("timeout", "Timeout",
206 "Fail after timeout microseconds on UDP connections (0 = disabled)",
207 0, G_MAXUINT64, DEFAULT_UDP_TIMEOUT,
208 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
210 g_object_class_install_property (gobject_class, PROP_LATENCY_MODE,
211 g_param_spec_enum ("latency-mode", "Latency Mode",
212 "Current latency mode", WFD_TIZEN_LATENCY_MODE,
213 DEFAULT_LATENCY_MODE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
215 g_object_class_install_property (gobject_class, PROP_DO_REQUEST,
216 g_param_spec_boolean ("do-request", "Enable RTP Retransmission Request",
217 "Send RTCP FB packets and handel retransmitted RTP packets.",
218 DEFAULT_DO_REQUEST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
220 g_object_class_install_property (gobject_class, PROP_DO_FEC,
221 g_param_spec_boolean ("do-fec", "Enable Forward Error Correction",
222 "Enabel Forward Error Correction decoding",
223 DEFAULT_DO_FEC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
225 g_object_class_install_property (gobject_class, PROP_FEC_MAX_K,
226 g_param_spec_uint ("fec-max-k",
227 "Max. size (k) for Forward Error Correction",
228 "Max. number of source symbol in a block", 1, G_MAXUINT,
229 DEFAULT_FEC_MAX_K, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
231 g_object_class_install_property (gobject_class, PROP_FEC_MAX_P,
232 g_param_spec_uint ("fec-max-p",
233 "Max. size (p) for Forward Error Correction",
234 "Max. number of parity symbol in a block", 0, G_MAXUINT,
235 DEFAULT_FEC_MAX_P, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
237 g_object_class_install_property (gobject_class, PROP_FEC_SYMBOL_LENGTH,
238 g_param_spec_uint ("fec-symbol-length",
239 "Symbol length for Forward Error Correction",
240 "Length of block symbol in bytes", 0, G_MAXUINT,
241 DEFAULT_FEC_SYMBOL_LENGTH,
242 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
244 gst_element_class_set_static_metadata (gstelement_class,
245 "Wi-Fi Display Sink source element", "Source/Network",
246 "Negotiate the capability and receive the RTP packets from the Wi-Fi Display source",
247 "YeJin Cho <cho.yejin@samsung.com>");
249 gstwfdbasesrc_class->handle_set_parameter =
250 GST_DEBUG_FUNCPTR (gst_wfd_tizen_src_handle_set_parameter);
251 gstwfdbasesrc_class->handle_get_parameter =
252 GST_DEBUG_FUNCPTR (gst_wfd_tizen_src_handle_get_parameter);
253 gstwfdbasesrc_class->configure_transport =
254 GST_DEBUG_FUNCPTR (gst_wfd_tizen_src_configure_transport);
255 gstwfdbasesrc_class->prepare_transport =
256 GST_DEBUG_FUNCPTR (gst_wfd_tizen_src_prepare_transport);
257 gstwfdbasesrc_class->push_event =
258 GST_DEBUG_FUNCPTR (gst_wfd_tizen_src_push_event);
259 gstwfdbasesrc_class->set_state =
260 GST_DEBUG_FUNCPTR (gst_wfd_tizen_src_set_state);
261 gstwfdbasesrc_class->cleanup = GST_DEBUG_FUNCPTR (gst_wfd_tizen_src_cleanup);
265 gst_wfd_tizen_src_init (GstWFDTizenSrc * src)
269 src->do_rtcp = DEFAULT_DO_RTCP;
270 src->latency = DEFAULT_LATENCY_MS;
271 src->udp_buffer_size = DEFAULT_UDP_BUFFER_SIZE;
272 src->udp_timeout = DEFAULT_UDP_TIMEOUT;
273 src->latency_mode = DEFAULT_LATENCY_MODE;
274 src->do_request = DEFAULT_DO_REQUEST;
275 src->do_fec = DEFAULT_DO_FEC;
276 src->fec_max_k = DEFAULT_FEC_MAX_K;
277 src->fec_max_p = DEFAULT_FEC_MAX_P;
278 src->fec_symbol_length = DEFAULT_FEC_SYMBOL_LENGTH;
282 src->requester = NULL;
283 src->wfdrtpbuffer = NULL;
284 for (i = 0; i < 3; i++) {
285 src->channelpad[i] = NULL;
286 src->udpsrc[i] = NULL;
287 src->udpsink[i] = NULL;
290 src->blockedpad = NULL;
294 gst_wfd_tizen_src_set_property (GObject * object, guint prop_id,
295 const GValue * value, GParamSpec * pspec)
297 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (object);
301 src->do_rtcp = g_value_get_boolean (value);
304 src->latency = g_value_get_uint (value);
306 case PROP_UDP_BUFFER_SIZE:
307 src->udp_buffer_size = g_value_get_int (value);
309 case PROP_UDP_TIMEOUT:
310 src->udp_timeout = g_value_get_uint64 (value);
312 case PROP_LATENCY_MODE:
313 src->latency_mode = g_value_get_enum (value);
315 case PROP_DO_REQUEST:
316 src->do_request = g_value_get_boolean (value);
319 src->do_fec = g_value_get_boolean (value);
322 src->fec_max_k = g_value_get_uint (value);
325 src->fec_max_p = g_value_get_uint (value);
327 case PROP_FEC_SYMBOL_LENGTH:
328 src->fec_symbol_length = g_value_get_uint (value);
331 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
337 gst_wfd_tizen_src_get_property (GObject * object, guint prop_id, GValue * value,
340 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (object);
344 g_value_set_boolean (value, src->do_rtcp);
347 g_value_set_uint (value, src->latency);
349 case PROP_UDP_BUFFER_SIZE:
350 g_value_set_int (value, src->udp_buffer_size);
352 case PROP_UDP_TIMEOUT:
353 g_value_set_uint64 (value, src->udp_timeout);
355 case PROP_LATENCY_MODE:
356 g_value_set_enum (value, src->latency_mode);
358 case PROP_DO_REQUEST:
359 g_value_set_boolean (value, src->do_request);
362 g_value_set_boolean (value, src->do_fec);
365 g_value_set_uint (value, src->fec_max_k);
368 g_value_set_uint (value, src->fec_max_p);
370 case PROP_FEC_SYMBOL_LENGTH:
371 g_value_set_uint (value, src->fec_symbol_length);
374 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
380 gst_wfd_tizen_src_handle_mode (GstWFDTizenSrc * src, guint mode)
382 GstRTSPResult res = GST_RTSP_OK;
384 GST_DEBUG_OBJECT (src, "latency mode is %d", mode);
386 src->latency_mode = mode;
388 case WFD_TIZEN_LATENCY_LOW:
389 GST_DEBUG_OBJECT (src, "low latency mode");
390 if (src->wfdrtpbuffer)
391 g_object_set (src->wfdrtpbuffer, "latency", src->latency, NULL);
393 g_object_set (src->fecdec, "do-fec", FALSE, NULL);
395 g_object_set (src->requester, "do-request", FALSE, NULL);
397 case WFD_TIZEN_LATENCY_MID:
398 GST_DEBUG_OBJECT (src, "mid latency mode");
399 if (src->wfdrtpbuffer)
400 g_object_set (src->wfdrtpbuffer, "latency", src->latency * 2, NULL);
401 if (src->fecdec && src->do_fec)
402 g_object_set (src->fecdec, "do-fec", TRUE, NULL);
404 g_object_set (src->requester, "do-request", FALSE, NULL);
406 case WFD_TIZEN_LATENCY_HIGH:
407 GST_DEBUG_OBJECT (src, "high latency mode");
408 if (src->wfdrtpbuffer)
409 g_object_set (src->wfdrtpbuffer, "latency", src->latency * 3, NULL);
410 if (src->fecdec && src->do_fec)
411 g_object_set (src->fecdec, "do-fec", TRUE, NULL);
412 if (src->requester && src->do_request)
413 g_object_set (src->requester, "do-request", TRUE, NULL);
423 gst_wfd_tizen_src_handle_set_parameter (GstWFDBaseSrc * bsrc,
424 GstRTSPMessage * request, GstRTSPMessage * response)
426 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (bsrc);
427 GstRTSPResult res = GST_RTSP_OK;
428 GstWFDResult wfd_res = GST_WFD_OK;
429 GstWFDTizenMessage *msg = NULL;
430 GstRTSPMethod method;
431 GstRTSPVersion version;
436 g_return_val_if_fail (request, GST_RTSP_EINVAL);
437 g_return_val_if_fail (response, GST_RTSP_EINVAL);
439 res = gst_rtsp_message_parse_request (request, &method, &uri, &version);
443 if (G_UNLIKELY (method != GST_RTSP_SET_PARAMETER))
446 res = gst_rtsp_message_get_body (request, &data, &size);
450 wfd_res = gst_wfd_tizen_message_new (&msg);
454 wfd_res = gst_wfd_tizen_message_parse_buffer (data, size, msg);
455 if (wfd_res != GST_WFD_OK)
458 if (msg->tizen_retransmission) {
459 guint32 rtp_port = 0, rtcp_port = 0;
462 gst_wfd_tizen_message_get_tizen_retransmission (msg, &rtp_port,
464 if (wfd_res != GST_WFD_OK)
467 GST_DEBUG_OBJECT (src, "tizen_retransmission : RTP port %d, RTCP port %d ",
468 rtp_port, rtcp_port);
471 if (msg->tizen_fec) {
472 guint t_max = 0, p_max = 0;
474 wfd_res = gst_wfd_tizen_message_get_tizen_fec (msg, &t_max, &p_max);
475 if (wfd_res != GST_WFD_OK)
478 src->fec_max_k = t_max;
479 src->fec_max_p = p_max;
481 GST_DEBUG_OBJECT (src, "tizen_fec : t max %d, p max %d ", t_max, p_max);
484 if (msg->tizen_latency_mode) {
485 guint mode = WFD_TIZEN_LATENCY_NONE;
487 wfd_res = gst_wfd_tizen_message_get_tizen_latency_mode (msg, &mode);
488 if (wfd_res != GST_WFD_OK)
491 GST_DEBUG_OBJECT (src, "tizen_latency_mode : %d", mode);
493 res = gst_wfd_tizen_src_handle_mode (src, mode);
494 if (res != GST_RTSP_OK)
498 gst_wfd_tizen_message_free (msg);
506 gst_wfd_tizen_message_free (msg);
508 GST_ERROR_OBJECT (src, "Could not handle message");
514 gst_wfd_tizen_src_handle_get_parameter (GstWFDBaseSrc * bsrc,
515 GstRTSPMessage * request, GstRTSPMessage * response)
517 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (bsrc);
518 GstRTSPResult res = GST_RTSP_OK;
519 GstWFDResult wfd_res = GST_WFD_OK;
520 GstWFDTizenMessage *msg = NULL;
521 GstRTSPMethod method;
522 GstRTSPVersion version;
527 GString *body = NULL;
528 GString *body_length = NULL;
530 g_return_val_if_fail (request, GST_RTSP_EINVAL);
531 g_return_val_if_fail (response, GST_RTSP_EINVAL);
533 res = gst_rtsp_message_parse_request (request, &method, &uri, &version);
537 if (G_UNLIKELY (method != GST_RTSP_GET_PARAMETER))
540 res = gst_rtsp_message_get_body (request, &data, &size);
544 wfd_res = gst_wfd_tizen_message_new (&msg);
548 wfd_res = gst_wfd_tizen_message_parse_buffer (data, size, msg);
549 if (wfd_res != GST_WFD_OK)
552 if (msg->tizen_retransmission) {
553 if (src->do_request) {
554 guint32 rtp_port = RETRANSMITTED_RTP_PORT, rtcp_port = RTCP_FB_PORT;
557 gst_wfd_tizen_message_set_tizen_retransmission (msg, rtp_port,
559 if (wfd_res != GST_WFD_OK)
562 GST_DEBUG_OBJECT (src,
563 "tizen_retransmission : RTP port %d, RTCP port %d ", rtp_port,
568 if (msg->tizen_fec) {
571 gst_wfd_tizen_message_set_tizen_fec (msg, src->fec_max_k,
573 if (wfd_res != GST_WFD_OK)
576 GST_DEBUG_OBJECT (src, "tizen_fec : t max %d, p max %d ", src->fec_max_k,
581 if (msg->tizen_latency_mode) {
583 gst_wfd_tizen_message_set_tizen_latency_mode (msg,
584 WFD_TIZEN_LATENCY_MID);
585 if (wfd_res != GST_WFD_OK)
588 GST_DEBUG_OBJECT (src, "tizen_latency_mode : %d", src->latency_mode);
591 res = gst_rtsp_message_steal_body (response, &data, &size);
592 if (res != GST_RTSP_OK)
595 body = g_string_new ((const gchar *) data);
596 g_string_append (body, (const gchar *) gst_wfd_tizen_message_as_text (msg));
598 GST_ERROR_OBJECT (src, "gst_wfd_tizen_message_as_text is failed");
602 body_length = g_string_new ("");
603 g_string_append_printf (body_length, "%d", body->len);
604 GST_DEBUG_OBJECT (src, "body_length : %s", body_length->str);
606 gst_rtsp_message_remove_header (response, GST_RTSP_HDR_CONTENT_LENGTH, -1);
607 gst_rtsp_message_add_header (response, GST_RTSP_HDR_CONTENT_LENGTH,
608 g_string_free (body_length, FALSE));
610 GST_DEBUG_OBJECT (src, "body : %s", body->str);
613 gst_rtsp_message_set_body (response, (const guint8 *) body->str,
618 g_string_free (body, FALSE);
620 gst_wfd_tizen_message_free (msg);
628 gst_wfd_tizen_message_free (msg);
629 GST_ERROR_OBJECT (src, "Could not handle message");
636 gst_wfd_tizen_src_set_state (GstWFDBaseSrc * bsrc, GstState state)
638 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (bsrc);
641 GST_DEBUG_OBJECT (src, "try to set %s state",
642 gst_element_state_get_name (state));
644 for (i = 0; i < 3; i++) {
646 gst_element_set_state (src->udpsrc[i], state);
648 gst_element_set_state (src->udpsink[i], state);
652 gst_element_set_state (src->fecdec, state);
655 gst_element_set_state (src->session, state);
658 gst_element_set_state (src->requester, state);
660 if (src->wfdrtpbuffer)
661 gst_element_set_state (src->wfdrtpbuffer, state);
665 gst_wfd_tizen_src_cleanup (GstWFDBaseSrc * bsrc)
667 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (bsrc);
670 GST_DEBUG_OBJECT (src, "cleanup");
672 for (i = 0; i < 3; i++) {
673 if (src->channelpad[i]) {
674 gst_object_unref (src->channelpad[i]);
675 src->channelpad[i] = NULL;
677 if (src->udpsrc[i]) {
678 gst_element_set_state (src->udpsrc[i], GST_STATE_NULL);
679 gst_bin_remove (GST_BIN_CAST (src), src->udpsrc[i]);
680 gst_object_unref (src->udpsrc[i]);
681 src->udpsrc[i] = NULL;
683 if (src->udpsink[i]) {
684 gst_element_set_state (src->udpsink[i], GST_STATE_NULL);
685 gst_bin_remove (GST_BIN_CAST (src), src->udpsink[i]);
686 gst_object_unref (src->udpsink[i]);
687 src->udpsink[i] = NULL;
691 gst_element_set_state (src->fecdec, GST_STATE_NULL);
692 gst_bin_remove (GST_BIN_CAST (src), src->fecdec);
693 gst_object_unref (src->fecdec);
697 gst_element_set_state (src->session, GST_STATE_NULL);
698 gst_bin_remove (GST_BIN_CAST (src), src->session);
699 gst_object_unref (src->session);
702 if (src->requester) {
703 gst_element_set_state (src->requester, GST_STATE_NULL);
704 gst_bin_remove (GST_BIN_CAST (src), src->requester);
705 gst_object_unref (src->requester);
706 src->requester = NULL;
708 if (src->wfdrtpbuffer) {
709 gst_element_set_state (src->wfdrtpbuffer, GST_STATE_NULL);
710 gst_bin_remove (GST_BIN_CAST (src), src->wfdrtpbuffer);
711 gst_object_unref (src->wfdrtpbuffer);
712 src->wfdrtpbuffer = NULL;
717 gst_wfd_tizen_src_prepare_transport (GstWFDBaseSrc * bsrc, gint rtpport,
720 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (bsrc);
721 GstStateChangeReturn ret;
722 GstElement *udpsrc0, *udpsrc1, *udpsrc2;
723 gint tmp_rtp, tmp_rtcp, tmp_rtcp_fb;
731 host = "udp://[::0]";
733 host = "udp://0.0.0.0";
735 /* try to allocate 2 UDP ports */
736 udpsrc0 = gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL);
738 goto no_udp_protocol;
739 g_object_set (G_OBJECT (udpsrc0), "port", rtpport, "reuse", TRUE, NULL);
741 if (src->udp_buffer_size != 0)
742 g_object_set (G_OBJECT (udpsrc0), "buffer-size", src->udp_buffer_size,
745 GST_DEBUG_OBJECT (src, "starting RTP on port %d", rtpport);
746 ret = gst_element_set_state (udpsrc0, GST_STATE_READY);
747 if (ret == GST_STATE_CHANGE_FAILURE) {
748 GST_ERROR_OBJECT (src, "Unable to make udpsrc from RTP port %d", rtpport);
752 g_object_get (G_OBJECT (udpsrc0), "port", &tmp_rtp, NULL);
753 GST_DEBUG_OBJECT (src, "got RTP port %d", tmp_rtp);
755 /* check if port is even */
756 if ((tmp_rtp & 0x01) != 0) {
757 GST_DEBUG_OBJECT (src, "RTP port not even");
758 /* port not even, free RTP udpsrc */
762 /* allocate port+1 for RTCP now */
763 udpsrc1 = gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL);
765 goto no_udp_protocol;
768 g_object_set (G_OBJECT (udpsrc1), "port", rtcpport, "reuse", TRUE, NULL);
770 GST_DEBUG_OBJECT (src, "starting RTCP on port %d", rtcpport);
771 ret = gst_element_set_state (udpsrc1, GST_STATE_READY);
772 if (ret == GST_STATE_CHANGE_FAILURE) {
773 GST_ERROR_OBJECT (src, "Unable to make udpsrc from RTCP port %d", rtcpport);
777 /* allocate port #19120 for retransmitted RTP now */
778 udpsrc2 = gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL);
780 goto no_udp_protocol;
783 g_object_set (G_OBJECT (udpsrc2), "port", RETRANSMITTED_RTP_PORT, "reuse",
786 if (src->udp_buffer_size != 0)
787 g_object_set (G_OBJECT (udpsrc2), "buffer-size", src->udp_buffer_size,
790 GST_DEBUG_OBJECT (src, "starting Retransmitted RTP on port %d",
791 RETRANSMITTED_RTP_PORT);
792 ret = gst_element_set_state (udpsrc2, GST_STATE_READY);
793 if (ret == GST_STATE_CHANGE_FAILURE) {
794 GST_ERROR_OBJECT (src,
795 "Unable to make udpsrc from Retransmitted RTP port %d",
796 RETRANSMITTED_RTP_PORT);
800 /* all fine, do port check */
801 g_object_get (G_OBJECT (udpsrc0), "port", &tmp_rtp, NULL);
802 g_object_get (G_OBJECT (udpsrc1), "port", &tmp_rtcp, NULL);
803 g_object_get (G_OBJECT (udpsrc2), "port", &tmp_rtcp_fb, NULL);
805 /* this should not happen... */
806 if (rtpport != tmp_rtp || rtcpport != tmp_rtcp
807 || tmp_rtcp_fb != RETRANSMITTED_RTP_PORT)
810 /* we keep these elements, we configure all in configure_transport when the
811 * server told us to really use the UDP ports. */
812 src->udpsrc[0] = gst_object_ref_sink (udpsrc0);
813 src->udpsrc[1] = gst_object_ref_sink (udpsrc1);
814 src->udpsrc[2] = gst_object_ref_sink (udpsrc2);
815 gst_element_set_locked_state (src->udpsrc[0], TRUE);
816 gst_element_set_locked_state (src->udpsrc[1], TRUE);
817 gst_element_set_locked_state (src->udpsrc[2], TRUE);
824 GST_DEBUG_OBJECT (src, "could not get UDP source");
829 GST_DEBUG_OBJECT (src, "could not allocate UDP port pair");
834 GST_DEBUG_OBJECT (src,
835 "ports don't match rtp: %d<->%d, rtcp: %d<->%d, retransmitted rtp: %d<->%d",
836 tmp_rtp, rtpport, tmp_rtcp, rtcpport, tmp_rtcp_fb,
837 RETRANSMITTED_RTP_PORT);
843 gst_element_set_state (udpsrc0, GST_STATE_NULL);
844 gst_object_unref (udpsrc0);
847 gst_element_set_state (udpsrc1, GST_STATE_NULL);
848 gst_object_unref (udpsrc1);
851 gst_element_set_state (udpsrc2, GST_STATE_NULL);
852 gst_object_unref (udpsrc2);
854 return GST_RTSP_ERROR;
859 request_idr_by_requester (GstElement * requester, GstWFDTizenSrc * src)
861 GstEvent *event = NULL;
863 GST_DEBUG_OBJECT (src, "try to request idr");
865 /* Send IDR request */
867 gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
868 gst_structure_new ("GstWFDIDRRequest", NULL, NULL));
870 if (!gst_pad_send_event (GST_WFD_BASE_SRC_CAST (src)->srcpad, event))
871 GST_WARNING_OBJECT (src, "failed to send event for idr reuest");
875 on_bye_ssrc (GObject * session, guint32 ssrc, GstWFDTizenSrc * src)
877 GST_DEBUG_OBJECT (src, "source in session received BYE");
879 //gst_wfdtizensrc_do_stream_eos (src, manager);
883 on_new_ssrc (GObject * session, guint32 ssrc, GstWFDTizenSrc * src)
885 GST_DEBUG_OBJECT (src, "source in session received NEW");
889 on_timeout (GObject * session, guint32 ssrc, GstWFDTizenSrc * src)
891 GST_DEBUG_OBJECT (src, "source in session timed out");
893 //gst_wfdtizensrc_do_stream_eos (src, manager);
897 on_ssrc_active (GObject * session, guint32 ssrc, GstWFDTizenSrc * src)
899 GST_DEBUG_OBJECT (src, "source in session is active");
903 request_pt_map_for_wfdrtpbuffer (GstElement * wfdrtpbuffer, guint pt,
904 GstWFDTizenSrc * src)
908 GST_DEBUG_OBJECT (src, "getting pt map for pt %d", pt);
910 GST_WFD_BASE_STATE_LOCK (src);
911 caps = GST_WFD_BASE_SRC_CAST (src)->caps;
914 GST_WFD_BASE_STATE_UNLOCK (src);
920 request_pt_map_for_session (GstElement * session, guint pt,
921 GstWFDTizenSrc * src)
925 GST_DEBUG_OBJECT (src, "getting pt map for pt %d", pt);
927 GST_WFD_BASE_STATE_LOCK (src);
928 caps = GST_WFD_BASE_SRC_CAST (src)->caps;
931 GST_WFD_BASE_STATE_UNLOCK (src);
937 gst_wfd_tizen_src_configure_manager (GstWFDTizenSrc * src)
941 /* construct wfdtizensrc */
942 src->fecdec = gst_element_factory_make ("alfecdecoder", "wfdtizensrc_fecdec");
943 if (G_UNLIKELY (src->fecdec == NULL)) {
944 GST_ERROR_OBJECT (src, "could not create alfecdecoder element");
947 gboolean do_fec = FALSE;
949 do_fec = (src->latency_mode >= WFD_TIZEN_LATENCY_MID && src->do_fec);
950 g_object_set (G_OBJECT (src->fecdec), "do-fec", do_fec, NULL);
951 g_object_set (G_OBJECT (src->fecdec), "max-size-k", src->fec_max_k, NULL);
952 g_object_set (G_OBJECT (src->fecdec), "max-size-p", src->fec_max_p, NULL);
953 g_object_set (G_OBJECT (src->fecdec), "do-reorder", TRUE, NULL);
954 g_object_set (G_OBJECT (src->fecdec), "symbol-length",
955 src->fec_symbol_length, NULL);
957 src->channelpad[0] = gst_element_get_static_pad (src->fecdec, "sink");
958 if (G_UNLIKELY (src->channelpad[0] == NULL)) {
959 GST_ERROR_OBJECT (src, "could not create rtp channel pad");
963 /* we manage session element */
964 gst_element_set_locked_state (src->fecdec, TRUE);
966 if (!gst_bin_add (GST_BIN_CAST (src), src->fecdec)) {
967 GST_ERROR_OBJECT (src, "failed to add alfecdecoder to wfdtizensrc");
972 src->session = gst_element_factory_make ("rtpsession", "wfdtizensrc_session");
973 if (G_UNLIKELY (src->session == NULL)) {
974 GST_ERROR_OBJECT (src, "could not create gstrtpsession element");
979 g_signal_connect (src->session, "on-bye-ssrc", (GCallback) on_bye_ssrc,
981 g_signal_connect (src->session, "on-bye-timeout", (GCallback) on_timeout,
983 g_signal_connect (src->session, "on-timeout", (GCallback) on_timeout, src);
984 g_signal_connect (src->session, "on-ssrc-active",
985 (GCallback) on_ssrc_active, src);
986 g_signal_connect (src->session, "on-new-ssrc", (GCallback) on_new_ssrc,
988 g_signal_connect (src->session, "request-pt-map",
989 (GCallback) request_pt_map_for_session, src);
991 g_object_set (G_OBJECT (src->session), "rtcp-min-interval",
992 (guint64) 1000000000, NULL);
994 sinkpad = gst_element_get_request_pad (src->session, "recv_rtp_sink");
995 if (G_UNLIKELY (sinkpad == NULL)) {
996 GST_ERROR_OBJECT (src, "could not create rtp sink pad");
999 gst_object_unref (sinkpad);
1001 src->channelpad[1] =
1002 gst_element_get_request_pad (src->session, "recv_rtcp_sink");
1003 if (G_UNLIKELY (src->channelpad[1] == NULL)) {
1004 GST_ERROR_OBJECT (src, "could not create rtcp channel pad");
1008 /* we manage session element */
1009 gst_element_set_locked_state (src->session, TRUE);
1011 if (!gst_bin_add (GST_BIN_CAST (src), src->session)) {
1012 GST_ERROR_OBJECT (src, "failed to add rtpsession to wfdtizensrc");
1018 gst_element_factory_make ("wfdrtprequester", "wfdtizensrc_requester");
1019 if (G_UNLIKELY (src->requester == NULL)) {
1020 GST_ERROR_OBJECT (src, "could not create wfdrtprequester element");
1023 gboolean do_request = FALSE;
1025 g_signal_connect (src->requester, "request-idr",
1026 (GCallback) request_idr_by_requester, src);
1028 do_request = (src->latency_mode == WFD_TIZEN_LATENCY_HIGH
1029 && src->do_request);
1030 g_object_set (src->requester, "do-request", do_request, NULL);
1032 GST_DEBUG_OBJECT (src,
1033 "getting retransmitted RTP sink pad of gstrtprequester");
1034 src->channelpad[2] =
1035 gst_element_get_request_pad (src->requester, "retransmitted_rtp_sink");
1036 if (!src->channelpad[2]) {
1037 GST_DEBUG_OBJECT (src,
1038 "fail to get retransmitted RTP sink pad of gstrtprequester");
1042 /* we manage requester element */
1043 gst_element_set_locked_state (src->requester, TRUE);
1045 if (!gst_bin_add (GST_BIN_CAST (src), src->requester)) {
1046 GST_ERROR_OBJECT (src, "failed to add wfdrtprequester to wfdtizensrc");
1052 gst_element_factory_make ("wfdrtpbuffer", "wfdtizensrc_wfdrtpbuffer");
1053 if (G_UNLIKELY (src->wfdrtpbuffer == NULL)) {
1054 GST_ERROR_OBJECT (src, "could not create wfdrtpbuffer element");
1057 /* configure latency and packet lost */
1058 g_object_set (src->wfdrtpbuffer, "latency", src->latency, NULL);
1060 g_signal_connect (src->wfdrtpbuffer, "request-pt-map",
1061 (GCallback) request_pt_map_for_wfdrtpbuffer, src);
1063 /* we manage wfdrtpbuffer element */
1064 gst_element_set_locked_state (src->wfdrtpbuffer, TRUE);
1066 if (!gst_bin_add (GST_BIN_CAST (src), src->wfdrtpbuffer)) {
1067 GST_ERROR_OBJECT (src, "failed to add wfdrtpbuffer to wfdtizensrc");
1072 if (!gst_element_link_many (src->fecdec, src->session, src->requester,
1073 src->wfdrtpbuffer, NULL)) {
1074 GST_ERROR_OBJECT (src, "failed to link elements for wfdtizensrc");
1078 if (!gst_element_sync_state_with_parent (src->fecdec)) {
1079 GST_ERROR_OBJECT (src, "failed for %s to sync state with wfdtizensrc",
1080 GST_ELEMENT_NAME (src->fecdec));
1084 if (!gst_element_sync_state_with_parent (src->session)) {
1085 GST_ERROR_OBJECT (src, "failed for %s to sync state with wfdtizensrc",
1086 GST_ELEMENT_NAME (src->session));
1090 if (!gst_element_sync_state_with_parent (src->requester)) {
1091 GST_ERROR_OBJECT (src, "failed for %s to sync state with wfdtizensrc",
1092 GST_ELEMENT_NAME (src->requester));
1096 if (!gst_element_sync_state_with_parent (src->wfdrtpbuffer)) {
1097 GST_ERROR_OBJECT (src, "failed for %s to sync state with wfdtizensrc",
1098 GST_ELEMENT_NAME (src->wfdrtpbuffer));
1103 pad = gst_element_get_static_pad (src->wfdrtpbuffer, "src");
1104 if (G_UNLIKELY (pad == NULL)) {
1105 GST_ERROR_OBJECT (src,
1106 "failed to get src pad of wfdrtpbuffer for setting ghost pad of wfdtizensrc");
1110 if (!gst_wfd_base_src_set_target (GST_WFD_BASE_SRC (src), pad)) {
1111 GST_ERROR_OBJECT (src, "failed to set target pad of ghost pad");
1112 gst_object_unref (pad);
1116 gst_object_unref (pad);
1121 gst_wfd_tizen_src_configure_udp_sinks (GstWFDTizenSrc * src,
1122 GstRTSPTransport * transport)
1125 GSocket *socket = NULL;
1126 gint rtp_port = -1, rtcp_port = -1, rtcp_fb_port = -1;
1127 gboolean do_rtcp, do_rtcp_fb;
1128 GstPadLinkReturn res = GST_PAD_LINK_REFUSED;
1129 const gchar *destination = NULL;
1131 GstPad *rtcp_fb_pad = NULL;
1133 /* get transport info */
1134 gst_wfd_base_src_get_transport_info (GST_WFD_BASE_SRC (src), transport,
1135 &destination, &rtp_port, &rtcp_port);
1136 rtcp_fb_port = RTCP_FB_PORT;
1138 /* it's possible that the server does not want us to send RTCP in which case
1140 do_rtcp = (rtcp_port != -1 && src->session != NULL && src->do_rtcp);
1141 do_rtcp_fb = (rtcp_fb_port != -1);
1143 /* we need a destination when we have RTCP RR and RTCP FB ports */
1144 if (destination == NULL && (do_rtcp_fb || do_rtcp))
1145 goto no_destination;
1148 GstPad *rtcppad = NULL;
1150 GST_DEBUG_OBJECT (src, "configure RTCP UDP sink for %s:%d", destination,
1153 uri = g_strdup_printf ("udp://%s:%d", destination, rtcp_port);
1154 src->udpsink[1] = gst_element_make_from_uri (GST_URI_SINK, uri, NULL, NULL);
1156 if (src->udpsink[1] == NULL)
1157 goto no_sink_element;
1159 /* don't join multicast group, we will have the source socket do that */
1160 /* no sync or async state changes needed */
1161 g_object_set (G_OBJECT (src->udpsink[1]), "auto-multicast", FALSE, "loop",
1162 FALSE, "sync", FALSE, "async", FALSE, NULL);
1164 if (src->udpsrc[1]) {
1165 /* configure socket, we give it the same UDP socket as the udpsrc for RTCP
1166 * because some servers check the port number of where it sends RTCP to identify
1167 * the RTCP packets it receives */
1168 g_object_get (G_OBJECT (src->udpsrc[1]), "used-socket", &socket, NULL);
1169 GST_DEBUG_OBJECT (src, "RTCP UDP src has sock %p", socket);
1170 /* configure socket and make sure udpsink does not close it when shutting
1171 * down, it belongs to udpsrc after all. */
1172 g_object_set (G_OBJECT (src->udpsink[1]), "socket", socket,
1173 "close-socket", FALSE, NULL);
1174 g_object_unref (socket);
1177 /* we don't want to consider this a sink */
1178 GST_OBJECT_FLAG_UNSET (src->udpsink[1], GST_ELEMENT_FLAG_SINK);
1180 /* we keep this playing always */
1181 gst_element_set_locked_state (src->udpsink[1], TRUE);
1182 gst_element_set_state (src->udpsink[1], GST_STATE_PLAYING);
1184 gst_object_ref (src->udpsink[1]);
1185 gst_bin_add (GST_BIN_CAST (src), src->udpsink[1]);
1187 rtcppad = gst_element_get_static_pad (src->udpsink[1], "sink");
1189 /* get session RTCP pad */
1190 pad = gst_element_get_request_pad (src->session, "send_rtcp_src");
1194 res = gst_pad_link_full (pad, rtcppad, GST_PAD_LINK_CHECK_NOTHING);
1197 gst_object_unref (pad);
1199 gst_object_unref (rtcppad);
1200 if (res != GST_PAD_LINK_OK)
1205 GST_DEBUG_OBJECT (src, "configure RTCP FB sink for %s:%d", destination,
1208 uri = g_strdup_printf ("udp://%s:%d", destination, rtcp_fb_port);
1209 src->udpsink[2] = gst_element_make_from_uri (GST_URI_SINK, uri, NULL, NULL);
1211 if (src->udpsink[2] == NULL)
1212 goto no_sink_element;
1214 /* don't join multicast group, we will have the source socket do that */
1215 /* no sync or async state changes needed */
1216 g_object_set (G_OBJECT (src->udpsink[2]), "auto-multicast", FALSE, "loop",
1217 FALSE, "sync", FALSE, "async", FALSE, NULL);
1219 g_object_set (G_OBJECT (src->udpsink[2]), "bind-port", rtcp_fb_port,
1220 "close-socket", FALSE, NULL);
1222 /* we don't want to consider this a sink */
1223 GST_OBJECT_FLAG_UNSET (src->udpsink[2], GST_ELEMENT_FLAG_SINK);
1225 /* we keep this playing always */
1226 gst_element_set_locked_state (src->udpsink[2], TRUE);
1227 gst_element_set_state (src->udpsink[2], GST_STATE_PLAYING);
1229 gst_object_ref (src->udpsink[2]);
1230 gst_bin_add (GST_BIN_CAST (src), src->udpsink[2]);
1232 /* get RTCP FB sink pad */
1233 rtcp_fb_pad = gst_element_get_static_pad (src->udpsink[2], "sink");
1235 /* get requester RTCP pad */
1236 pad = gst_element_get_static_pad (src->requester, "rtcp_src");
1239 if (rtcp_fb_pad && pad)
1240 res = gst_pad_link (pad, rtcp_fb_pad);
1242 gst_object_unref (pad);
1244 gst_object_unref (rtcp_fb_pad);
1245 if (res != GST_PAD_LINK_OK)
1254 GST_ERROR_OBJECT (src, "no destination address specified");
1259 GST_ERROR_OBJECT (src, "no UDP sink element found");
1264 GST_ERROR_OBJECT (src, "pad linking is failed [%d]", res);
1270 pad_blocked (GstPad * pad, gboolean blocked, GstWFDTizenSrc * src)
1272 GST_DEBUG_OBJECT (src, "pad %s:%s blocked, activating streams",
1273 GST_DEBUG_PAD_NAME (pad));
1275 if (src->udpsrc[0]) {
1276 /* remove timeout, we are streaming now and timeouts will be handled by
1277 * the session manager and jitter buffer */
1278 g_object_set (G_OBJECT (src->udpsrc[0]), "timeout", (guint64) 0, NULL);
1281 /* activate the streams */
1282 gst_wfd_base_src_activate (GST_WFD_BASE_SRC (src));
1284 /* unblock all pads */
1285 if (src->blockedpad && src->blockid != 0) {
1286 GST_DEBUG_OBJECT (src, "unblocking blocked pad");
1287 gst_pad_remove_probe (src->blockedpad, src->blockid);
1289 src->blockedpad = NULL;
1294 gst_wfd_tizen_src_configure_udp (GstWFDTizenSrc * src)
1298 /* we manage the UDP elements now. For unicast, the UDP sources where
1299 * allocated in the stream when we suggested a transport. */
1300 if (src->udpsrc[0]) {
1303 gst_element_set_locked_state (src->udpsrc[0], TRUE);
1304 gst_bin_add (GST_BIN_CAST (src), src->udpsrc[0]);
1306 GST_DEBUG_OBJECT (src, "setting up UDP source");
1308 /* configure a timeout on the UDP port. When the timeout message is
1310 g_object_set (G_OBJECT (src->udpsrc[0]), "timeout", src->udp_timeout * 1000,
1313 caps = gst_caps_new_simple ("application/x-rtp",
1314 "media", G_TYPE_STRING, "video", "payload", G_TYPE_INT, 33,
1315 "clock-rate", G_TYPE_INT, 90000, NULL);
1316 g_object_set (src->udpsrc[0], "caps", caps, NULL);
1317 gst_caps_unref (caps);
1319 /* get output pad of the UDP source. */
1320 outpad = gst_element_get_static_pad (src->udpsrc[0], "src");
1322 /* save it so we can unblock */
1323 src->blockedpad = outpad;
1325 /* configure pad block on the pad. As soon as there is dataflow on the
1326 * UDP source, we know that UDP is not blocked by a firewall and we can
1327 * configure all the streams to let the application autoplug decoders. */
1329 gst_pad_add_probe (src->blockedpad,
1330 GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER |
1331 GST_PAD_PROBE_TYPE_BUFFER_LIST, (GstPadProbeCallback) pad_blocked, src,
1334 if (src->channelpad[0]) {
1335 GST_DEBUG_OBJECT (src, "connecting UDP source 0 to session");
1336 /* configure for UDP delivery, we need to connect the UDP pads to
1337 * the session plugin. */
1338 gst_pad_link_full (outpad, src->channelpad[0],
1339 GST_PAD_LINK_CHECK_NOTHING);
1340 /* we connected to pad-added signal to get pads from the manager */
1342 /* leave unlinked */
1347 if (src->udpsrc[1]) {
1350 gst_element_set_locked_state (src->udpsrc[1], TRUE);
1351 gst_bin_add (GST_BIN_CAST (src), src->udpsrc[1]);
1353 caps = gst_caps_new_empty_simple ("application/x-rtcp");
1354 g_object_set (src->udpsrc[1], "caps", caps, NULL);
1355 gst_caps_unref (caps);
1357 if (src->channelpad[1]) {
1360 GST_DEBUG_OBJECT (src, "connecting UDP source 1 to session");
1362 pad = gst_element_get_static_pad (src->udpsrc[1], "src");
1363 gst_pad_link_full (pad, src->channelpad[1], GST_PAD_LINK_CHECK_NOTHING);
1364 gst_object_unref (pad);
1366 /* leave unlinked */
1370 /* Retransmitted RTP port */
1371 if (src->udpsrc[2]) {
1374 gst_element_set_locked_state (src->udpsrc[2], TRUE);
1375 gst_bin_add (GST_BIN_CAST (src), src->udpsrc[2]);
1377 caps = gst_caps_new_simple ("application/x-rtp",
1378 "media", G_TYPE_STRING, "video", "payload", G_TYPE_INT, 33,
1379 "clock-rate", G_TYPE_INT, 90000, NULL);
1380 g_object_set (src->udpsrc[2], "caps", caps, NULL);
1381 gst_caps_unref (caps);
1383 if (src->channelpad[2]) {
1386 GST_DEBUG_OBJECT (src, "connecting UDP source 2 to requester");
1387 pad = gst_element_get_static_pad (src->udpsrc[2], "src");
1388 gst_pad_link_full (pad, src->channelpad[2], GST_PAD_LINK_CHECK_NOTHING);
1389 gst_object_unref (pad);
1391 /* leave unlinked */
1398 static GstRTSPResult
1399 gst_wfd_tizen_src_configure_transport (GstWFDBaseSrc * bsrc,
1400 GstRTSPTransport * transport)
1402 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (bsrc);
1405 g_return_val_if_fail (transport, GST_RTSP_EINVAL);
1407 GST_DEBUG_OBJECT (src, "configuring transport");
1409 /* get the proper mime type for this manager now */
1410 if (gst_rtsp_transport_get_mime (transport->trans, &mime) < 0)
1411 goto unknown_transport;
1413 goto unknown_transport;
1415 /* configure the final mime type */
1416 GST_DEBUG_OBJECT (src, "setting mime to %s", mime);
1418 if (!gst_wfd_tizen_src_configure_manager (src))
1421 switch (transport->lower_transport) {
1422 case GST_RTSP_LOWER_TRANS_TCP:
1423 case GST_RTSP_LOWER_TRANS_UDP_MCAST:
1424 goto transport_failed;
1425 case GST_RTSP_LOWER_TRANS_UDP:
1426 if (!gst_wfd_tizen_src_configure_udp (src))
1427 goto transport_failed;
1428 if (!gst_wfd_tizen_src_configure_udp_sinks (src, transport))
1429 goto transport_failed;
1432 goto unknown_transport;
1440 GST_DEBUG_OBJECT (src, "unknown transport");
1441 return GST_RTSP_ERROR;
1445 GST_DEBUG_OBJECT (src, "cannot configure manager");
1446 return GST_RTSP_ERROR;
1450 GST_DEBUG_OBJECT (src, "failed to configure transport");
1451 return GST_RTSP_ERROR;
1456 gst_wfd_tizen_src_push_event (GstWFDBaseSrc * bsrc, GstEvent * event)
1458 GstWFDTizenSrc *src = GST_WFD_TIZEN_SRC (bsrc);
1459 gboolean res = TRUE;
1461 if (src->udpsrc[0] && GST_STATE (src->udpsrc[0]) >= GST_STATE_PAUSED) {
1462 gst_event_ref (event);
1463 res = gst_element_send_event (src->udpsrc[0], event);
1464 } else if (src->channelpad[0]) {
1465 gst_event_ref (event);
1466 if (GST_PAD_IS_SRC (src->channelpad[0]))
1467 res = gst_pad_push_event (src->channelpad[0], event);
1469 res = gst_pad_send_event (src->channelpad[0], event);
1472 if (src->udpsrc[1] && GST_STATE (src->udpsrc[1]) >= GST_STATE_PAUSED) {
1473 gst_event_ref (event);
1474 res &= gst_element_send_event (src->udpsrc[1], event);
1475 } else if (src->channelpad[1]) {
1476 gst_event_ref (event);
1477 if (GST_PAD_IS_SRC (src->channelpad[1]))
1478 res &= gst_pad_push_event (src->channelpad[1], event);
1480 res &= gst_pad_send_event (src->channelpad[1], event);
1483 if (src->udpsrc[2] && GST_STATE (src->udpsrc[2]) >= GST_STATE_PAUSED) {
1484 gst_event_ref (event);
1485 res &= gst_element_send_event (src->udpsrc[2], event);
1486 } else if (src->channelpad[2]) {
1487 gst_event_ref (event);
1488 if (GST_PAD_IS_SRC (src->channelpad[2]))
1489 res &= gst_pad_push_event (src->channelpad[2], event);
1491 res &= gst_pad_send_event (src->channelpad[2], event);
1494 gst_event_unref (event);