rtspsrc: use use-rtsp-buffering property of rtpbin
[platform/upstream/gst-plugins-good.git] / gst / rtsp / gstrtspsrc.c
1 /* GStreamer
2  * Copyright (C) <2005,2006> Wim Taymans <wim at fluendo dot com>
3  *               <2006> Lutz Mueller <lutz at topfrose dot de>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 /*
21  * Unless otherwise indicated, Source Code is licensed under MIT license.
22  * See further explanation attached in License Statement (distributed in the file
23  * LICENSE).
24  *
25  * Permission is hereby granted, free of charge, to any person obtaining a copy of
26  * this software and associated documentation files (the "Software"), to deal in
27  * the Software without restriction, including without limitation the rights to
28  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
29  * of the Software, and to permit persons to whom the Software is furnished to do
30  * so, subject to the following conditions:
31  *
32  * The above copyright notice and this permission notice shall be included in all
33  * copies or substantial portions of the Software.
34  *
35  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41  * SOFTWARE.
42  */
43 /**
44  * SECTION:element-rtspsrc
45  * @title: rtspsrc
46  *
47  * Makes a connection to an RTSP server and read the data.
48  * rtspsrc strictly follows RFC 2326 and therefore does not (yet) support
49  * RealMedia/Quicktime/Microsoft extensions.
50  *
51  * RTSP supports transport over TCP or UDP in unicast or multicast mode. By
52  * default rtspsrc will negotiate a connection in the following order:
53  * UDP unicast/UDP multicast/TCP. The order cannot be changed but the allowed
54  * protocols can be controlled with the #GstRTSPSrc:protocols property.
55  *
56  * rtspsrc currently understands SDP as the format of the session description.
57  * For each stream listed in the SDP a new rtp_stream\%d pad will be created
58  * with caps derived from the SDP media description. This is a caps of mime type
59  * "application/x-rtp" that can be connected to any available RTP depayloader
60  * element.
61  *
62  * rtspsrc will internally instantiate an RTP session manager element
63  * that will handle the RTCP messages to and from the server, jitter removal,
64  * packet reordering along with providing a clock for the pipeline.
65  * This feature is implemented using the gstrtpbin element.
66  *
67  * rtspsrc acts like a live source and will therefore only generate data in the
68  * PLAYING state.
69  *
70  * If a RTP session times out then the rtspsrc will generate an element message
71  * named "GstRTSPSrcTimeout". Currently this is only supported for timeouts
72  * triggered by RTCP.
73  *
74  * The message's structure contains three fields:
75  *
76  *   #GstRTSPSrcTimeoutCause `cause`: the cause of the timeout.
77  *
78  *   #gint `stream-number`: an internal identifier of the stream that timed out.
79  *
80  *   #guint `ssrc`: the SSRC of the stream that timed out.
81  *
82  * ## Example launch line
83  * |[
84  * gst-launch-1.0 rtspsrc location=rtsp://some.server/url ! fakesink
85  * ]| Establish a connection to an RTSP server and send the raw RTP packets to a
86  * fakesink.
87  *
88  */
89
90 #ifdef HAVE_CONFIG_H
91 #include "config.h"
92 #endif
93
94 #ifdef HAVE_UNISTD_H
95 #include <unistd.h>
96 #endif /* HAVE_UNISTD_H */
97 #include <stdlib.h>
98 #include <string.h>
99 #include <stdio.h>
100 #include <stdarg.h>
101
102 #include <gst/net/gstnet.h>
103 #include <gst/sdp/gstsdpmessage.h>
104 #include <gst/sdp/gstmikey.h>
105 #include <gst/rtp/rtp.h>
106
107 #include "gst/gst-i18n-plugin.h"
108
109 #include "gstrtspsrc.h"
110
111 GST_DEBUG_CATEGORY_STATIC (rtspsrc_debug);
112 #define GST_CAT_DEFAULT (rtspsrc_debug)
113
114 static GstStaticPadTemplate rtptemplate = GST_STATIC_PAD_TEMPLATE ("stream_%u",
115     GST_PAD_SRC,
116     GST_PAD_SOMETIMES,
117     GST_STATIC_CAPS ("application/x-rtp; application/x-rdt"));
118
119 /* templates used internally */
120 static GstStaticPadTemplate anysrctemplate =
121 GST_STATIC_PAD_TEMPLATE ("internalsrc_%u",
122     GST_PAD_SRC,
123     GST_PAD_SOMETIMES,
124     GST_STATIC_CAPS_ANY);
125
126 static GstStaticPadTemplate anysinktemplate =
127 GST_STATIC_PAD_TEMPLATE ("internalsink_%u",
128     GST_PAD_SINK,
129     GST_PAD_SOMETIMES,
130     GST_STATIC_CAPS_ANY);
131
132 enum
133 {
134   SIGNAL_HANDLE_REQUEST,
135   SIGNAL_ON_SDP,
136   SIGNAL_SELECT_STREAM,
137   SIGNAL_NEW_MANAGER,
138   SIGNAL_REQUEST_RTCP_KEY,
139   SIGNAL_ACCEPT_CERTIFICATE,
140   SIGNAL_BEFORE_SEND,
141   SIGNAL_PUSH_BACKCHANNEL_BUFFER,
142   SIGNAL_GET_PARAMETER,
143   SIGNAL_GET_PARAMETERS,
144   SIGNAL_SET_PARAMETER,
145   LAST_SIGNAL
146 };
147
148 enum _GstRtspSrcRtcpSyncMode
149 {
150   RTCP_SYNC_ALWAYS,
151   RTCP_SYNC_INITIAL,
152   RTCP_SYNC_RTP
153 };
154
155 enum _GstRtspSrcBufferMode
156 {
157   BUFFER_MODE_NONE,
158   BUFFER_MODE_SLAVE,
159   BUFFER_MODE_BUFFER,
160   BUFFER_MODE_AUTO,
161   BUFFER_MODE_SYNCED
162 };
163
164 #define GST_TYPE_RTSP_SRC_BUFFER_MODE (gst_rtsp_src_buffer_mode_get_type())
165 static GType
166 gst_rtsp_src_buffer_mode_get_type (void)
167 {
168   static GType buffer_mode_type = 0;
169   static const GEnumValue buffer_modes[] = {
170     {BUFFER_MODE_NONE, "Only use RTP timestamps", "none"},
171     {BUFFER_MODE_SLAVE, "Slave receiver to sender clock", "slave"},
172     {BUFFER_MODE_BUFFER, "Do low/high watermark buffering", "buffer"},
173     {BUFFER_MODE_AUTO, "Choose mode depending on stream live", "auto"},
174     {BUFFER_MODE_SYNCED, "Synchronized sender and receiver clocks", "synced"},
175     {0, NULL, NULL},
176   };
177
178   if (!buffer_mode_type) {
179     buffer_mode_type =
180         g_enum_register_static ("GstRTSPSrcBufferMode", buffer_modes);
181   }
182   return buffer_mode_type;
183 }
184
185 enum _GstRtspSrcNtpTimeSource
186 {
187   NTP_TIME_SOURCE_NTP,
188   NTP_TIME_SOURCE_UNIX,
189   NTP_TIME_SOURCE_RUNNING_TIME,
190   NTP_TIME_SOURCE_CLOCK_TIME
191 };
192
193 #define DEBUG_RTSP(__self,msg) gst_rtspsrc_print_rtsp_message (__self, msg)
194 #define DEBUG_SDP(__self,msg) gst_rtspsrc_print_sdp_message (__self, msg)
195
196 #define GST_TYPE_RTSP_SRC_NTP_TIME_SOURCE (gst_rtsp_src_ntp_time_source_get_type())
197 static GType
198 gst_rtsp_src_ntp_time_source_get_type (void)
199 {
200   static GType ntp_time_source_type = 0;
201   static const GEnumValue ntp_time_source_values[] = {
202     {NTP_TIME_SOURCE_NTP, "NTP time based on realtime clock", "ntp"},
203     {NTP_TIME_SOURCE_UNIX, "UNIX time based on realtime clock", "unix"},
204     {NTP_TIME_SOURCE_RUNNING_TIME,
205           "Running time based on pipeline clock",
206         "running-time"},
207     {NTP_TIME_SOURCE_CLOCK_TIME, "Pipeline clock time", "clock-time"},
208     {0, NULL, NULL},
209   };
210
211   if (!ntp_time_source_type) {
212     ntp_time_source_type =
213         g_enum_register_static ("GstRTSPSrcNtpTimeSource",
214         ntp_time_source_values);
215   }
216   return ntp_time_source_type;
217 }
218
219 enum _GstRtspBackchannel
220 {
221   BACKCHANNEL_NONE,
222   BACKCHANNEL_ONVIF
223 };
224
225 #define GST_TYPE_RTSP_BACKCHANNEL (gst_rtsp_backchannel_get_type())
226 static GType
227 gst_rtsp_backchannel_get_type (void)
228 {
229   static GType backchannel_type = 0;
230   static const GEnumValue backchannel_values[] = {
231     {BACKCHANNEL_NONE, "No backchannel", "none"},
232     {BACKCHANNEL_ONVIF, "ONVIF audio backchannel", "onvif"},
233     {0, NULL, NULL},
234   };
235
236   if (G_UNLIKELY (backchannel_type == 0)) {
237     backchannel_type =
238         g_enum_register_static ("GstRTSPBackchannel", backchannel_values);
239   }
240   return backchannel_type;
241 }
242
243 #define BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL "www.onvif.org/ver20/backchannel"
244
245 #define DEFAULT_LOCATION         NULL
246 #define DEFAULT_PROTOCOLS        GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP
247 #define DEFAULT_DEBUG            FALSE
248 #define DEFAULT_RETRY            20
249 #define DEFAULT_TIMEOUT          5000000
250 #define DEFAULT_UDP_BUFFER_SIZE  0x80000
251 #define DEFAULT_TCP_TIMEOUT      20000000
252 #define DEFAULT_LATENCY_MS       2000
253 #define DEFAULT_DROP_ON_LATENCY  FALSE
254 #define DEFAULT_CONNECTION_SPEED 0
255 #define DEFAULT_NAT_METHOD       GST_RTSP_NAT_DUMMY
256 #define DEFAULT_DO_RTCP          TRUE
257 #define DEFAULT_DO_RTSP_KEEP_ALIVE       TRUE
258 #define DEFAULT_PROXY            NULL
259 #define DEFAULT_RTP_BLOCKSIZE    0
260 #define DEFAULT_USER_ID          NULL
261 #define DEFAULT_USER_PW          NULL
262 #define DEFAULT_BUFFER_MODE      BUFFER_MODE_AUTO
263 #define DEFAULT_PORT_RANGE       NULL
264 #define DEFAULT_SHORT_HEADER     FALSE
265 #define DEFAULT_PROBATION        2
266 #define DEFAULT_UDP_RECONNECT    TRUE
267 #define DEFAULT_MULTICAST_IFACE  NULL
268 #define DEFAULT_NTP_SYNC         FALSE
269 #define DEFAULT_USE_PIPELINE_CLOCK       FALSE
270 #define DEFAULT_TLS_VALIDATION_FLAGS     G_TLS_CERTIFICATE_VALIDATE_ALL
271 #define DEFAULT_TLS_DATABASE     NULL
272 #define DEFAULT_TLS_INTERACTION     NULL
273 #define DEFAULT_DO_RETRANSMISSION        TRUE
274 #define DEFAULT_NTP_TIME_SOURCE  NTP_TIME_SOURCE_NTP
275 #define DEFAULT_USER_AGENT       "GStreamer/" PACKAGE_VERSION
276 #define DEFAULT_MAX_RTCP_RTP_TIME_DIFF 1000
277 #define DEFAULT_RFC7273_SYNC         FALSE
278 #define DEFAULT_MAX_TS_OFFSET_ADJUSTMENT   G_GUINT64_CONSTANT(0)
279 #define DEFAULT_MAX_TS_OFFSET   G_GINT64_CONSTANT(3000000000)
280 #define DEFAULT_VERSION         GST_RTSP_VERSION_1_0
281 #define DEFAULT_BACKCHANNEL  GST_RTSP_BACKCHANNEL_NONE
282 #define DEFAULT_TEARDOWN_TIMEOUT  (100 * GST_MSECOND)
283
284 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
285 #define DEFAULT_START_POSITION   0
286 #endif
287
288 enum
289 {
290   PROP_0,
291   PROP_LOCATION,
292   PROP_PROTOCOLS,
293   PROP_DEBUG,
294   PROP_RETRY,
295   PROP_TIMEOUT,
296 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
297   PROP_START_POSITION,
298   PROP_RESUME_POSITION,
299 #endif
300   PROP_TCP_TIMEOUT,
301   PROP_LATENCY,
302   PROP_DROP_ON_LATENCY,
303   PROP_CONNECTION_SPEED,
304   PROP_NAT_METHOD,
305   PROP_DO_RTCP,
306   PROP_DO_RTSP_KEEP_ALIVE,
307   PROP_PROXY,
308   PROP_PROXY_ID,
309   PROP_PROXY_PW,
310   PROP_RTP_BLOCKSIZE,
311   PROP_USER_ID,
312   PROP_USER_PW,
313   PROP_BUFFER_MODE,
314   PROP_PORT_RANGE,
315   PROP_UDP_BUFFER_SIZE,
316   PROP_SHORT_HEADER,
317   PROP_PROBATION,
318   PROP_UDP_RECONNECT,
319   PROP_MULTICAST_IFACE,
320   PROP_NTP_SYNC,
321   PROP_USE_PIPELINE_CLOCK,
322   PROP_SDES,
323   PROP_TLS_VALIDATION_FLAGS,
324   PROP_TLS_DATABASE,
325   PROP_TLS_INTERACTION,
326   PROP_DO_RETRANSMISSION,
327   PROP_NTP_TIME_SOURCE,
328   PROP_USER_AGENT,
329   PROP_MAX_RTCP_RTP_TIME_DIFF,
330   PROP_RFC7273_SYNC,
331   PROP_MAX_TS_OFFSET_ADJUSTMENT,
332   PROP_MAX_TS_OFFSET,
333   PROP_DEFAULT_VERSION,
334   PROP_BACKCHANNEL,
335   PROP_TEARDOWN_TIMEOUT,
336 };
337
338 #define GST_TYPE_RTSP_NAT_METHOD (gst_rtsp_nat_method_get_type())
339 static GType
340 gst_rtsp_nat_method_get_type (void)
341 {
342   static GType rtsp_nat_method_type = 0;
343   static const GEnumValue rtsp_nat_method[] = {
344     {GST_RTSP_NAT_NONE, "None", "none"},
345     {GST_RTSP_NAT_DUMMY, "Send Dummy packets", "dummy"},
346     {0, NULL, NULL},
347   };
348
349   if (!rtsp_nat_method_type) {
350     rtsp_nat_method_type =
351         g_enum_register_static ("GstRTSPNatMethod", rtsp_nat_method);
352   }
353   return rtsp_nat_method_type;
354 }
355
356 #define RTSP_SRC_RESPONSE_ERROR(src, response_msg, err_cat, err_code, error_message) \
357   do { \
358     GST_ELEMENT_ERROR_WITH_DETAILS((src), err_cat, err_code, ("%s", error_message), \
359         ("%s (%d)", (response_msg)->type_data.response.reason, (response_msg)->type_data.response.code), \
360         ("rtsp-status-code", G_TYPE_UINT, (response_msg)->type_data.response.code, \
361          "rtsp-status-reason", G_TYPE_STRING, GST_STR_NULL((response_msg)->type_data.response.reason), NULL)); \
362   } while (0)
363
364 typedef struct _ParameterRequest
365 {
366   gint cmd;
367   gchar *content_type;
368   GString *body;
369   GstPromise *promise;
370 } ParameterRequest;
371
372 static void gst_rtspsrc_finalize (GObject * object);
373
374 static void gst_rtspsrc_set_property (GObject * object, guint prop_id,
375     const GValue * value, GParamSpec * pspec);
376 static void gst_rtspsrc_get_property (GObject * object, guint prop_id,
377     GValue * value, GParamSpec * pspec);
378
379 static GstClock *gst_rtspsrc_provide_clock (GstElement * element);
380
381 static void gst_rtspsrc_uri_handler_init (gpointer g_iface,
382     gpointer iface_data);
383
384 static gboolean gst_rtspsrc_set_proxy (GstRTSPSrc * rtsp, const gchar * proxy);
385 static void gst_rtspsrc_set_tcp_timeout (GstRTSPSrc * rtspsrc, guint64 timeout);
386
387 static GstStateChangeReturn gst_rtspsrc_change_state (GstElement * element,
388     GstStateChange transition);
389 static gboolean gst_rtspsrc_send_event (GstElement * element, GstEvent * event);
390 static void gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message);
391
392 static gboolean gst_rtspsrc_setup_auth (GstRTSPSrc * src,
393     GstRTSPMessage * response);
394
395 static gboolean gst_rtspsrc_loop_send_cmd (GstRTSPSrc * src, gint cmd,
396     gint mask);
397 static GstRTSPResult gst_rtspsrc_send_cb (GstRTSPExtension * ext,
398     GstRTSPMessage * request, GstRTSPMessage * response, GstRTSPSrc * src);
399
400 static GstRTSPResult gst_rtspsrc_open (GstRTSPSrc * src, gboolean async);
401 static GstRTSPResult gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment,
402     gboolean async, const gchar * seek_style);
403 static GstRTSPResult gst_rtspsrc_pause (GstRTSPSrc * src, gboolean async);
404 static GstRTSPResult gst_rtspsrc_close (GstRTSPSrc * src, gboolean async,
405     gboolean only_close);
406
407 static gboolean gst_rtspsrc_uri_set_uri (GstURIHandler * handler,
408     const gchar * uri, GError ** error);
409 static gchar *gst_rtspsrc_uri_get_uri (GstURIHandler * handler);
410
411 static gboolean gst_rtspsrc_activate_streams (GstRTSPSrc * src);
412 static gboolean gst_rtspsrc_loop (GstRTSPSrc * src);
413 static gboolean gst_rtspsrc_stream_push_event (GstRTSPSrc * src,
414     GstRTSPStream * stream, GstEvent * event);
415 static gboolean gst_rtspsrc_push_event (GstRTSPSrc * src, GstEvent * event);
416 static void gst_rtspsrc_connection_flush (GstRTSPSrc * src, gboolean flush);
417 static GstRTSPResult gst_rtsp_conninfo_close (GstRTSPSrc * src,
418     GstRTSPConnInfo * info, gboolean free);
419 static void
420 gst_rtspsrc_print_rtsp_message (GstRTSPSrc * src, const GstRTSPMessage * msg);
421 static void
422 gst_rtspsrc_print_sdp_message (GstRTSPSrc * src, const GstSDPMessage * msg);
423
424 static GstRTSPResult
425 gst_rtspsrc_get_parameter (GstRTSPSrc * src, ParameterRequest * req);
426
427 static GstRTSPResult
428 gst_rtspsrc_set_parameter (GstRTSPSrc * src, ParameterRequest * req);
429
430 static gboolean get_parameter (GstRTSPSrc * src, const gchar * parameter,
431     const gchar * content_type, GstPromise * promise);
432
433 static gboolean get_parameters (GstRTSPSrc * src, gchar ** parameters,
434     const gchar * content_type, GstPromise * promise);
435
436 static gboolean set_parameter (GstRTSPSrc * src, const gchar * name,
437     const gchar * value, const gchar * content_type, GstPromise * promise);
438
439 static GstFlowReturn gst_rtspsrc_push_backchannel_buffer (GstRTSPSrc * src,
440     guint id, GstSample * sample);
441
442 typedef struct
443 {
444   guint8 pt;
445   GstCaps *caps;
446 } PtMapItem;
447
448 /* commands we send to out loop to notify it of events */
449 #define CMD_OPEN            (1 << 0)
450 #define CMD_PLAY            (1 << 1)
451 #define CMD_PAUSE           (1 << 2)
452 #define CMD_CLOSE           (1 << 3)
453 #define CMD_WAIT            (1 << 4)
454 #define CMD_RECONNECT       (1 << 5)
455 #define CMD_LOOP            (1 << 6)
456 #define CMD_GET_PARAMETER   (1 << 7)
457 #define CMD_SET_PARAMETER   (1 << 8)
458
459 /* mask for all commands */
460 #define CMD_ALL         ((CMD_SET_PARAMETER << 1) - 1)
461
462 #define GST_ELEMENT_PROGRESS(el, type, code, text)      \
463 G_STMT_START {                                          \
464   gchar *__txt = _gst_element_error_printf text;        \
465   gst_element_post_message (GST_ELEMENT_CAST (el),      \
466       gst_message_new_progress (GST_OBJECT_CAST (el),   \
467           GST_PROGRESS_TYPE_ ##type, code, __txt));     \
468   g_free (__txt);                                       \
469 } G_STMT_END
470
471 static guint gst_rtspsrc_signals[LAST_SIGNAL] = { 0 };
472
473 #define gst_rtspsrc_parent_class parent_class
474 G_DEFINE_TYPE_WITH_CODE (GstRTSPSrc, gst_rtspsrc, GST_TYPE_BIN,
475     G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_rtspsrc_uri_handler_init));
476
477 #ifndef GST_DISABLE_GST_DEBUG
478 static inline const char *
479 cmd_to_string (guint cmd)
480 {
481   switch (cmd) {
482     case CMD_OPEN:
483       return "OPEN";
484     case CMD_PLAY:
485       return "PLAY";
486     case CMD_PAUSE:
487       return "PAUSE";
488     case CMD_CLOSE:
489       return "CLOSE";
490     case CMD_WAIT:
491       return "WAIT";
492     case CMD_RECONNECT:
493       return "RECONNECT";
494     case CMD_LOOP:
495       return "LOOP";
496     case CMD_GET_PARAMETER:
497       return "GET_PARAMETER";
498     case CMD_SET_PARAMETER:
499       return "SET_PARAMETER";
500   }
501
502   return "unknown";
503 }
504 #endif
505
506 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
507 static void
508 gst_rtspsrc_post_error_message (GstRTSPSrc * src, GstRTSPSrcError error_id,
509     const gchar * error_string)
510 {
511   GstMessage *message;
512   GstStructure *structure;
513   gboolean ret = TRUE;
514
515   GST_ERROR_OBJECT (src, "[%d] %s", error_id, error_string);
516
517   structure = gst_structure_new ("streaming_error",
518       "error_id", G_TYPE_UINT, error_id,
519       "error_string", G_TYPE_STRING, error_string, NULL);
520
521   message =
522       gst_message_new_custom (GST_MESSAGE_ERROR, GST_OBJECT (src), structure);
523
524   ret = gst_element_post_message (GST_ELEMENT (src), message);
525   if (!ret)
526     GST_ERROR_OBJECT (src, "fail to post error message.");
527
528   return;
529 }
530 #endif
531
532 static gboolean
533 default_select_stream (GstRTSPSrc * src, guint id, GstCaps * caps)
534 {
535   GST_DEBUG_OBJECT (src, "default handler");
536   return TRUE;
537 }
538
539 static gboolean
540 select_stream_accum (GSignalInvocationHint * ihint,
541     GValue * return_accu, const GValue * handler_return, gpointer data)
542 {
543   gboolean myboolean;
544
545   myboolean = g_value_get_boolean (handler_return);
546   GST_DEBUG ("accum %d", myboolean);
547   g_value_set_boolean (return_accu, myboolean);
548
549   /* stop emission if FALSE */
550   return myboolean;
551 }
552
553 static gboolean
554 default_before_send (GstRTSPSrc * src, GstRTSPMessage * msg)
555 {
556   GST_DEBUG_OBJECT (src, "default handler");
557   return TRUE;
558 }
559
560 static gboolean
561 before_send_accum (GSignalInvocationHint * ihint,
562     GValue * return_accu, const GValue * handler_return, gpointer data)
563 {
564   gboolean myboolean;
565
566   myboolean = g_value_get_boolean (handler_return);
567   g_value_set_boolean (return_accu, myboolean);
568
569   /* prevent send if FALSE */
570   return myboolean;
571 }
572
573 static void
574 gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
575 {
576   GObjectClass *gobject_class;
577   GstElementClass *gstelement_class;
578   GstBinClass *gstbin_class;
579
580   gobject_class = (GObjectClass *) klass;
581   gstelement_class = (GstElementClass *) klass;
582   gstbin_class = (GstBinClass *) klass;
583
584   GST_DEBUG_CATEGORY_INIT (rtspsrc_debug, "rtspsrc", 0, "RTSP src");
585
586   gobject_class->set_property = gst_rtspsrc_set_property;
587   gobject_class->get_property = gst_rtspsrc_get_property;
588
589   gobject_class->finalize = gst_rtspsrc_finalize;
590
591   g_object_class_install_property (gobject_class, PROP_LOCATION,
592       g_param_spec_string ("location", "RTSP Location",
593           "Location of the RTSP url to read",
594           DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
595
596   g_object_class_install_property (gobject_class, PROP_PROTOCOLS,
597       g_param_spec_flags ("protocols", "Protocols",
598           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
599           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
600
601   g_object_class_install_property (gobject_class, PROP_DEBUG,
602       g_param_spec_boolean ("debug", "Debug",
603           "Dump request and response messages to stdout"
604           "(DEPRECATED: Printed all RTSP message to gstreamer log as 'log' level)",
605           DEFAULT_DEBUG,
606           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
607
608   g_object_class_install_property (gobject_class, PROP_RETRY,
609       g_param_spec_uint ("retry", "Retry",
610           "Max number of retries when allocating RTP ports.",
611           0, G_MAXUINT16, DEFAULT_RETRY,
612           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
613
614   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
615       g_param_spec_uint64 ("timeout", "Timeout",
616           "Retry TCP transport after UDP timeout microseconds (0 = disabled)",
617           0, G_MAXUINT64, DEFAULT_TIMEOUT,
618           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
619 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
620   g_object_class_install_property (gobject_class, PROP_START_POSITION,
621       g_param_spec_uint64 ("pending-start-position", "set start position",
622           "Set start position before PLAYING request.",
623           0, G_MAXUINT64, DEFAULT_START_POSITION,
624           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
625   g_object_class_install_property (gobject_class, PROP_RESUME_POSITION,
626       g_param_spec_uint64 ("resume-position", "set resume position",
627           "Set resume position before PLAYING request after pause.",
628           0, G_MAXUINT64, DEFAULT_START_POSITION,
629           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
630 #endif
631   g_object_class_install_property (gobject_class, PROP_TCP_TIMEOUT,
632       g_param_spec_uint64 ("tcp-timeout", "TCP Timeout",
633           "Fail after timeout microseconds on TCP connections (0 = disabled)",
634           0, G_MAXUINT64, DEFAULT_TCP_TIMEOUT,
635           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
636
637   g_object_class_install_property (gobject_class, PROP_LATENCY,
638       g_param_spec_uint ("latency", "Buffer latency in ms",
639           "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS,
640           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
641
642   g_object_class_install_property (gobject_class, PROP_DROP_ON_LATENCY,
643       g_param_spec_boolean ("drop-on-latency",
644           "Drop buffers when maximum latency is reached",
645           "Tells the jitterbuffer to never exceed the given latency in size",
646           DEFAULT_DROP_ON_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
647
648   g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED,
649       g_param_spec_uint64 ("connection-speed", "Connection Speed",
650           "Network connection speed in kbps (0 = unknown)",
651           0, G_MAXUINT64 / 1000, DEFAULT_CONNECTION_SPEED,
652           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
653
654   g_object_class_install_property (gobject_class, PROP_NAT_METHOD,
655       g_param_spec_enum ("nat-method", "NAT Method",
656           "Method to use for traversing firewalls and NAT",
657           GST_TYPE_RTSP_NAT_METHOD, DEFAULT_NAT_METHOD,
658           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
659
660   /**
661    * GstRTSPSrc:do-rtcp:
662    *
663    * Enable RTCP support. Some old server don't like RTCP and then this property
664    * needs to be set to FALSE.
665    */
666   g_object_class_install_property (gobject_class, PROP_DO_RTCP,
667       g_param_spec_boolean ("do-rtcp", "Do RTCP",
668           "Send RTCP packets, disable for old incompatible server.",
669           DEFAULT_DO_RTCP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
670
671   /**
672    * GstRTSPSrc:do-rtsp-keep-alive:
673    *
674    * Enable RTSP keep alive support. Some old server don't like RTSP
675    * keep alive and then this property needs to be set to FALSE.
676    */
677   g_object_class_install_property (gobject_class, PROP_DO_RTSP_KEEP_ALIVE,
678       g_param_spec_boolean ("do-rtsp-keep-alive", "Do RTSP Keep Alive",
679           "Send RTSP keep alive packets, disable for old incompatible server.",
680           DEFAULT_DO_RTSP_KEEP_ALIVE,
681           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
682
683   /**
684    * GstRTSPSrc:proxy:
685    *
686    * Set the proxy parameters. This has to be a string of the format
687    * [http://][user:passwd@]host[:port].
688    */
689   g_object_class_install_property (gobject_class, PROP_PROXY,
690       g_param_spec_string ("proxy", "Proxy",
691           "Proxy settings for HTTP tunneling. Format: [http://][user:passwd@]host[:port]",
692           DEFAULT_PROXY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
693   /**
694    * GstRTSPSrc:proxy-id:
695    *
696    * Sets the proxy URI user id for authentication. If the URI set via the
697    * "proxy" property contains a user-id already, that will take precedence.
698    *
699    * Since: 1.2
700    */
701   g_object_class_install_property (gobject_class, PROP_PROXY_ID,
702       g_param_spec_string ("proxy-id", "proxy-id",
703           "HTTP proxy URI user id for authentication", "",
704           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
705   /**
706    * GstRTSPSrc:proxy-pw:
707    *
708    * Sets the proxy URI password for authentication. If the URI set via the
709    * "proxy" property contains a password already, that will take precedence.
710    *
711    * Since: 1.2
712    */
713   g_object_class_install_property (gobject_class, PROP_PROXY_PW,
714       g_param_spec_string ("proxy-pw", "proxy-pw",
715           "HTTP proxy URI user password for authentication", "",
716           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
717
718   /**
719    * GstRTSPSrc:rtp-blocksize:
720    *
721    * RTP package size to suggest to server.
722    */
723   g_object_class_install_property (gobject_class, PROP_RTP_BLOCKSIZE,
724       g_param_spec_uint ("rtp-blocksize", "RTP Blocksize",
725           "RTP package size to suggest to server (0 = disabled)",
726           0, 65536, DEFAULT_RTP_BLOCKSIZE,
727           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
728
729   g_object_class_install_property (gobject_class,
730       PROP_USER_ID,
731       g_param_spec_string ("user-id", "user-id",
732           "RTSP location URI user id for authentication", DEFAULT_USER_ID,
733           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
734   g_object_class_install_property (gobject_class, PROP_USER_PW,
735       g_param_spec_string ("user-pw", "user-pw",
736           "RTSP location URI user password for authentication", DEFAULT_USER_PW,
737           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
738
739   /**
740    * GstRTSPSrc:buffer-mode:
741    *
742    * Control the buffering and timestamping mode used by the jitterbuffer.
743    */
744   g_object_class_install_property (gobject_class, PROP_BUFFER_MODE,
745       g_param_spec_enum ("buffer-mode", "Buffer Mode",
746           "Control the buffering algorithm in use",
747           GST_TYPE_RTSP_SRC_BUFFER_MODE, DEFAULT_BUFFER_MODE,
748           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
749
750   /**
751    * GstRTSPSrc:port-range:
752    *
753    * Configure the client port numbers that can be used to receive RTP and
754    * RTCP.
755    */
756   g_object_class_install_property (gobject_class, PROP_PORT_RANGE,
757       g_param_spec_string ("port-range", "Port range",
758           "Client port range that can be used to receive RTP and RTCP data, "
759           "eg. 3000-3005 (NULL = no restrictions)", DEFAULT_PORT_RANGE,
760           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
761
762   /**
763    * GstRTSPSrc:udp-buffer-size:
764    *
765    * Size of the kernel UDP receive buffer in bytes.
766    */
767   g_object_class_install_property (gobject_class, PROP_UDP_BUFFER_SIZE,
768       g_param_spec_int ("udp-buffer-size", "UDP Buffer Size",
769           "Size of the kernel UDP receive buffer in bytes, 0=default",
770           0, G_MAXINT, DEFAULT_UDP_BUFFER_SIZE,
771           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
772
773   /**
774    * GstRTSPSrc:short-header:
775    *
776    * Only send the basic RTSP headers for broken encoders.
777    */
778   g_object_class_install_property (gobject_class, PROP_SHORT_HEADER,
779       g_param_spec_boolean ("short-header", "Short Header",
780           "Only send the basic RTSP headers for broken encoders",
781           DEFAULT_SHORT_HEADER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
782
783   g_object_class_install_property (gobject_class, PROP_PROBATION,
784       g_param_spec_uint ("probation", "Number of probations",
785           "Consecutive packet sequence numbers to accept the source",
786           0, G_MAXUINT, DEFAULT_PROBATION,
787           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
788
789   g_object_class_install_property (gobject_class, PROP_UDP_RECONNECT,
790       g_param_spec_boolean ("udp-reconnect", "Reconnect to the server",
791           "Reconnect to the server if RTSP connection is closed when doing UDP",
792           DEFAULT_UDP_RECONNECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
793
794   g_object_class_install_property (gobject_class, PROP_MULTICAST_IFACE,
795       g_param_spec_string ("multicast-iface", "Multicast Interface",
796           "The network interface on which to join the multicast group",
797           DEFAULT_MULTICAST_IFACE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
798
799   g_object_class_install_property (gobject_class, PROP_NTP_SYNC,
800       g_param_spec_boolean ("ntp-sync", "Sync on NTP clock",
801           "Synchronize received streams to the NTP clock", DEFAULT_NTP_SYNC,
802           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
803
804   g_object_class_install_property (gobject_class, PROP_USE_PIPELINE_CLOCK,
805       g_param_spec_boolean ("use-pipeline-clock", "Use pipeline clock",
806           "Use the pipeline running-time to set the NTP time in the RTCP SR messages"
807           "(DEPRECATED: Use ntp-time-source property)",
808           DEFAULT_USE_PIPELINE_CLOCK,
809           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
810
811   g_object_class_install_property (gobject_class, PROP_SDES,
812       g_param_spec_boxed ("sdes", "SDES",
813           "The SDES items of this session",
814           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
815
816   /**
817    * GstRTSPSrc::tls-validation-flags:
818    *
819    * TLS certificate validation flags used to validate server
820    * certificate.
821    *
822    * Since: 1.2.1
823    */
824   g_object_class_install_property (gobject_class, PROP_TLS_VALIDATION_FLAGS,
825       g_param_spec_flags ("tls-validation-flags", "TLS validation flags",
826           "TLS certificate validation flags used to validate the server certificate",
827           G_TYPE_TLS_CERTIFICATE_FLAGS, DEFAULT_TLS_VALIDATION_FLAGS,
828           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
829
830   /**
831    * GstRTSPSrc::tls-database:
832    *
833    * TLS database with anchor certificate authorities used to validate
834    * the server certificate.
835    *
836    * Since: 1.4
837    */
838   g_object_class_install_property (gobject_class, PROP_TLS_DATABASE,
839       g_param_spec_object ("tls-database", "TLS database",
840           "TLS database with anchor certificate authorities used to validate the server certificate",
841           G_TYPE_TLS_DATABASE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
842
843   /**
844    * GstRTSPSrc::tls-interaction:
845    *
846    * A #GTlsInteraction object to be used when the connection or certificate
847    * database need to interact with the user. This will be used to prompt the
848    * user for passwords where necessary.
849    *
850    * Since: 1.6
851    */
852   g_object_class_install_property (gobject_class, PROP_TLS_INTERACTION,
853       g_param_spec_object ("tls-interaction", "TLS interaction",
854           "A GTlsInteraction object to promt the user for password or certificate",
855           G_TYPE_TLS_INTERACTION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
856
857   /**
858    * GstRTSPSrc::do-retransmission:
859    *
860    * Attempt to ask the server to retransmit lost packets according to RFC4588.
861    *
862    * Note: currently only works with SSRC-multiplexed retransmission streams
863    *
864    * Since: 1.6
865    */
866   g_object_class_install_property (gobject_class, PROP_DO_RETRANSMISSION,
867       g_param_spec_boolean ("do-retransmission", "Retransmission",
868           "Ask the server to retransmit lost packets",
869           DEFAULT_DO_RETRANSMISSION,
870           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
871
872   /**
873    * GstRTSPSrc::ntp-time-source:
874    *
875    * allows to select the time source that should be used
876    * for the NTP time in RTCP packets
877    *
878    * Since: 1.6
879    */
880   g_object_class_install_property (gobject_class, PROP_NTP_TIME_SOURCE,
881       g_param_spec_enum ("ntp-time-source", "NTP Time Source",
882           "NTP time source for RTCP packets",
883           GST_TYPE_RTSP_SRC_NTP_TIME_SOURCE, DEFAULT_NTP_TIME_SOURCE,
884           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
885
886   /**
887    * GstRTSPSrc::user-agent:
888    *
889    * The string to set in the User-Agent header.
890    *
891    * Since: 1.6
892    */
893   g_object_class_install_property (gobject_class, PROP_USER_AGENT,
894       g_param_spec_string ("user-agent", "User Agent",
895           "The User-Agent string to send to the server",
896           DEFAULT_USER_AGENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
897
898   g_object_class_install_property (gobject_class, PROP_MAX_RTCP_RTP_TIME_DIFF,
899       g_param_spec_int ("max-rtcp-rtp-time-diff", "Max RTCP RTP Time Diff",
900           "Maximum amount of time in ms that the RTP time in RTCP SRs "
901           "is allowed to be ahead (-1 disabled)", -1, G_MAXINT,
902           DEFAULT_MAX_RTCP_RTP_TIME_DIFF,
903           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
904
905   g_object_class_install_property (gobject_class, PROP_RFC7273_SYNC,
906       g_param_spec_boolean ("rfc7273-sync", "Sync on RFC7273 clock",
907           "Synchronize received streams to the RFC7273 clock "
908           "(requires clock and offset to be provided)", DEFAULT_RFC7273_SYNC,
909           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
910
911   /**
912    * GstRTSPSrc:default-rtsp-version:
913    *
914    * The preferred RTSP version to use while negotiating the version with the server.
915    *
916    * Since: 1.14
917    */
918   g_object_class_install_property (gobject_class, PROP_DEFAULT_VERSION,
919       g_param_spec_enum ("default-rtsp-version",
920           "The RTSP version to try first",
921           "The RTSP version that should be tried first when negotiating version.",
922           GST_TYPE_RTSP_VERSION, DEFAULT_VERSION,
923           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
924
925   /**
926    * GstRTSPSrc:max-ts-offset-adjustment:
927    *
928    * Syncing time stamps to NTP time adds a time offset. This parameter
929    * specifies the maximum number of nanoseconds per frame that this time offset
930    * may be adjusted with. This is used to avoid sudden large changes to time
931    * stamps.
932    */
933   g_object_class_install_property (gobject_class, PROP_MAX_TS_OFFSET_ADJUSTMENT,
934       g_param_spec_uint64 ("max-ts-offset-adjustment",
935           "Max Timestamp Offset Adjustment",
936           "The maximum number of nanoseconds per frame that time stamp offsets "
937           "may be adjusted (0 = no limit).", 0, G_MAXUINT64,
938           DEFAULT_MAX_TS_OFFSET_ADJUSTMENT, G_PARAM_READWRITE |
939           G_PARAM_STATIC_STRINGS));
940
941   /**
942    * GstRTSPSrc:max-ts-offset:
943    *
944    * Used to set an upper limit of how large a time offset may be. This
945    * is used to protect against unrealistic values as a result of either
946    * client,server or clock issues.
947    */
948   g_object_class_install_property (gobject_class, PROP_MAX_TS_OFFSET,
949       g_param_spec_int64 ("max-ts-offset", "Max TS Offset",
950           "The maximum absolute value of the time offset in (nanoseconds). "
951           "Note, if the ntp-sync parameter is set the default value is "
952           "changed to 0 (no limit)", 0, G_MAXINT64, DEFAULT_MAX_TS_OFFSET,
953           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
954
955   /**
956    * GstRTSPSrc:backchannel
957    *
958    * Select a type of backchannel to setup with the RTSP server.
959    * Default value is "none". Allowed values are "none" and "onvif".
960    *
961    * Since: 1.14
962    */
963   g_object_class_install_property (gobject_class, PROP_BACKCHANNEL,
964       g_param_spec_enum ("backchannel", "Backchannel type",
965           "The type of backchannel to setup. Default is 'none'.",
966           GST_TYPE_RTSP_BACKCHANNEL, BACKCHANNEL_NONE,
967           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
968
969   /**
970    * GstRtspSrc:teardown-timeout
971    *
972    * When transitioning PAUSED-READY, allow up to timeout (in nanoseconds)
973    * delay in order to send teardown (0 = disabled)
974    *
975    * Since: 1.14
976    */
977   g_object_class_install_property (gobject_class, PROP_TEARDOWN_TIMEOUT,
978       g_param_spec_uint64 ("teardown-timeout", "Teardown Timeout",
979           "When transitioning PAUSED-READY, allow up to timeout (in nanoseconds) "
980           "delay in order to send teardown (0 = disabled)",
981           0, G_MAXUINT64, DEFAULT_TEARDOWN_TIMEOUT,
982           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
983
984   /**
985    * GstRTSPSrc::handle-request:
986    * @rtspsrc: a #GstRTSPSrc
987    * @request: a #GstRTSPMessage
988    * @response: a #GstRTSPMessage
989    *
990    * Handle a server request in @request and prepare @response.
991    *
992    * This signal is called from the streaming thread, you should therefore not
993    * do any state changes on @rtspsrc because this might deadlock. If you want
994    * to modify the state as a result of this signal, post a
995    * #GST_MESSAGE_REQUEST_STATE message on the bus or signal the main thread
996    * in some other way.
997    *
998    * Since: 1.2
999    */
1000   gst_rtspsrc_signals[SIGNAL_HANDLE_REQUEST] =
1001       g_signal_new ("handle-request", G_TYPE_FROM_CLASS (klass), 0,
1002       0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2,
1003       G_TYPE_POINTER, G_TYPE_POINTER);
1004
1005   /**
1006    * GstRTSPSrc::on-sdp:
1007    * @rtspsrc: a #GstRTSPSrc
1008    * @sdp: a #GstSDPMessage
1009    *
1010    * Emitted when the client has retrieved the SDP and before it configures the
1011    * streams in the SDP. @sdp can be inspected and modified.
1012    *
1013    * This signal is called from the streaming thread, you should therefore not
1014    * do any state changes on @rtspsrc because this might deadlock. If you want
1015    * to modify the state as a result of this signal, post a
1016    * #GST_MESSAGE_REQUEST_STATE message on the bus or signal the main thread
1017    * in some other way.
1018    *
1019    * Since: 1.2
1020    */
1021   gst_rtspsrc_signals[SIGNAL_ON_SDP] =
1022       g_signal_new ("on-sdp", G_TYPE_FROM_CLASS (klass), 0,
1023       0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
1024       GST_TYPE_SDP_MESSAGE | G_SIGNAL_TYPE_STATIC_SCOPE);
1025
1026   /**
1027    * GstRTSPSrc::select-stream:
1028    * @rtspsrc: a #GstRTSPSrc
1029    * @num: the stream number
1030    * @caps: the stream caps
1031    *
1032    * Emitted before the client decides to configure the stream @num with
1033    * @caps.
1034    *
1035    * Returns: %TRUE when the stream should be selected, %FALSE when the stream
1036    * is to be ignored.
1037    *
1038    * Since: 1.2
1039    */
1040   gst_rtspsrc_signals[SIGNAL_SELECT_STREAM] =
1041       g_signal_new_class_handler ("select-stream", G_TYPE_FROM_CLASS (klass),
1042       G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_CLEANUP,
1043       (GCallback) default_select_stream, select_stream_accum, NULL,
1044       g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 2, G_TYPE_UINT,
1045       GST_TYPE_CAPS);
1046   /**
1047    * GstRTSPSrc::new-manager:
1048    * @rtspsrc: a #GstRTSPSrc
1049    * @manager: a #GstElement
1050    *
1051    * Emitted after a new manager (like rtpbin) was created and the default
1052    * properties were configured.
1053    *
1054    * Since: 1.4
1055    */
1056   gst_rtspsrc_signals[SIGNAL_NEW_MANAGER] =
1057       g_signal_new_class_handler ("new-manager", G_TYPE_FROM_CLASS (klass),
1058       G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_CLEANUP, 0, NULL, NULL,
1059       g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
1060
1061   /**
1062    * GstRTSPSrc::request-rtcp-key:
1063    * @rtspsrc: a #GstRTSPSrc
1064    * @num: the stream number
1065    *
1066    * Signal emitted to get the crypto parameters relevant to the RTCP
1067    * stream. User should provide the key and the RTCP encryption ciphers
1068    * and authentication, and return them wrapped in a GstCaps.
1069    *
1070    * Since: 1.4
1071    */
1072   gst_rtspsrc_signals[SIGNAL_REQUEST_RTCP_KEY] =
1073       g_signal_new ("request-rtcp-key", G_TYPE_FROM_CLASS (klass),
1074       G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_CAPS, 1, G_TYPE_UINT);
1075
1076   /**
1077    * GstRTSPSrc::accept-certificate:
1078    * @rtspsrc: a #GstRTSPSrc
1079    * @peer_cert: the peer's #GTlsCertificate
1080    * @errors: the problems with @peer_cert
1081    * @user_data: user data set when the signal handler was connected.
1082    *
1083    * This will directly map to #GTlsConnection 's "accept-certificate"
1084    * signal and be performed after the default checks of #GstRTSPConnection
1085    * (checking against the #GTlsDatabase with the given #GTlsCertificateFlags)
1086    * have failed. If no #GTlsDatabase is set on this connection, only this
1087    * signal will be emitted.
1088    *
1089    * Since: 1.14
1090    */
1091   gst_rtspsrc_signals[SIGNAL_ACCEPT_CERTIFICATE] =
1092       g_signal_new ("accept-certificate", G_TYPE_FROM_CLASS (klass),
1093       G_SIGNAL_RUN_LAST, 0, g_signal_accumulator_true_handled, NULL, NULL,
1094       G_TYPE_BOOLEAN, 3, G_TYPE_TLS_CONNECTION, G_TYPE_TLS_CERTIFICATE,
1095       G_TYPE_TLS_CERTIFICATE_FLAGS);
1096
1097   /*
1098    * GstRTSPSrc::before-send
1099    * @rtspsrc: a #GstRTSPSrc
1100    * @num: the stream number
1101    *
1102    * Emitted before each RTSP request is sent, in order to allow
1103    * the application to modify send parameters or to skip the message entirely.
1104    * This can be used, for example, to work with ONVIF Profile G servers,
1105    * which need a different/additional range, rate-control, and intra/x
1106    * parameters.
1107    *
1108    * Returns: %TRUE when the command should be sent, %FALSE when the
1109    * command should be dropped.
1110    *
1111    * Since: 1.14
1112    */
1113   gst_rtspsrc_signals[SIGNAL_BEFORE_SEND] =
1114       g_signal_new_class_handler ("before-send", G_TYPE_FROM_CLASS (klass),
1115       G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_CLEANUP,
1116       (GCallback) default_before_send, before_send_accum, NULL,
1117       g_cclosure_marshal_generic, G_TYPE_BOOLEAN,
1118       1, GST_TYPE_RTSP_MESSAGE | G_SIGNAL_TYPE_STATIC_SCOPE);
1119
1120   /**
1121    * GstRTSPSrc::push-backchannel-buffer:
1122    * @rtspsrc: a #GstRTSPSrc
1123    * @buffer: RTP buffer to send back
1124    *
1125    *
1126    */
1127   gst_rtspsrc_signals[SIGNAL_PUSH_BACKCHANNEL_BUFFER] =
1128       g_signal_new ("push-backchannel-buffer", G_TYPE_FROM_CLASS (klass),
1129       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRTSPSrcClass,
1130           push_backchannel_buffer), NULL, NULL, NULL, GST_TYPE_FLOW_RETURN, 2,
1131       G_TYPE_UINT, GST_TYPE_BUFFER);
1132
1133   /**
1134    * GstRTSPSrc::get-parameter:
1135    * @rtspsrc: a #GstRTSPSrc
1136    * @parameter: the parameter name
1137    * @parameter: the content type
1138    * @parameter: a pointer to #GstPromise
1139    *
1140    * Handle the GET_PARAMETER signal.
1141    *
1142    * Returns: %TRUE when the command could be issued, %FALSE otherwise
1143    *
1144    */
1145   gst_rtspsrc_signals[SIGNAL_GET_PARAMETER] =
1146       g_signal_new ("get-parameter", G_TYPE_FROM_CLASS (klass),
1147       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRTSPSrcClass,
1148           get_parameter), NULL, NULL, g_cclosure_marshal_generic,
1149       G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_STRING, GST_TYPE_PROMISE);
1150
1151   /**
1152    * GstRTSPSrc::get-parameters:
1153    * @rtspsrc: a #GstRTSPSrc
1154    * @parameter: a NULL-terminated array of parameters
1155    * @parameter: the content type
1156    * @parameter: a pointer to #GstPromise
1157    *
1158    * Handle the GET_PARAMETERS signal.
1159    *
1160    * Returns: %TRUE when the command could be issued, %FALSE otherwise
1161    *
1162    */
1163   gst_rtspsrc_signals[SIGNAL_GET_PARAMETERS] =
1164       g_signal_new ("get-parameters", G_TYPE_FROM_CLASS (klass),
1165       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRTSPSrcClass,
1166           get_parameters), NULL, NULL, g_cclosure_marshal_generic,
1167       G_TYPE_BOOLEAN, 3, G_TYPE_STRV, G_TYPE_STRING, GST_TYPE_PROMISE);
1168
1169   /**
1170    * GstRTSPSrc::set-parameter:
1171    * @rtspsrc: a #GstRTSPSrc
1172    * @parameter: the parameter name
1173    * @parameter: the parameter value
1174    * @parameter: the content type
1175    * @parameter: a pointer to #GstPromise
1176    *
1177    * Handle the SET_PARAMETER signal.
1178    *
1179    * Returns: %TRUE when the command could be issued, %FALSE otherwise
1180    *
1181    */
1182   gst_rtspsrc_signals[SIGNAL_SET_PARAMETER] =
1183       g_signal_new ("set-parameter", G_TYPE_FROM_CLASS (klass),
1184       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRTSPSrcClass,
1185           set_parameter), NULL, NULL, g_cclosure_marshal_generic,
1186       G_TYPE_BOOLEAN, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
1187       GST_TYPE_PROMISE);
1188
1189   gstelement_class->send_event = gst_rtspsrc_send_event;
1190   gstelement_class->provide_clock = gst_rtspsrc_provide_clock;
1191   gstelement_class->change_state = gst_rtspsrc_change_state;
1192
1193   gst_element_class_add_static_pad_template (gstelement_class, &rtptemplate);
1194
1195   gst_element_class_set_static_metadata (gstelement_class,
1196       "RTSP packet receiver", "Source/Network",
1197       "Receive data over the network via RTSP (RFC 2326)",
1198       "Wim Taymans <wim@fluendo.com>, "
1199       "Thijs Vermeir <thijs.vermeir@barco.com>, "
1200       "Lutz Mueller <lutz@topfrose.de>");
1201
1202   gstbin_class->handle_message = gst_rtspsrc_handle_message;
1203
1204   klass->push_backchannel_buffer = gst_rtspsrc_push_backchannel_buffer;
1205   klass->get_parameter = GST_DEBUG_FUNCPTR (get_parameter);
1206   klass->get_parameters = GST_DEBUG_FUNCPTR (get_parameters);
1207   klass->set_parameter = GST_DEBUG_FUNCPTR (set_parameter);
1208
1209   gst_rtsp_ext_list_init ();
1210 }
1211
1212 static gboolean
1213 validate_set_get_parameter_name (const gchar * parameter_name)
1214 {
1215   gchar *ptr = (gchar *) parameter_name;
1216
1217   while (*ptr) {
1218     /* Don't allow '\r', '\n', \'t', ' ' etc in the parameter name */
1219     if (g_ascii_isspace (*ptr) || g_ascii_iscntrl (*ptr)) {
1220       GST_DEBUG ("invalid parameter name '%s'", parameter_name);
1221       return FALSE;
1222     }
1223     ptr++;
1224   }
1225   return TRUE;
1226 }
1227
1228 static gboolean
1229 validate_set_get_parameters (gchar ** parameter_names)
1230 {
1231   while (*parameter_names) {
1232     if (!validate_set_get_parameter_name (*parameter_names)) {
1233       return FALSE;
1234     }
1235     parameter_names++;
1236   }
1237   return TRUE;
1238 }
1239
1240 static gboolean
1241 get_parameter (GstRTSPSrc * src, const gchar * parameter,
1242     const gchar * content_type, GstPromise * promise)
1243 {
1244   gchar *parameters[] = { (gchar *) parameter, NULL };
1245
1246   GST_LOG_OBJECT (src, "get_parameter: %s", GST_STR_NULL (parameter));
1247
1248   if (parameter == NULL || parameter[0] == '\0' || promise == NULL) {
1249     GST_DEBUG ("invalid input");
1250     return FALSE;
1251   }
1252
1253   return get_parameters (src, parameters, content_type, promise);
1254 }
1255
1256 static gboolean
1257 get_parameters (GstRTSPSrc * src, gchar ** parameters,
1258     const gchar * content_type, GstPromise * promise)
1259 {
1260   ParameterRequest *req;
1261
1262   GST_LOG_OBJECT (src, "get_parameters: %d", g_strv_length (parameters));
1263
1264   if (parameters == NULL || promise == NULL) {
1265     GST_DEBUG ("invalid input");
1266     return FALSE;
1267   }
1268
1269   if (src->state == GST_RTSP_STATE_INVALID) {
1270     GST_DEBUG ("invalid state");
1271     return FALSE;
1272   }
1273
1274   if (!validate_set_get_parameters (parameters)) {
1275     return FALSE;
1276   }
1277
1278   req = g_new0 (ParameterRequest, 1);
1279   req->promise = gst_promise_ref (promise);
1280   req->cmd = CMD_GET_PARAMETER;
1281   /* Set the request body according to RFC 2326 or RFC 7826 */
1282   req->body = g_string_new (NULL);
1283   while (*parameters) {
1284     g_string_append_printf (req->body, "%s:\r\n", *parameters);
1285     parameters++;
1286   }
1287   if (content_type)
1288     req->content_type = g_strdup (content_type);
1289
1290   GST_OBJECT_LOCK (src);
1291   g_queue_push_tail (&src->set_get_param_q, req);
1292   GST_OBJECT_UNLOCK (src);
1293
1294   gst_rtspsrc_loop_send_cmd (src, CMD_GET_PARAMETER, CMD_LOOP);
1295
1296   return TRUE;
1297 }
1298
1299 static gboolean
1300 set_parameter (GstRTSPSrc * src, const gchar * name, const gchar * value,
1301     const gchar * content_type, GstPromise * promise)
1302 {
1303   ParameterRequest *req;
1304
1305   GST_LOG_OBJECT (src, "set_parameter: %s: %s", GST_STR_NULL (name),
1306       GST_STR_NULL (value));
1307
1308   if (name == NULL || name[0] == '\0' || value == NULL || promise == NULL) {
1309     GST_DEBUG ("invalid input");
1310     return FALSE;
1311   }
1312
1313   if (src->state == GST_RTSP_STATE_INVALID) {
1314     GST_DEBUG ("invalid state");
1315     return FALSE;
1316   }
1317
1318   if (!validate_set_get_parameter_name (name)) {
1319     return FALSE;
1320   }
1321
1322   req = g_new0 (ParameterRequest, 1);
1323   req->cmd = CMD_SET_PARAMETER;
1324   req->promise = gst_promise_ref (promise);
1325   req->body = g_string_new (NULL);
1326   /* Set the request body according to RFC 2326 or RFC 7826 */
1327   g_string_append_printf (req->body, "%s: %s\r\n", name, value);
1328   if (content_type)
1329     req->content_type = g_strdup (content_type);
1330
1331   GST_OBJECT_LOCK (src);
1332   g_queue_push_tail (&src->set_get_param_q, req);
1333   GST_OBJECT_UNLOCK (src);
1334
1335   gst_rtspsrc_loop_send_cmd (src, CMD_SET_PARAMETER, CMD_LOOP);
1336
1337   return TRUE;
1338 }
1339
1340 static void
1341 gst_rtspsrc_init (GstRTSPSrc * src)
1342 {
1343   src->conninfo.location = g_strdup (DEFAULT_LOCATION);
1344   src->protocols = DEFAULT_PROTOCOLS;
1345   src->debug = DEFAULT_DEBUG;
1346   src->retry = DEFAULT_RETRY;
1347   src->udp_timeout = DEFAULT_TIMEOUT;
1348 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1349   src->start_position = DEFAULT_START_POSITION;
1350   src->is_audio_codec_supported = FALSE;
1351   src->is_video_codec_supported = FALSE;
1352   src->audio_codec = NULL;
1353   src->video_codec = NULL;
1354   src->video_frame_size = NULL;
1355 #endif
1356   gst_rtspsrc_set_tcp_timeout (src, DEFAULT_TCP_TIMEOUT);
1357   src->latency = DEFAULT_LATENCY_MS;
1358   src->drop_on_latency = DEFAULT_DROP_ON_LATENCY;
1359   src->connection_speed = DEFAULT_CONNECTION_SPEED;
1360   src->nat_method = DEFAULT_NAT_METHOD;
1361   src->do_rtcp = DEFAULT_DO_RTCP;
1362   src->do_rtsp_keep_alive = DEFAULT_DO_RTSP_KEEP_ALIVE;
1363   gst_rtspsrc_set_proxy (src, DEFAULT_PROXY);
1364   src->rtp_blocksize = DEFAULT_RTP_BLOCKSIZE;
1365   src->user_id = g_strdup (DEFAULT_USER_ID);
1366   src->user_pw = g_strdup (DEFAULT_USER_PW);
1367   src->buffer_mode = DEFAULT_BUFFER_MODE;
1368   src->client_port_range.min = 0;
1369   src->client_port_range.max = 0;
1370   src->udp_buffer_size = DEFAULT_UDP_BUFFER_SIZE;
1371   src->short_header = DEFAULT_SHORT_HEADER;
1372   src->probation = DEFAULT_PROBATION;
1373   src->udp_reconnect = DEFAULT_UDP_RECONNECT;
1374   src->multi_iface = g_strdup (DEFAULT_MULTICAST_IFACE);
1375   src->ntp_sync = DEFAULT_NTP_SYNC;
1376   src->use_pipeline_clock = DEFAULT_USE_PIPELINE_CLOCK;
1377   src->sdes = NULL;
1378   src->tls_validation_flags = DEFAULT_TLS_VALIDATION_FLAGS;
1379   src->tls_database = DEFAULT_TLS_DATABASE;
1380   src->tls_interaction = DEFAULT_TLS_INTERACTION;
1381   src->do_retransmission = DEFAULT_DO_RETRANSMISSION;
1382   src->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
1383   src->user_agent = g_strdup (DEFAULT_USER_AGENT);
1384   src->max_rtcp_rtp_time_diff = DEFAULT_MAX_RTCP_RTP_TIME_DIFF;
1385   src->rfc7273_sync = DEFAULT_RFC7273_SYNC;
1386   src->max_ts_offset_adjustment = DEFAULT_MAX_TS_OFFSET_ADJUSTMENT;
1387   src->max_ts_offset = DEFAULT_MAX_TS_OFFSET;
1388   src->max_ts_offset_is_set = FALSE;
1389   src->default_version = DEFAULT_VERSION;
1390   src->version = GST_RTSP_VERSION_INVALID;
1391   src->teardown_timeout = DEFAULT_TEARDOWN_TIMEOUT;
1392
1393 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1394   g_mutex_init (&(src)->pause_lock);
1395   g_cond_init (&(src)->open_end);
1396 #endif
1397   /* get a list of all extensions */
1398   src->extensions = gst_rtsp_ext_list_get ();
1399
1400   /* connect to send signal */
1401   gst_rtsp_ext_list_connect (src->extensions, "send",
1402       (GCallback) gst_rtspsrc_send_cb, src);
1403
1404   /* protects the streaming thread in interleaved mode or the polling
1405    * thread in UDP mode. */
1406   g_rec_mutex_init (&src->stream_rec_lock);
1407
1408   /* protects our state changes from multiple invocations */
1409   g_rec_mutex_init (&src->state_rec_lock);
1410
1411   g_queue_init (&src->set_get_param_q);
1412
1413   src->state = GST_RTSP_STATE_INVALID;
1414
1415   g_mutex_init (&src->conninfo.send_lock);
1416   g_mutex_init (&src->conninfo.recv_lock);
1417   g_cond_init (&src->cmd_cond);
1418
1419   GST_OBJECT_FLAG_SET (src, GST_ELEMENT_FLAG_SOURCE);
1420   gst_bin_set_suppressed_flags (GST_BIN (src),
1421       GST_ELEMENT_FLAG_SOURCE | GST_ELEMENT_FLAG_SINK);
1422 }
1423
1424 static void
1425 free_param_data (ParameterRequest * req)
1426 {
1427   gst_promise_unref (req->promise);
1428   if (req->body)
1429     g_string_free (req->body, TRUE);
1430   g_free (req->content_type);
1431   g_free (req);
1432 }
1433
1434 static void
1435 free_param_queue (gpointer data)
1436 {
1437   ParameterRequest *req = data;
1438
1439   gst_promise_expire (req->promise);
1440   free_param_data (req);
1441 }
1442
1443 static void
1444 gst_rtspsrc_finalize (GObject * object)
1445 {
1446   GstRTSPSrc *rtspsrc;
1447
1448   rtspsrc = GST_RTSPSRC (object);
1449
1450 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1451   rtspsrc->is_audio_codec_supported = FALSE;
1452   rtspsrc->is_video_codec_supported = FALSE;
1453   if (rtspsrc->audio_codec) {
1454     g_free (rtspsrc->audio_codec);
1455     rtspsrc->audio_codec = NULL;
1456   }
1457   if (rtspsrc->video_codec) {
1458     g_free (rtspsrc->video_codec);
1459     rtspsrc->video_codec = NULL;
1460   }
1461   if (rtspsrc->video_frame_size) {
1462     g_free (rtspsrc->video_frame_size);
1463     rtspsrc->video_frame_size = NULL;
1464   }
1465 #endif
1466   gst_rtsp_ext_list_free (rtspsrc->extensions);
1467   g_free (rtspsrc->conninfo.location);
1468   gst_rtsp_url_free (rtspsrc->conninfo.url);
1469   g_free (rtspsrc->conninfo.url_str);
1470   g_free (rtspsrc->user_id);
1471   g_free (rtspsrc->user_pw);
1472   g_free (rtspsrc->multi_iface);
1473   g_free (rtspsrc->user_agent);
1474
1475 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1476   g_mutex_clear (&(rtspsrc)->pause_lock);
1477   g_cond_clear (&(rtspsrc)->open_end);
1478 #endif
1479
1480   if (rtspsrc->sdp) {
1481     gst_sdp_message_free (rtspsrc->sdp);
1482     rtspsrc->sdp = NULL;
1483   }
1484   if (rtspsrc->provided_clock)
1485     gst_object_unref (rtspsrc->provided_clock);
1486
1487   if (rtspsrc->sdes)
1488     gst_structure_free (rtspsrc->sdes);
1489
1490   if (rtspsrc->tls_database)
1491     g_object_unref (rtspsrc->tls_database);
1492
1493   if (rtspsrc->tls_interaction)
1494     g_object_unref (rtspsrc->tls_interaction);
1495
1496   /* free locks */
1497   g_rec_mutex_clear (&rtspsrc->stream_rec_lock);
1498   g_rec_mutex_clear (&rtspsrc->state_rec_lock);
1499
1500   g_mutex_clear (&rtspsrc->conninfo.send_lock);
1501   g_mutex_clear (&rtspsrc->conninfo.recv_lock);
1502   g_cond_clear (&rtspsrc->cmd_cond);
1503
1504   G_OBJECT_CLASS (parent_class)->finalize (object);
1505 }
1506
1507 static GstClock *
1508 gst_rtspsrc_provide_clock (GstElement * element)
1509 {
1510   GstRTSPSrc *src = GST_RTSPSRC (element);
1511   GstClock *clock;
1512
1513   if ((clock = src->provided_clock) != NULL)
1514     return gst_object_ref (clock);
1515
1516   return GST_ELEMENT_CLASS (parent_class)->provide_clock (element);
1517 }
1518
1519 /* a proxy string of the format [user:passwd@]host[:port] */
1520 static gboolean
1521 gst_rtspsrc_set_proxy (GstRTSPSrc * rtsp, const gchar * proxy)
1522 {
1523   gchar *p, *at, *col;
1524
1525   g_free (rtsp->proxy_user);
1526   rtsp->proxy_user = NULL;
1527   g_free (rtsp->proxy_passwd);
1528   rtsp->proxy_passwd = NULL;
1529   g_free (rtsp->proxy_host);
1530   rtsp->proxy_host = NULL;
1531   rtsp->proxy_port = 0;
1532
1533   p = (gchar *) proxy;
1534
1535   if (p == NULL)
1536     return TRUE;
1537
1538   /* we allow http:// in front but ignore it */
1539   if (g_str_has_prefix (p, "http://"))
1540     p += 7;
1541
1542   at = strchr (p, '@');
1543   if (at) {
1544     /* look for user:passwd */
1545     col = strchr (proxy, ':');
1546     if (col == NULL || col > at)
1547       return FALSE;
1548
1549     rtsp->proxy_user = g_strndup (p, col - p);
1550     col++;
1551     rtsp->proxy_passwd = g_strndup (col, at - col);
1552
1553     /* move to host */
1554     p = at + 1;
1555   } else {
1556     if (rtsp->prop_proxy_id != NULL && *rtsp->prop_proxy_id != '\0')
1557       rtsp->proxy_user = g_strdup (rtsp->prop_proxy_id);
1558     if (rtsp->prop_proxy_pw != NULL && *rtsp->prop_proxy_pw != '\0')
1559       rtsp->proxy_passwd = g_strdup (rtsp->prop_proxy_pw);
1560     if (rtsp->proxy_user != NULL || rtsp->proxy_passwd != NULL) {
1561       GST_LOG_OBJECT (rtsp, "set proxy user/pw from properties: %s:%s",
1562           GST_STR_NULL (rtsp->proxy_user), GST_STR_NULL (rtsp->proxy_passwd));
1563     }
1564   }
1565   col = strchr (p, ':');
1566
1567   if (col) {
1568     /* everything before the colon is the hostname */
1569     rtsp->proxy_host = g_strndup (p, col - p);
1570     p = col + 1;
1571     rtsp->proxy_port = strtoul (p, (char **) &p, 10);
1572   } else {
1573     rtsp->proxy_host = g_strdup (p);
1574     rtsp->proxy_port = 8080;
1575   }
1576   return TRUE;
1577 }
1578
1579 static void
1580 gst_rtspsrc_set_tcp_timeout (GstRTSPSrc * rtspsrc, guint64 timeout)
1581 {
1582   rtspsrc->tcp_timeout.tv_sec = timeout / G_USEC_PER_SEC;
1583   rtspsrc->tcp_timeout.tv_usec = timeout % G_USEC_PER_SEC;
1584
1585   if (timeout != 0)
1586     rtspsrc->ptcp_timeout = &rtspsrc->tcp_timeout;
1587   else
1588     rtspsrc->ptcp_timeout = NULL;
1589 }
1590
1591 static void
1592 gst_rtspsrc_set_property (GObject * object, guint prop_id, const GValue * value,
1593     GParamSpec * pspec)
1594 {
1595   GstRTSPSrc *rtspsrc;
1596
1597   rtspsrc = GST_RTSPSRC (object);
1598
1599   switch (prop_id) {
1600     case PROP_LOCATION:
1601       gst_rtspsrc_uri_set_uri (GST_URI_HANDLER (rtspsrc),
1602           g_value_get_string (value), NULL);
1603       break;
1604     case PROP_PROTOCOLS:
1605       rtspsrc->protocols = g_value_get_flags (value);
1606       break;
1607     case PROP_DEBUG:
1608       rtspsrc->debug = g_value_get_boolean (value);
1609       break;
1610     case PROP_RETRY:
1611       rtspsrc->retry = g_value_get_uint (value);
1612       break;
1613     case PROP_TIMEOUT:
1614       rtspsrc->udp_timeout = g_value_get_uint64 (value);
1615       break;
1616 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1617     case PROP_START_POSITION:
1618       rtspsrc->start_position = g_value_get_uint64 (value);
1619       break;
1620     case PROP_RESUME_POSITION:
1621       rtspsrc->last_pos = g_value_get_uint64 (value);
1622       GST_DEBUG_OBJECT (rtspsrc, "src->last_pos value set to %" GST_TIME_FORMAT,
1623           GST_TIME_ARGS (rtspsrc->last_pos));
1624       break;
1625 #endif
1626     case PROP_TCP_TIMEOUT:
1627       gst_rtspsrc_set_tcp_timeout (rtspsrc, g_value_get_uint64 (value));
1628       break;
1629     case PROP_LATENCY:
1630       rtspsrc->latency = g_value_get_uint (value);
1631       break;
1632     case PROP_DROP_ON_LATENCY:
1633       rtspsrc->drop_on_latency = g_value_get_boolean (value);
1634       break;
1635     case PROP_CONNECTION_SPEED:
1636       rtspsrc->connection_speed = g_value_get_uint64 (value);
1637       break;
1638     case PROP_NAT_METHOD:
1639       rtspsrc->nat_method = g_value_get_enum (value);
1640       break;
1641     case PROP_DO_RTCP:
1642       rtspsrc->do_rtcp = g_value_get_boolean (value);
1643       break;
1644     case PROP_DO_RTSP_KEEP_ALIVE:
1645       rtspsrc->do_rtsp_keep_alive = g_value_get_boolean (value);
1646       break;
1647     case PROP_PROXY:
1648       gst_rtspsrc_set_proxy (rtspsrc, g_value_get_string (value));
1649       break;
1650     case PROP_PROXY_ID:
1651       g_free (rtspsrc->prop_proxy_id);
1652       rtspsrc->prop_proxy_id = g_value_dup_string (value);
1653       break;
1654     case PROP_PROXY_PW:
1655       g_free (rtspsrc->prop_proxy_pw);
1656       rtspsrc->prop_proxy_pw = g_value_dup_string (value);
1657       break;
1658     case PROP_RTP_BLOCKSIZE:
1659       rtspsrc->rtp_blocksize = g_value_get_uint (value);
1660       break;
1661     case PROP_USER_ID:
1662       g_free (rtspsrc->user_id);
1663       rtspsrc->user_id = g_value_dup_string (value);
1664       break;
1665     case PROP_USER_PW:
1666       g_free (rtspsrc->user_pw);
1667       rtspsrc->user_pw = g_value_dup_string (value);
1668       break;
1669     case PROP_BUFFER_MODE:
1670       rtspsrc->buffer_mode = g_value_get_enum (value);
1671       break;
1672     case PROP_PORT_RANGE:
1673     {
1674       const gchar *str;
1675
1676       str = g_value_get_string (value);
1677       if (str == NULL || sscanf (str, "%u-%u", &rtspsrc->client_port_range.min,
1678               &rtspsrc->client_port_range.max) != 2) {
1679         rtspsrc->client_port_range.min = 0;
1680         rtspsrc->client_port_range.max = 0;
1681       }
1682       break;
1683     }
1684     case PROP_UDP_BUFFER_SIZE:
1685       rtspsrc->udp_buffer_size = g_value_get_int (value);
1686       break;
1687     case PROP_SHORT_HEADER:
1688       rtspsrc->short_header = g_value_get_boolean (value);
1689       break;
1690     case PROP_PROBATION:
1691       rtspsrc->probation = g_value_get_uint (value);
1692       break;
1693     case PROP_UDP_RECONNECT:
1694       rtspsrc->udp_reconnect = g_value_get_boolean (value);
1695       break;
1696     case PROP_MULTICAST_IFACE:
1697       g_free (rtspsrc->multi_iface);
1698
1699       if (g_value_get_string (value) == NULL)
1700         rtspsrc->multi_iface = g_strdup (DEFAULT_MULTICAST_IFACE);
1701       else
1702         rtspsrc->multi_iface = g_value_dup_string (value);
1703       break;
1704     case PROP_NTP_SYNC:
1705       rtspsrc->ntp_sync = g_value_get_boolean (value);
1706       /* The default value of max_ts_offset depends on ntp_sync. If user
1707        * hasn't set it then change default value */
1708       if (!rtspsrc->max_ts_offset_is_set) {
1709         if (rtspsrc->ntp_sync) {
1710           rtspsrc->max_ts_offset = 0;
1711         } else {
1712           rtspsrc->max_ts_offset = DEFAULT_MAX_TS_OFFSET;
1713         }
1714       }
1715       break;
1716     case PROP_USE_PIPELINE_CLOCK:
1717       rtspsrc->use_pipeline_clock = g_value_get_boolean (value);
1718       break;
1719     case PROP_SDES:
1720       rtspsrc->sdes = g_value_dup_boxed (value);
1721       break;
1722     case PROP_TLS_VALIDATION_FLAGS:
1723       rtspsrc->tls_validation_flags = g_value_get_flags (value);
1724       break;
1725     case PROP_TLS_DATABASE:
1726       g_clear_object (&rtspsrc->tls_database);
1727       rtspsrc->tls_database = g_value_dup_object (value);
1728       break;
1729     case PROP_TLS_INTERACTION:
1730       g_clear_object (&rtspsrc->tls_interaction);
1731       rtspsrc->tls_interaction = g_value_dup_object (value);
1732       break;
1733     case PROP_DO_RETRANSMISSION:
1734       rtspsrc->do_retransmission = g_value_get_boolean (value);
1735       break;
1736     case PROP_NTP_TIME_SOURCE:
1737       rtspsrc->ntp_time_source = g_value_get_enum (value);
1738       break;
1739     case PROP_USER_AGENT:
1740       g_free (rtspsrc->user_agent);
1741       rtspsrc->user_agent = g_value_dup_string (value);
1742       break;
1743     case PROP_MAX_RTCP_RTP_TIME_DIFF:
1744       rtspsrc->max_rtcp_rtp_time_diff = g_value_get_int (value);
1745       break;
1746     case PROP_RFC7273_SYNC:
1747       rtspsrc->rfc7273_sync = g_value_get_boolean (value);
1748       break;
1749     case PROP_MAX_TS_OFFSET_ADJUSTMENT:
1750       rtspsrc->max_ts_offset_adjustment = g_value_get_uint64 (value);
1751       break;
1752     case PROP_MAX_TS_OFFSET:
1753       rtspsrc->max_ts_offset = g_value_get_int64 (value);
1754       rtspsrc->max_ts_offset_is_set = TRUE;
1755       break;
1756     case PROP_DEFAULT_VERSION:
1757       rtspsrc->default_version = g_value_get_enum (value);
1758       break;
1759     case PROP_BACKCHANNEL:
1760       rtspsrc->backchannel = g_value_get_enum (value);
1761       break;
1762     case PROP_TEARDOWN_TIMEOUT:
1763       rtspsrc->teardown_timeout = g_value_get_uint64 (value);
1764       break;
1765     default:
1766       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1767       break;
1768   }
1769 }
1770
1771 static void
1772 gst_rtspsrc_get_property (GObject * object, guint prop_id, GValue * value,
1773     GParamSpec * pspec)
1774 {
1775   GstRTSPSrc *rtspsrc;
1776
1777   rtspsrc = GST_RTSPSRC (object);
1778
1779   switch (prop_id) {
1780     case PROP_LOCATION:
1781       g_value_set_string (value, rtspsrc->conninfo.location);
1782       break;
1783     case PROP_PROTOCOLS:
1784       g_value_set_flags (value, rtspsrc->protocols);
1785       break;
1786     case PROP_DEBUG:
1787       g_value_set_boolean (value, rtspsrc->debug);
1788       break;
1789     case PROP_RETRY:
1790       g_value_set_uint (value, rtspsrc->retry);
1791       break;
1792     case PROP_TIMEOUT:
1793       g_value_set_uint64 (value, rtspsrc->udp_timeout);
1794       break;
1795 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
1796     case PROP_START_POSITION:
1797       g_value_set_uint64 (value, rtspsrc->start_position);
1798       break;
1799     case PROP_RESUME_POSITION:
1800       g_value_set_uint64 (value, rtspsrc->last_pos);
1801       break;
1802 #endif
1803     case PROP_TCP_TIMEOUT:
1804     {
1805       guint64 timeout;
1806
1807       timeout = ((guint64) rtspsrc->tcp_timeout.tv_sec) * G_USEC_PER_SEC +
1808           rtspsrc->tcp_timeout.tv_usec;
1809       g_value_set_uint64 (value, timeout);
1810       break;
1811     }
1812     case PROP_LATENCY:
1813       g_value_set_uint (value, rtspsrc->latency);
1814       break;
1815     case PROP_DROP_ON_LATENCY:
1816       g_value_set_boolean (value, rtspsrc->drop_on_latency);
1817       break;
1818     case PROP_CONNECTION_SPEED:
1819       g_value_set_uint64 (value, rtspsrc->connection_speed);
1820       break;
1821     case PROP_NAT_METHOD:
1822       g_value_set_enum (value, rtspsrc->nat_method);
1823       break;
1824     case PROP_DO_RTCP:
1825       g_value_set_boolean (value, rtspsrc->do_rtcp);
1826       break;
1827     case PROP_DO_RTSP_KEEP_ALIVE:
1828       g_value_set_boolean (value, rtspsrc->do_rtsp_keep_alive);
1829       break;
1830     case PROP_PROXY:
1831     {
1832       gchar *str;
1833
1834       if (rtspsrc->proxy_host) {
1835         str =
1836             g_strdup_printf ("%s:%d", rtspsrc->proxy_host, rtspsrc->proxy_port);
1837       } else {
1838         str = NULL;
1839       }
1840       g_value_take_string (value, str);
1841       break;
1842     }
1843     case PROP_PROXY_ID:
1844       g_value_set_string (value, rtspsrc->prop_proxy_id);
1845       break;
1846     case PROP_PROXY_PW:
1847       g_value_set_string (value, rtspsrc->prop_proxy_pw);
1848       break;
1849     case PROP_RTP_BLOCKSIZE:
1850       g_value_set_uint (value, rtspsrc->rtp_blocksize);
1851       break;
1852     case PROP_USER_ID:
1853       g_value_set_string (value, rtspsrc->user_id);
1854       break;
1855     case PROP_USER_PW:
1856       g_value_set_string (value, rtspsrc->user_pw);
1857       break;
1858     case PROP_BUFFER_MODE:
1859       g_value_set_enum (value, rtspsrc->buffer_mode);
1860       break;
1861     case PROP_PORT_RANGE:
1862     {
1863       gchar *str;
1864
1865       if (rtspsrc->client_port_range.min != 0) {
1866         str = g_strdup_printf ("%u-%u", rtspsrc->client_port_range.min,
1867             rtspsrc->client_port_range.max);
1868       } else {
1869         str = NULL;
1870       }
1871       g_value_take_string (value, str);
1872       break;
1873     }
1874     case PROP_UDP_BUFFER_SIZE:
1875       g_value_set_int (value, rtspsrc->udp_buffer_size);
1876       break;
1877     case PROP_SHORT_HEADER:
1878       g_value_set_boolean (value, rtspsrc->short_header);
1879       break;
1880     case PROP_PROBATION:
1881       g_value_set_uint (value, rtspsrc->probation);
1882       break;
1883     case PROP_UDP_RECONNECT:
1884       g_value_set_boolean (value, rtspsrc->udp_reconnect);
1885       break;
1886     case PROP_MULTICAST_IFACE:
1887       g_value_set_string (value, rtspsrc->multi_iface);
1888       break;
1889     case PROP_NTP_SYNC:
1890       g_value_set_boolean (value, rtspsrc->ntp_sync);
1891       break;
1892     case PROP_USE_PIPELINE_CLOCK:
1893       g_value_set_boolean (value, rtspsrc->use_pipeline_clock);
1894       break;
1895     case PROP_SDES:
1896       g_value_set_boxed (value, rtspsrc->sdes);
1897       break;
1898     case PROP_TLS_VALIDATION_FLAGS:
1899       g_value_set_flags (value, rtspsrc->tls_validation_flags);
1900       break;
1901     case PROP_TLS_DATABASE:
1902       g_value_set_object (value, rtspsrc->tls_database);
1903       break;
1904     case PROP_TLS_INTERACTION:
1905       g_value_set_object (value, rtspsrc->tls_interaction);
1906       break;
1907     case PROP_DO_RETRANSMISSION:
1908       g_value_set_boolean (value, rtspsrc->do_retransmission);
1909       break;
1910     case PROP_NTP_TIME_SOURCE:
1911       g_value_set_enum (value, rtspsrc->ntp_time_source);
1912       break;
1913     case PROP_USER_AGENT:
1914       g_value_set_string (value, rtspsrc->user_agent);
1915       break;
1916     case PROP_MAX_RTCP_RTP_TIME_DIFF:
1917       g_value_set_int (value, rtspsrc->max_rtcp_rtp_time_diff);
1918       break;
1919     case PROP_RFC7273_SYNC:
1920       g_value_set_boolean (value, rtspsrc->rfc7273_sync);
1921       break;
1922     case PROP_MAX_TS_OFFSET_ADJUSTMENT:
1923       g_value_set_uint64 (value, rtspsrc->max_ts_offset_adjustment);
1924       break;
1925     case PROP_MAX_TS_OFFSET:
1926       g_value_set_int64 (value, rtspsrc->max_ts_offset);
1927       break;
1928     case PROP_DEFAULT_VERSION:
1929       g_value_set_enum (value, rtspsrc->default_version);
1930       break;
1931     case PROP_BACKCHANNEL:
1932       g_value_set_enum (value, rtspsrc->backchannel);
1933       break;
1934     case PROP_TEARDOWN_TIMEOUT:
1935       g_value_set_uint64 (value, rtspsrc->teardown_timeout);
1936       break;
1937     default:
1938       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1939       break;
1940   }
1941 }
1942
1943 static gint
1944 find_stream_by_id (GstRTSPStream * stream, gint * id)
1945 {
1946   if (stream->id == *id)
1947     return 0;
1948
1949   return -1;
1950 }
1951
1952 static gint
1953 find_stream_by_channel (GstRTSPStream * stream, gint * channel)
1954 {
1955   /* ignore unconfigured channels here (e.g., those that
1956    * were explicitly skipped during SETUP) */
1957   if ((stream->channelpad[0] != NULL) &&
1958       (stream->channel[0] == *channel || stream->channel[1] == *channel))
1959     return 0;
1960
1961   return -1;
1962 }
1963
1964 static gint
1965 find_stream_by_udpsrc (GstRTSPStream * stream, gconstpointer a)
1966 {
1967   GstElement *src = (GstElement *) a;
1968
1969   if (stream->udpsrc[0] == src)
1970     return 0;
1971   if (stream->udpsrc[1] == src)
1972     return 0;
1973
1974   return -1;
1975 }
1976
1977 static gint
1978 find_stream_by_setup (GstRTSPStream * stream, gconstpointer a)
1979 {
1980   if (stream->conninfo.location) {
1981     /* check qualified setup_url */
1982     if (!strcmp (stream->conninfo.location, (gchar *) a))
1983       return 0;
1984   }
1985   if (stream->control_url) {
1986     /* check original control_url */
1987     if (!strcmp (stream->control_url, (gchar *) a))
1988       return 0;
1989
1990     /* check if qualified setup_url ends with string */
1991     if (g_str_has_suffix (stream->control_url, (gchar *) a))
1992       return 0;
1993   }
1994
1995   return -1;
1996 }
1997
1998 static GstRTSPStream *
1999 find_stream (GstRTSPSrc * src, gconstpointer data, gconstpointer func)
2000 {
2001   GList *lstream;
2002
2003   /* find and get stream */
2004   if ((lstream = g_list_find_custom (src->streams, data, (GCompareFunc) func)))
2005     return (GstRTSPStream *) lstream->data;
2006
2007   return NULL;
2008 }
2009
2010 static const GstSDPBandwidth *
2011 gst_rtspsrc_get_bandwidth (GstRTSPSrc * src, const GstSDPMessage * sdp,
2012     const GstSDPMedia * media, const gchar * type)
2013 {
2014   guint i, len;
2015
2016   /* first look in the media specific section */
2017   len = gst_sdp_media_bandwidths_len (media);
2018   for (i = 0; i < len; i++) {
2019     const GstSDPBandwidth *bw = gst_sdp_media_get_bandwidth (media, i);
2020
2021     if (strcmp (bw->bwtype, type) == 0)
2022       return bw;
2023   }
2024   /* then look in the message specific section */
2025   len = gst_sdp_message_bandwidths_len (sdp);
2026   for (i = 0; i < len; i++) {
2027     const GstSDPBandwidth *bw = gst_sdp_message_get_bandwidth (sdp, i);
2028
2029     if (strcmp (bw->bwtype, type) == 0)
2030       return bw;
2031   }
2032   return NULL;
2033 }
2034
2035 static void
2036 gst_rtspsrc_collect_bandwidth (GstRTSPSrc * src, const GstSDPMessage * sdp,
2037     const GstSDPMedia * media, GstRTSPStream * stream)
2038 {
2039   const GstSDPBandwidth *bw;
2040
2041   if ((bw = gst_rtspsrc_get_bandwidth (src, sdp, media, GST_SDP_BWTYPE_AS)))
2042     stream->as_bandwidth = bw->bandwidth;
2043   else
2044     stream->as_bandwidth = -1;
2045
2046   if ((bw = gst_rtspsrc_get_bandwidth (src, sdp, media, GST_SDP_BWTYPE_RR)))
2047     stream->rr_bandwidth = bw->bandwidth;
2048   else
2049     stream->rr_bandwidth = -1;
2050
2051   if ((bw = gst_rtspsrc_get_bandwidth (src, sdp, media, GST_SDP_BWTYPE_RS)))
2052     stream->rs_bandwidth = bw->bandwidth;
2053   else
2054     stream->rs_bandwidth = -1;
2055 }
2056
2057 static void
2058 gst_rtspsrc_do_stream_connection (GstRTSPSrc * src, GstRTSPStream * stream,
2059     const GstSDPConnection * conn)
2060 {
2061   if (conn->nettype == NULL || strcmp (conn->nettype, "IN") != 0)
2062     return;
2063
2064   if (conn->addrtype == NULL)
2065     return;
2066
2067   /* check for IPV6 */
2068   if (strcmp (conn->addrtype, "IP4") == 0)
2069     stream->is_ipv6 = FALSE;
2070   else if (strcmp (conn->addrtype, "IP6") == 0)
2071     stream->is_ipv6 = TRUE;
2072   else
2073     return;
2074
2075   /* save address */
2076   g_free (stream->destination);
2077   stream->destination = g_strdup (conn->address);
2078
2079   /* check for multicast */
2080   stream->is_multicast =
2081       gst_sdp_address_is_multicast (conn->nettype, conn->addrtype,
2082       conn->address);
2083   stream->ttl = conn->ttl;
2084 }
2085
2086 /* Go over the connections for a stream.
2087  * - If we are dealing with IPV6, we will setup IPV6 sockets for sending and
2088  *   receiving.
2089  * - If we are dealing with a localhost address, we disable multicast
2090  */
2091 static void
2092 gst_rtspsrc_collect_connections (GstRTSPSrc * src, const GstSDPMessage * sdp,
2093     const GstSDPMedia * media, GstRTSPStream * stream)
2094 {
2095   const GstSDPConnection *conn;
2096   guint i, len;
2097
2098   /* first look in the media specific section */
2099   len = gst_sdp_media_connections_len (media);
2100   for (i = 0; i < len; i++) {
2101     conn = gst_sdp_media_get_connection (media, i);
2102
2103     gst_rtspsrc_do_stream_connection (src, stream, conn);
2104   }
2105   /* then look in the message specific section */
2106   if ((conn = gst_sdp_message_get_connection (sdp))) {
2107     gst_rtspsrc_do_stream_connection (src, stream, conn);
2108   }
2109 }
2110
2111 static gchar *
2112 make_stream_id (GstRTSPStream * stream, const GstSDPMedia * media)
2113 {
2114   gchar *stream_id =
2115       g_strdup_printf ("%s:%d:%d:%s:%d", media->media, media->port,
2116       media->num_ports, media->proto, stream->default_pt);
2117
2118   g_strcanon (stream_id, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS, ':');
2119
2120   return stream_id;
2121 }
2122
2123 /*   m=<media> <UDP port> RTP/AVP <payload>
2124  */
2125 static void
2126 gst_rtspsrc_collect_payloads (GstRTSPSrc * src, const GstSDPMessage * sdp,
2127     const GstSDPMedia * media, GstRTSPStream * stream)
2128 {
2129   guint i, len;
2130   const gchar *proto;
2131   GstCaps *global_caps;
2132
2133   /* get proto */
2134   proto = gst_sdp_media_get_proto (media);
2135   if (proto == NULL)
2136     goto no_proto;
2137
2138   if (g_str_equal (proto, "RTP/AVP"))
2139     stream->profile = GST_RTSP_PROFILE_AVP;
2140   else if (g_str_equal (proto, "RTP/SAVP"))
2141     stream->profile = GST_RTSP_PROFILE_SAVP;
2142   else if (g_str_equal (proto, "RTP/AVPF"))
2143     stream->profile = GST_RTSP_PROFILE_AVPF;
2144   else if (g_str_equal (proto, "RTP/SAVPF"))
2145     stream->profile = GST_RTSP_PROFILE_SAVPF;
2146   else
2147     goto unknown_proto;
2148
2149   if (gst_sdp_media_get_attribute_val (media, "sendonly") != NULL &&
2150       /* We want to setup caps for streams configured as backchannel */
2151       !stream->is_backchannel && src->backchannel != BACKCHANNEL_NONE)
2152     goto sendonly_media;
2153
2154   /* Parse global SDP attributes once */
2155   global_caps = gst_caps_new_empty_simple ("application/x-unknown");
2156   GST_DEBUG ("mapping sdp session level attributes to caps");
2157   gst_sdp_message_attributes_to_caps (sdp, global_caps);
2158   GST_DEBUG ("mapping sdp media level attributes to caps");
2159   gst_sdp_media_attributes_to_caps (media, global_caps);
2160
2161   /* Keep a copy of the SDP key management */
2162   gst_sdp_media_parse_keymgmt (media, &stream->mikey);
2163   if (stream->mikey == NULL)
2164     gst_sdp_message_parse_keymgmt (sdp, &stream->mikey);
2165
2166   len = gst_sdp_media_formats_len (media);
2167   for (i = 0; i < len; i++) {
2168     gint pt;
2169     GstCaps *caps, *outcaps;
2170     GstStructure *s;
2171     const gchar *enc;
2172     PtMapItem item;
2173 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
2174     const gchar *encoder, *mediatype;
2175 #endif
2176     pt = atoi (gst_sdp_media_get_format (media, i));
2177
2178     GST_DEBUG_OBJECT (src, " looking at %d pt: %d", i, pt);
2179
2180     /* convert caps */
2181     caps = gst_sdp_media_get_caps_from_media (media, pt);
2182     if (caps == NULL) {
2183       GST_WARNING_OBJECT (src, " skipping pt %d without caps", pt);
2184       continue;
2185     }
2186
2187     /* do some tweaks */
2188     s = gst_caps_get_structure (caps, 0);
2189     if ((enc = gst_structure_get_string (s, "encoding-name"))) {
2190       stream->is_real = (strstr (enc, "-REAL") != NULL);
2191       if (strcmp (enc, "X-ASF-PF") == 0)
2192         stream->container = TRUE;
2193     }
2194 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
2195     if ((mediatype = gst_structure_get_string (s, "media"))) {
2196       GST_DEBUG_OBJECT (src, " mediatype : %s", mediatype);
2197       if (!strcmp (mediatype, "video")) {
2198         if ((encoder = gst_structure_get_string (s, "encoding-name"))) {
2199           GST_DEBUG_OBJECT (src, " encoder : %s", encoder);
2200           if ((!strcmp (encoder, "H261")) ||
2201               (!strcmp (encoder, "H263")) ||
2202               (!strcmp (encoder, "H263-1998"))
2203               || (!strcmp (encoder, "H263-2000")) || (!strcmp (encoder, "H264"))
2204               || (!strcmp (encoder, "MP4V-ES"))) {
2205             src->is_video_codec_supported = TRUE;
2206             GST_DEBUG_OBJECT (src, "Supported Video Codec %s", encoder);
2207           } else {
2208             GST_DEBUG_OBJECT (src, "Unsupported Video Codec %s", encoder);
2209           }
2210         }
2211
2212         src->video_codec = g_strdup (encoder);
2213         src->video_frame_size =
2214             g_strdup (gst_structure_get_string (s, "a-framesize"));
2215         GST_DEBUG_OBJECT (src, "video_codec %s , video_frame_size %s ",
2216             src->video_codec, src->video_frame_size);
2217       } else if (!strcmp (mediatype, "audio")) {
2218         if ((encoder = gst_structure_get_string (s, "encoding-name"))) {
2219           GST_DEBUG_OBJECT (src, " encoder : %s", encoder);
2220           if ((!strcmp (encoder, "MP4A-LATM")) ||
2221               (!strcmp (encoder, "AMR")) || (!strcmp (encoder, "AMR-WB"))
2222               || (!strcmp (encoder, "AMR-NB"))
2223               || (!strcmp (encoder, "mpeg4-generic"))
2224               || (!strcmp (encoder, "MPEG4-GENERIC"))
2225               || (!strcmp (encoder, "QCELP")) || ((strstr (encoder, "G726"))
2226                   || (strstr (encoder, "PCMU")))) {
2227             src->is_audio_codec_supported = TRUE;
2228             GST_DEBUG_OBJECT (src, "Supported Audio Codec %s", encoder);
2229           } else {
2230             GST_DEBUG_OBJECT (src, "Unsupported Audio Codec %s", encoder);
2231           }
2232         }
2233
2234         src->audio_codec = g_strdup (encoder);
2235         GST_DEBUG_OBJECT (src, "audio_codec %s ", src->audio_codec);
2236       }
2237     }
2238 #endif
2239
2240     /* Merge in global caps */
2241     /* Intersect will merge in missing fields to the current caps */
2242     outcaps = gst_caps_intersect (caps, global_caps);
2243     gst_caps_unref (caps);
2244
2245     /* the first pt will be the default */
2246     if (stream->ptmap->len == 0)
2247       stream->default_pt = pt;
2248
2249     item.pt = pt;
2250     item.caps = outcaps;
2251
2252     g_array_append_val (stream->ptmap, item);
2253   }
2254
2255   stream->stream_id = make_stream_id (stream, media);
2256
2257   gst_caps_unref (global_caps);
2258   return;
2259
2260 no_proto:
2261   {
2262     GST_ERROR_OBJECT (src, "can't find proto in media");
2263     return;
2264   }
2265 unknown_proto:
2266   {
2267     GST_ERROR_OBJECT (src, "unknown proto in media: '%s'", proto);
2268     return;
2269   }
2270 sendonly_media:
2271   {
2272     GST_DEBUG_OBJECT (src, "sendonly media ignored, no backchannel");
2273     return;
2274   }
2275 }
2276
2277 static const gchar *
2278 get_aggregate_control (GstRTSPSrc * src)
2279 {
2280   const gchar *base;
2281
2282   if (src->control)
2283     base = src->control;
2284   else if (src->content_base)
2285     base = src->content_base;
2286   else if (src->conninfo.url_str)
2287     base = src->conninfo.url_str;
2288   else
2289     base = "/";
2290
2291   return base;
2292 }
2293
2294 static void
2295 clear_ptmap_item (PtMapItem * item)
2296 {
2297   if (item->caps)
2298     gst_caps_unref (item->caps);
2299 }
2300
2301 static GstRTSPStream *
2302 gst_rtspsrc_create_stream (GstRTSPSrc * src, GstSDPMessage * sdp, gint idx,
2303     gint n_streams)
2304 {
2305   GstRTSPStream *stream;
2306   const gchar *control_url;
2307   const GstSDPMedia *media;
2308
2309   /* get media, should not return NULL */
2310   media = gst_sdp_message_get_media (sdp, idx);
2311   if (media == NULL)
2312     return NULL;
2313
2314   stream = g_new0 (GstRTSPStream, 1);
2315   stream->parent = src;
2316   /* we mark the pad as not linked, we will mark it as OK when we add the pad to
2317    * the element. */
2318   stream->last_ret = GST_FLOW_NOT_LINKED;
2319   stream->added = FALSE;
2320   stream->setup = FALSE;
2321   stream->skipped = FALSE;
2322   stream->id = idx;
2323   stream->eos = FALSE;
2324   stream->discont = TRUE;
2325   stream->seqbase = -1;
2326   stream->timebase = -1;
2327   stream->send_ssrc = g_random_int ();
2328   stream->profile = GST_RTSP_PROFILE_AVP;
2329   stream->ptmap = g_array_new (FALSE, FALSE, sizeof (PtMapItem));
2330   stream->mikey = NULL;
2331   stream->stream_id = NULL;
2332   stream->is_backchannel = FALSE;
2333   g_mutex_init (&stream->conninfo.send_lock);
2334   g_mutex_init (&stream->conninfo.recv_lock);
2335   g_array_set_clear_func (stream->ptmap, (GDestroyNotify) clear_ptmap_item);
2336
2337   /* stream is sendonly and onvif backchannel is requested */
2338   if (gst_sdp_media_get_attribute_val (media, "sendonly") != NULL &&
2339       src->backchannel != BACKCHANNEL_NONE)
2340     stream->is_backchannel = TRUE;
2341
2342   /* collect bandwidth information for this steam. FIXME, configure in the RTP
2343    * session manager to scale RTCP. */
2344   gst_rtspsrc_collect_bandwidth (src, sdp, media, stream);
2345
2346   /* collect connection info */
2347   gst_rtspsrc_collect_connections (src, sdp, media, stream);
2348
2349   /* make the payload type map */
2350   gst_rtspsrc_collect_payloads (src, sdp, media, stream);
2351
2352   /* collect port number */
2353   stream->port = gst_sdp_media_get_port (media);
2354
2355   /* get control url to construct the setup url. The setup url is used to
2356    * configure the transport of the stream and is used to identity the stream in
2357    * the RTP-Info header field returned from PLAY. */
2358   control_url = gst_sdp_media_get_attribute_val (media, "control");
2359   if (control_url == NULL)
2360     control_url = gst_sdp_message_get_attribute_val_n (sdp, "control", 0);
2361
2362   GST_DEBUG_OBJECT (src, "stream %d, (%p)", stream->id, stream);
2363   GST_DEBUG_OBJECT (src, " port: %d", stream->port);
2364   GST_DEBUG_OBJECT (src, " container: %d", stream->container);
2365   GST_DEBUG_OBJECT (src, " control: %s", GST_STR_NULL (control_url));
2366
2367   /* RFC 2326, C.3: missing control_url permitted in case of a single stream */
2368   if (control_url == NULL && n_streams == 1) {
2369     control_url = "";
2370   }
2371
2372   if (control_url != NULL) {
2373     stream->control_url = g_strdup (control_url);
2374     /* Build a fully qualified url using the content_base if any or by prefixing
2375      * the original request.
2376      * If the control_url starts with a '/' or a non rtsp: protocol we will most
2377      * likely build a URL that the server will fail to understand, this is ok,
2378      * we will fail then. */
2379     if (g_str_has_prefix (control_url, "rtsp://"))
2380       stream->conninfo.location = g_strdup (control_url);
2381     else {
2382       const gchar *base;
2383       gboolean has_slash;
2384
2385       if (g_strcmp0 (control_url, "*") == 0)
2386         control_url = "";
2387
2388       base = get_aggregate_control (src);
2389
2390       /* check if the base ends or control starts with / */
2391       has_slash = g_str_has_prefix (control_url, "/");
2392       has_slash = has_slash || g_str_has_suffix (base, "/");
2393
2394       /* concatenate the two strings, insert / when not present */
2395       stream->conninfo.location =
2396           g_strdup_printf ("%s%s%s", base, has_slash ? "" : "/", control_url);
2397     }
2398   }
2399   GST_DEBUG_OBJECT (src, " setup: %s",
2400       GST_STR_NULL (stream->conninfo.location));
2401
2402   /* we keep track of all streams */
2403   src->streams = g_list_append (src->streams, stream);
2404
2405   return stream;
2406
2407   /* ERRORS */
2408 }
2409
2410 static void
2411 gst_rtspsrc_stream_free (GstRTSPSrc * src, GstRTSPStream * stream)
2412 {
2413   gint i;
2414
2415   GST_DEBUG_OBJECT (src, "free stream %p", stream);
2416
2417   g_array_free (stream->ptmap, TRUE);
2418
2419   g_free (stream->destination);
2420   g_free (stream->control_url);
2421   g_free (stream->conninfo.location);
2422   g_free (stream->stream_id);
2423
2424   for (i = 0; i < 2; i++) {
2425     if (stream->udpsrc[i]) {
2426       gst_element_set_state (stream->udpsrc[i], GST_STATE_NULL);
2427       if (gst_object_has_as_parent (GST_OBJECT (stream->udpsrc[i]),
2428               GST_OBJECT (src)))
2429         gst_bin_remove (GST_BIN_CAST (src), stream->udpsrc[i]);
2430       gst_object_unref (stream->udpsrc[i]);
2431     }
2432     if (stream->channelpad[i])
2433       gst_object_unref (stream->channelpad[i]);
2434
2435     if (stream->udpsink[i]) {
2436       gst_element_set_state (stream->udpsink[i], GST_STATE_NULL);
2437       if (gst_object_has_as_parent (GST_OBJECT (stream->udpsink[i]),
2438               GST_OBJECT (src)))
2439         gst_bin_remove (GST_BIN_CAST (src), stream->udpsink[i]);
2440       gst_object_unref (stream->udpsink[i]);
2441     }
2442   }
2443   if (stream->rtpsrc) {
2444     gst_element_set_state (stream->rtpsrc, GST_STATE_NULL);
2445     gst_bin_remove (GST_BIN_CAST (src), stream->rtpsrc);
2446     gst_object_unref (stream->rtpsrc);
2447   }
2448   if (stream->srcpad) {
2449     gst_pad_set_active (stream->srcpad, FALSE);
2450     if (stream->added)
2451       gst_element_remove_pad (GST_ELEMENT_CAST (src), stream->srcpad);
2452   }
2453   if (stream->srtpenc)
2454     gst_object_unref (stream->srtpenc);
2455   if (stream->srtpdec)
2456     gst_object_unref (stream->srtpdec);
2457   if (stream->srtcpparams)
2458     gst_caps_unref (stream->srtcpparams);
2459   if (stream->mikey)
2460     gst_mikey_message_unref (stream->mikey);
2461   if (stream->rtcppad)
2462     gst_object_unref (stream->rtcppad);
2463   if (stream->session)
2464     g_object_unref (stream->session);
2465   if (stream->rtx_pt_map)
2466     gst_structure_free (stream->rtx_pt_map);
2467
2468   g_mutex_clear (&stream->conninfo.send_lock);
2469   g_mutex_clear (&stream->conninfo.recv_lock);
2470
2471   g_free (stream);
2472 }
2473
2474 static void
2475 gst_rtspsrc_cleanup (GstRTSPSrc * src)
2476 {
2477   GList *walk;
2478
2479   GST_DEBUG_OBJECT (src, "cleanup");
2480
2481   for (walk = src->streams; walk; walk = g_list_next (walk)) {
2482     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
2483
2484     gst_rtspsrc_stream_free (src, stream);
2485   }
2486   g_list_free (src->streams);
2487   src->streams = NULL;
2488   if (src->manager) {
2489     if (src->manager_sig_id) {
2490       g_signal_handler_disconnect (src->manager, src->manager_sig_id);
2491       src->manager_sig_id = 0;
2492     }
2493     gst_element_set_state (src->manager, GST_STATE_NULL);
2494     gst_bin_remove (GST_BIN_CAST (src), src->manager);
2495     src->manager = NULL;
2496   }
2497   if (src->props)
2498     gst_structure_free (src->props);
2499   src->props = NULL;
2500
2501   g_free (src->content_base);
2502   src->content_base = NULL;
2503
2504   g_free (src->control);
2505   src->control = NULL;
2506
2507   if (src->range)
2508     gst_rtsp_range_free (src->range);
2509   src->range = NULL;
2510
2511   /* don't clear the SDP when it was used in the url */
2512   if (src->sdp && !src->from_sdp) {
2513     gst_sdp_message_free (src->sdp);
2514     src->sdp = NULL;
2515   }
2516
2517   src->need_segment = FALSE;
2518
2519   if (src->provided_clock) {
2520     gst_object_unref (src->provided_clock);
2521     src->provided_clock = NULL;
2522   }
2523
2524   /* free parameter requests queue */
2525   if (!g_queue_is_empty (&src->set_get_param_q))
2526     g_queue_free_full (&src->set_get_param_q, free_param_queue);
2527
2528 }
2529
2530 static gboolean
2531 gst_rtspsrc_alloc_udp_ports (GstRTSPStream * stream,
2532     gint * rtpport, gint * rtcpport)
2533 {
2534   GstRTSPSrc *src;
2535   GstStateChangeReturn ret;
2536   GstElement *udpsrc0, *udpsrc1;
2537   gint tmp_rtp, tmp_rtcp;
2538   guint count;
2539   const gchar *host;
2540
2541   src = stream->parent;
2542
2543   udpsrc0 = NULL;
2544   udpsrc1 = NULL;
2545   count = 0;
2546
2547   /* Start at next port */
2548   tmp_rtp = src->next_port_num;
2549
2550   if (stream->is_ipv6)
2551     host = "udp://[::0]";
2552   else
2553     host = "udp://0.0.0.0";
2554
2555   /* try to allocate 2 UDP ports, the RTP port should be an even
2556    * number and the RTCP port should be the next (uneven) port */
2557 again:
2558
2559   if (tmp_rtp != 0 && src->client_port_range.max > 0 &&
2560       tmp_rtp >= src->client_port_range.max)
2561     goto no_ports;
2562
2563   udpsrc0 = gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL);
2564   if (udpsrc0 == NULL)
2565     goto no_udp_protocol;
2566   g_object_set (G_OBJECT (udpsrc0), "port", tmp_rtp, "reuse", FALSE, NULL);
2567
2568   if (src->udp_buffer_size != 0)
2569     g_object_set (G_OBJECT (udpsrc0), "buffer-size", src->udp_buffer_size,
2570         NULL);
2571
2572   ret = gst_element_set_state (udpsrc0, GST_STATE_READY);
2573   if (ret == GST_STATE_CHANGE_FAILURE) {
2574     if (tmp_rtp != 0) {
2575       GST_DEBUG_OBJECT (src, "Unable to make udpsrc from RTP port %d", tmp_rtp);
2576
2577       tmp_rtp += 2;
2578       if (++count > src->retry)
2579         goto no_ports;
2580
2581       GST_DEBUG_OBJECT (src, "free RTP udpsrc");
2582       gst_element_set_state (udpsrc0, GST_STATE_NULL);
2583       gst_object_unref (udpsrc0);
2584       udpsrc0 = NULL;
2585
2586       GST_DEBUG_OBJECT (src, "retry %d", count);
2587       goto again;
2588     }
2589     goto no_udp_protocol;
2590   }
2591
2592   g_object_get (G_OBJECT (udpsrc0), "port", &tmp_rtp, NULL);
2593   GST_DEBUG_OBJECT (src, "got RTP port %d", tmp_rtp);
2594
2595   /* check if port is even */
2596   if ((tmp_rtp & 0x01) != 0) {
2597     /* port not even, close and allocate another */
2598     if (++count > src->retry)
2599       goto no_ports;
2600
2601     GST_DEBUG_OBJECT (src, "RTP port not even");
2602
2603     GST_DEBUG_OBJECT (src, "free RTP udpsrc");
2604     gst_element_set_state (udpsrc0, GST_STATE_NULL);
2605     gst_object_unref (udpsrc0);
2606     udpsrc0 = NULL;
2607
2608     GST_DEBUG_OBJECT (src, "retry %d", count);
2609     tmp_rtp++;
2610     goto again;
2611   }
2612
2613   /* allocate port+1 for RTCP now */
2614   udpsrc1 = gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL);
2615   if (udpsrc1 == NULL)
2616     goto no_udp_rtcp_protocol;
2617
2618   /* set port */
2619   tmp_rtcp = tmp_rtp + 1;
2620   if (src->client_port_range.max > 0 && tmp_rtcp > src->client_port_range.max)
2621     goto no_ports;
2622
2623   g_object_set (G_OBJECT (udpsrc1), "port", tmp_rtcp, "reuse", FALSE, NULL);
2624
2625   GST_DEBUG_OBJECT (src, "starting RTCP on port %d", tmp_rtcp);
2626   ret = gst_element_set_state (udpsrc1, GST_STATE_READY);
2627   /* tmp_rtcp port is busy already : retry to make rtp/rtcp pair */
2628   if (ret == GST_STATE_CHANGE_FAILURE) {
2629     GST_DEBUG_OBJECT (src, "Unable to make udpsrc from RTCP port %d", tmp_rtcp);
2630
2631     if (++count > src->retry)
2632       goto no_ports;
2633
2634     GST_DEBUG_OBJECT (src, "free RTP udpsrc");
2635     gst_element_set_state (udpsrc0, GST_STATE_NULL);
2636     gst_object_unref (udpsrc0);
2637     udpsrc0 = NULL;
2638
2639     GST_DEBUG_OBJECT (src, "free RTCP udpsrc");
2640     gst_element_set_state (udpsrc1, GST_STATE_NULL);
2641     gst_object_unref (udpsrc1);
2642     udpsrc1 = NULL;
2643
2644     tmp_rtp += 2;
2645     GST_DEBUG_OBJECT (src, "retry %d", count);
2646     goto again;
2647   }
2648
2649   /* all fine, do port check */
2650   g_object_get (G_OBJECT (udpsrc0), "port", rtpport, NULL);
2651   g_object_get (G_OBJECT (udpsrc1), "port", rtcpport, NULL);
2652
2653   /* this should not happen... */
2654   if (*rtpport != tmp_rtp || *rtcpport != tmp_rtcp)
2655     goto port_error;
2656
2657   /* we keep these elements, we configure all in configure_transport when the
2658    * server told us to really use the UDP ports. */
2659   stream->udpsrc[0] = gst_object_ref_sink (udpsrc0);
2660   stream->udpsrc[1] = gst_object_ref_sink (udpsrc1);
2661   gst_element_set_locked_state (stream->udpsrc[0], TRUE);
2662   gst_element_set_locked_state (stream->udpsrc[1], TRUE);
2663
2664   /* keep track of next available port number when we have a range
2665    * configured */
2666   if (src->next_port_num != 0)
2667     src->next_port_num = tmp_rtcp + 1;
2668
2669   return TRUE;
2670
2671   /* ERRORS */
2672 no_udp_protocol:
2673   {
2674     GST_DEBUG_OBJECT (src, "could not get UDP source");
2675     goto cleanup;
2676   }
2677 no_ports:
2678   {
2679     GST_DEBUG_OBJECT (src, "could not allocate UDP port pair after %d retries",
2680         count);
2681     goto cleanup;
2682   }
2683 no_udp_rtcp_protocol:
2684   {
2685     GST_DEBUG_OBJECT (src, "could not get UDP source for RTCP");
2686     goto cleanup;
2687   }
2688 port_error:
2689   {
2690     GST_DEBUG_OBJECT (src, "ports don't match rtp: %d<->%d, rtcp: %d<->%d",
2691         tmp_rtp, *rtpport, tmp_rtcp, *rtcpport);
2692     goto cleanup;
2693   }
2694 cleanup:
2695   {
2696     if (udpsrc0) {
2697       gst_element_set_state (udpsrc0, GST_STATE_NULL);
2698       gst_object_unref (udpsrc0);
2699     }
2700     if (udpsrc1) {
2701       gst_element_set_state (udpsrc1, GST_STATE_NULL);
2702       gst_object_unref (udpsrc1);
2703     }
2704     return FALSE;
2705   }
2706 }
2707
2708 static void
2709 gst_rtspsrc_set_state (GstRTSPSrc * src, GstState state)
2710 {
2711   GList *walk;
2712
2713 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
2714   GST_WARNING_OBJECT (src, "Setting [%s] element state to: %s \n",
2715       GST_ELEMENT_NAME (GST_ELEMENT_CAST (src)),
2716       gst_element_state_get_name (state));
2717 #endif
2718   if (src->manager)
2719     gst_element_set_state (GST_ELEMENT_CAST (src->manager), state);
2720
2721   for (walk = src->streams; walk; walk = g_list_next (walk)) {
2722     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
2723     gint i;
2724
2725     for (i = 0; i < 2; i++) {
2726       if (stream->udpsrc[i])
2727         gst_element_set_state (stream->udpsrc[i], state);
2728     }
2729   }
2730 }
2731
2732 static void
2733 gst_rtspsrc_flush (GstRTSPSrc * src, gboolean flush, gboolean playing,
2734     guint32 seqnum)
2735 {
2736   GstEvent *event;
2737   gint cmd;
2738   GstState state;
2739
2740   if (flush) {
2741     event = gst_event_new_flush_start ();
2742     gst_event_set_seqnum (event, seqnum);
2743     GST_DEBUG_OBJECT (src, "start flush");
2744     cmd = CMD_WAIT;
2745     state = GST_STATE_PAUSED;
2746   } else {
2747     event = gst_event_new_flush_stop (FALSE);
2748     gst_event_set_seqnum (event, seqnum);
2749     GST_DEBUG_OBJECT (src, "stop flush; playing %d", playing);
2750     cmd = CMD_LOOP;
2751     if (playing)
2752       state = GST_STATE_PLAYING;
2753     else
2754       state = GST_STATE_PAUSED;
2755   }
2756   gst_rtspsrc_push_event (src, event);
2757   gst_rtspsrc_loop_send_cmd (src, cmd, CMD_LOOP);
2758   gst_rtspsrc_set_state (src, state);
2759 }
2760
2761 static GstRTSPResult
2762 gst_rtspsrc_connection_send (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
2763     GstRTSPMessage * message, GTimeVal * timeout)
2764 {
2765   GstRTSPResult ret;
2766
2767   if (conninfo->connection) {
2768     g_mutex_lock (&conninfo->send_lock);
2769     ret = gst_rtsp_connection_send (conninfo->connection, message, timeout);
2770     g_mutex_unlock (&conninfo->send_lock);
2771   } else {
2772     ret = GST_RTSP_ERROR;
2773   }
2774
2775   return ret;
2776 }
2777
2778 static GstRTSPResult
2779 gst_rtspsrc_connection_receive (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
2780     GstRTSPMessage * message, GTimeVal * timeout)
2781 {
2782   GstRTSPResult ret;
2783
2784   if (conninfo->connection) {
2785     g_mutex_lock (&conninfo->recv_lock);
2786     ret = gst_rtsp_connection_receive (conninfo->connection, message, timeout);
2787     g_mutex_unlock (&conninfo->recv_lock);
2788   } else {
2789     ret = GST_RTSP_ERROR;
2790   }
2791
2792   return ret;
2793 }
2794
2795 static void
2796 gst_rtspsrc_get_position (GstRTSPSrc * src)
2797 {
2798   GstQuery *query;
2799   GList *walk;
2800
2801   query = gst_query_new_position (GST_FORMAT_TIME);
2802   /*  should be known somewhere down the stream (e.g. jitterbuffer) */
2803   for (walk = src->streams; walk; walk = g_list_next (walk)) {
2804     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
2805     GstFormat fmt;
2806     gint64 pos;
2807
2808     if (stream->srcpad) {
2809       if (gst_pad_query (stream->srcpad, query)) {
2810         gst_query_parse_position (query, &fmt, &pos);
2811         GST_DEBUG_OBJECT (src, "retaining position %" GST_TIME_FORMAT,
2812             GST_TIME_ARGS (pos));
2813         src->last_pos = pos;
2814         goto out;
2815       }
2816     }
2817   }
2818
2819   src->last_pos = 0;
2820
2821 out:
2822
2823   gst_query_unref (query);
2824 }
2825
2826 static gboolean
2827 gst_rtspsrc_perform_seek (GstRTSPSrc * src, GstEvent * event)
2828 {
2829   gdouble rate;
2830   GstFormat format;
2831   GstSeekFlags flags;
2832   GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
2833   gint64 cur, stop;
2834   gboolean flush, skip;
2835   gboolean update;
2836   gboolean playing;
2837   GstSegment seeksegment = { 0, };
2838   GList *walk;
2839   const gchar *seek_style = NULL;
2840
2841   GST_DEBUG_OBJECT (src, "doing seek with event %" GST_PTR_FORMAT, event);
2842
2843   gst_event_parse_seek (event, &rate, &format, &flags,
2844       &cur_type, &cur, &stop_type, &stop);
2845
2846   /* no negative rates yet */
2847   if (rate < 0.0)
2848     goto negative_rate;
2849
2850   /* we need TIME format */
2851   if (format != src->segment.format)
2852     goto no_format;
2853
2854   /* Check if we are not at all seekable */
2855   if (src->seekable == -1.0)
2856     goto not_seekable;
2857
2858   /* Additional seeking-to-beginning-only check */
2859   if (src->seekable == 0.0 && cur != 0)
2860     goto not_seekable;
2861
2862   if (flags & GST_SEEK_FLAG_SEGMENT)
2863     goto invalid_segment_flag;
2864
2865   /* get flush flag */
2866   flush = flags & GST_SEEK_FLAG_FLUSH;
2867   skip = flags & GST_SEEK_FLAG_SKIP;
2868
2869   /* now we need to make sure the streaming thread is stopped. We do this by
2870    * either sending a FLUSH_START event downstream which will cause the
2871    * streaming thread to stop with a WRONG_STATE.
2872    * For a non-flushing seek we simply pause the task, which will happen as soon
2873    * as it completes one iteration (and thus might block when the sink is
2874    * blocking in preroll). */
2875   if (flush) {
2876     GST_DEBUG_OBJECT (src, "starting flush");
2877     gst_rtspsrc_flush (src, TRUE, FALSE, gst_event_get_seqnum (event));
2878   } else {
2879     if (src->task) {
2880       gst_task_pause (src->task);
2881     }
2882   }
2883
2884   /* we should now be able to grab the streaming thread because we stopped it
2885    * with the above flush/pause code */
2886   GST_RTSP_STREAM_LOCK (src);
2887
2888   GST_DEBUG_OBJECT (src, "stopped streaming");
2889
2890   /* stop flushing the rtsp connection so we can send PAUSE/PLAY below */
2891   gst_rtspsrc_connection_flush (src, FALSE);
2892
2893   /* copy segment, we need this because we still need the old
2894    * segment when we close the current segment. */
2895   memcpy (&seeksegment, &src->segment, sizeof (GstSegment));
2896
2897   /* configure the seek parameters in the seeksegment. We will then have the
2898    * right values in the segment to perform the seek */
2899   GST_DEBUG_OBJECT (src, "configuring seek");
2900   gst_segment_do_seek (&seeksegment, rate, format, flags,
2901       cur_type, cur, stop_type, stop, &update);
2902
2903   /* figure out the last position we need to play. If it's configured (stop !=
2904    * -1), use that, else we play until the total duration of the file */
2905   if ((stop = seeksegment.stop) == -1)
2906     stop = seeksegment.duration;
2907
2908   /* if we were playing, pause first */
2909   playing = (src->state == GST_RTSP_STATE_PLAYING);
2910   if (playing) {
2911     /* obtain current position in case seek fails */
2912     gst_rtspsrc_get_position (src);
2913     gst_rtspsrc_pause (src, FALSE);
2914   }
2915   src->skip = skip;
2916
2917   src->state = GST_RTSP_STATE_SEEKING;
2918
2919   /* PLAY will add the range header now. */
2920   src->need_range = TRUE;
2921
2922   /* prepare for streaming again */
2923   if (flush) {
2924     /* if we started flush, we stop now */
2925     GST_DEBUG_OBJECT (src, "stopping flush");
2926     gst_rtspsrc_flush (src, FALSE, playing, gst_event_get_seqnum (event));
2927   }
2928
2929   /* now we did the seek and can activate the new segment values */
2930   memcpy (&src->segment, &seeksegment, sizeof (GstSegment));
2931
2932   /* if we're doing a segment seek, post a SEGMENT_START message */
2933   if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
2934     gst_element_post_message (GST_ELEMENT_CAST (src),
2935         gst_message_new_segment_start (GST_OBJECT_CAST (src),
2936             src->segment.format, src->segment.position));
2937   }
2938
2939   /* now create the newsegment */
2940   GST_DEBUG_OBJECT (src, "Creating newsegment from %" G_GINT64_FORMAT
2941       " to %" G_GINT64_FORMAT, src->segment.position, stop);
2942
2943   /* mark discont */
2944   GST_DEBUG_OBJECT (src, "mark DISCONT, we did a seek to another position");
2945   for (walk = src->streams; walk; walk = g_list_next (walk)) {
2946     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
2947     stream->discont = TRUE;
2948   }
2949
2950   /* and continue playing if needed */
2951   GST_OBJECT_LOCK (src);
2952   playing = (GST_STATE_PENDING (src) == GST_STATE_VOID_PENDING
2953       && GST_STATE (src) == GST_STATE_PLAYING)
2954       || (GST_STATE_PENDING (src) == GST_STATE_PLAYING);
2955   GST_OBJECT_UNLOCK (src);
2956
2957   if (src->version >= GST_RTSP_VERSION_2_0) {
2958     if (flags & GST_SEEK_FLAG_ACCURATE)
2959       seek_style = "RAP";
2960     else if (flags & GST_SEEK_FLAG_KEY_UNIT)
2961       seek_style = "CoRAP";
2962     else if (flags & GST_SEEK_FLAG_KEY_UNIT
2963         && flags & GST_SEEK_FLAG_SNAP_BEFORE)
2964       seek_style = "First-Prior";
2965     else if (flags & GST_SEEK_FLAG_KEY_UNIT && flags & GST_SEEK_FLAG_SNAP_AFTER)
2966       seek_style = "Next";
2967   }
2968
2969   if (playing)
2970     gst_rtspsrc_play (src, &seeksegment, FALSE, seek_style);
2971
2972   GST_RTSP_STREAM_UNLOCK (src);
2973
2974   return TRUE;
2975
2976   /* ERRORS */
2977 negative_rate:
2978   {
2979     GST_DEBUG_OBJECT (src, "negative playback rates are not supported yet.");
2980     return FALSE;
2981   }
2982 no_format:
2983   {
2984     GST_DEBUG_OBJECT (src, "unsupported format given, seek aborted.");
2985     return FALSE;
2986   }
2987 not_seekable:
2988   {
2989     GST_DEBUG_OBJECT (src, "stream is not seekable");
2990     return FALSE;
2991   }
2992 invalid_segment_flag:
2993   {
2994     GST_WARNING_OBJECT (src, "Segment seeks not supported");
2995     return FALSE;
2996   }
2997 }
2998
2999 static gboolean
3000 gst_rtspsrc_handle_src_event (GstPad * pad, GstObject * parent,
3001     GstEvent * event)
3002 {
3003   GstRTSPSrc *src;
3004   gboolean res = TRUE;
3005   gboolean forward;
3006
3007   src = GST_RTSPSRC_CAST (parent);
3008
3009   GST_DEBUG_OBJECT (src, "pad %s:%s received event %s",
3010       GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
3011
3012   switch (GST_EVENT_TYPE (event)) {
3013     case GST_EVENT_SEEK:
3014       res = gst_rtspsrc_perform_seek (src, event);
3015       forward = FALSE;
3016       break;
3017     case GST_EVENT_QOS:
3018     case GST_EVENT_NAVIGATION:
3019     case GST_EVENT_LATENCY:
3020     default:
3021       forward = TRUE;
3022       break;
3023   }
3024   if (forward) {
3025     GstPad *target;
3026
3027     if ((target = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (pad)))) {
3028       res = gst_pad_send_event (target, event);
3029       gst_object_unref (target);
3030     } else {
3031       gst_event_unref (event);
3032     }
3033   } else {
3034     gst_event_unref (event);
3035   }
3036
3037   return res;
3038 }
3039
3040 static gboolean
3041 gst_rtspsrc_handle_src_sink_event (GstPad * pad, GstObject * parent,
3042     GstEvent * event)
3043 {
3044   GstRTSPStream *stream;
3045
3046   stream = gst_pad_get_element_private (pad);
3047
3048   switch (GST_EVENT_TYPE (event)) {
3049     case GST_EVENT_STREAM_START:{
3050       const gchar *upstream_id;
3051       gchar *stream_id;
3052
3053       gst_event_parse_stream_start (event, &upstream_id);
3054       stream_id = g_strdup_printf ("%s/%s", upstream_id, stream->stream_id);
3055
3056       gst_event_unref (event);
3057       event = gst_event_new_stream_start (stream_id);
3058       g_free (stream_id);
3059       break;
3060     }
3061     default:
3062       break;
3063   }
3064
3065   return gst_pad_push_event (stream->srcpad, event);
3066 }
3067
3068 /* this is the final event function we receive on the internal source pad when
3069  * we deal with TCP connections */
3070 static gboolean
3071 gst_rtspsrc_handle_internal_src_event (GstPad * pad, GstObject * parent,
3072     GstEvent * event)
3073 {
3074   gboolean res;
3075
3076   GST_DEBUG_OBJECT (pad, "received event %s", GST_EVENT_TYPE_NAME (event));
3077
3078   switch (GST_EVENT_TYPE (event)) {
3079     case GST_EVENT_SEEK:
3080     case GST_EVENT_QOS:
3081     case GST_EVENT_NAVIGATION:
3082     case GST_EVENT_LATENCY:
3083     default:
3084       gst_event_unref (event);
3085       res = TRUE;
3086       break;
3087   }
3088   return res;
3089 }
3090
3091 /* this is the final query function we receive on the internal source pad when
3092  * we deal with TCP connections */
3093 static gboolean
3094 gst_rtspsrc_handle_internal_src_query (GstPad * pad, GstObject * parent,
3095     GstQuery * query)
3096 {
3097   GstRTSPSrc *src;
3098   gboolean res = TRUE;
3099
3100   src = GST_RTSPSRC_CAST (gst_pad_get_element_private (pad));
3101
3102   GST_DEBUG_OBJECT (src, "pad %s:%s received query %s",
3103       GST_DEBUG_PAD_NAME (pad), GST_QUERY_TYPE_NAME (query));
3104
3105   switch (GST_QUERY_TYPE (query)) {
3106     case GST_QUERY_POSITION:
3107     {
3108       /* no idea */
3109       break;
3110     }
3111     case GST_QUERY_DURATION:
3112     {
3113       GstFormat format;
3114
3115       gst_query_parse_duration (query, &format, NULL);
3116
3117       switch (format) {
3118         case GST_FORMAT_TIME:
3119           gst_query_set_duration (query, format, src->segment.duration);
3120           break;
3121         default:
3122           res = FALSE;
3123           break;
3124       }
3125       break;
3126     }
3127     case GST_QUERY_LATENCY:
3128     {
3129       /* we are live with a min latency of 0 and unlimited max latency, this
3130        * result will be updated by the session manager if there is any. */
3131       gst_query_set_latency (query, TRUE, 0, -1);
3132       break;
3133     }
3134     default:
3135       break;
3136   }
3137
3138   return res;
3139 }
3140
3141 /* this query is executed on the ghost source pad exposed on rtspsrc. */
3142 static gboolean
3143 gst_rtspsrc_handle_src_query (GstPad * pad, GstObject * parent,
3144     GstQuery * query)
3145 {
3146   GstRTSPSrc *src;
3147   gboolean res = FALSE;
3148
3149   src = GST_RTSPSRC_CAST (parent);
3150
3151   GST_DEBUG_OBJECT (src, "pad %s:%s received query %s",
3152       GST_DEBUG_PAD_NAME (pad), GST_QUERY_TYPE_NAME (query));
3153
3154   switch (GST_QUERY_TYPE (query)) {
3155     case GST_QUERY_DURATION:
3156     {
3157       GstFormat format;
3158
3159       gst_query_parse_duration (query, &format, NULL);
3160
3161       switch (format) {
3162         case GST_FORMAT_TIME:
3163           gst_query_set_duration (query, format, src->segment.duration);
3164           res = TRUE;
3165           break;
3166         default:
3167           break;
3168       }
3169       break;
3170     }
3171     case GST_QUERY_SEEKING:
3172     {
3173       GstFormat format;
3174
3175       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
3176       if (format == GST_FORMAT_TIME) {
3177         gboolean seekable =
3178             src->cur_protocols != GST_RTSP_LOWER_TRANS_UDP_MCAST;
3179         GstClockTime start = 0, duration = src->segment.duration;
3180
3181         /* seeking without duration is unlikely */
3182         seekable = seekable && src->seekable >= 0.0 && src->segment.duration &&
3183             GST_CLOCK_TIME_IS_VALID (src->segment.duration);
3184
3185         if (seekable) {
3186           if (src->seekable > 0.0) {
3187             start = src->last_pos - src->seekable * GST_SECOND;
3188           } else {
3189             /* src->seekable == 0 means that we can only seek to 0 */
3190             start = 0;
3191             duration = 0;
3192           }
3193         }
3194
3195         GST_LOG_OBJECT (src, "seekable : %d", seekable);
3196
3197         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, start,
3198             duration);
3199         res = TRUE;
3200       }
3201       break;
3202     }
3203     case GST_QUERY_URI:
3204     {
3205       gchar *uri;
3206
3207       uri = gst_rtspsrc_uri_get_uri (GST_URI_HANDLER (src));
3208       if (uri != NULL) {
3209         gst_query_set_uri (query, uri);
3210         g_free (uri);
3211         res = TRUE;
3212       }
3213       break;
3214     }
3215     default:
3216     {
3217       GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (pad));
3218
3219       /* forward the query to the proxy target pad */
3220       if (target) {
3221         res = gst_pad_query (target, query);
3222         gst_object_unref (target);
3223       }
3224       break;
3225     }
3226   }
3227
3228   return res;
3229 }
3230
3231 /* callback for RTCP messages to be sent to the server when operating in TCP
3232  * mode. */
3233 static GstFlowReturn
3234 gst_rtspsrc_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
3235 {
3236   GstRTSPSrc *src;
3237   GstRTSPStream *stream;
3238   GstFlowReturn res = GST_FLOW_OK;
3239   GstMapInfo map;
3240   guint8 *data;
3241   guint size;
3242   GstRTSPResult ret;
3243   GstRTSPMessage message = { 0 };
3244   GstRTSPConnInfo *conninfo;
3245
3246   stream = (GstRTSPStream *) gst_pad_get_element_private (pad);
3247   src = stream->parent;
3248
3249   gst_buffer_map (buffer, &map, GST_MAP_READ);
3250   size = map.size;
3251   data = map.data;
3252
3253   gst_rtsp_message_init_data (&message, stream->channel[1]);
3254
3255   /* lend the body data to the message */
3256   gst_rtsp_message_take_body (&message, data, size);
3257
3258   if (stream->conninfo.connection)
3259     conninfo = &stream->conninfo;
3260   else
3261     conninfo = &src->conninfo;
3262
3263   GST_DEBUG_OBJECT (src, "sending %u bytes RTCP", size);
3264   ret = gst_rtspsrc_connection_send (src, conninfo, &message, NULL);
3265   GST_DEBUG_OBJECT (src, "sent RTCP, %d", ret);
3266
3267   /* and steal it away again because we will free it when unreffing the
3268    * buffer */
3269   gst_rtsp_message_steal_body (&message, &data, &size);
3270   gst_rtsp_message_unset (&message);
3271
3272   gst_buffer_unmap (buffer, &map);
3273   gst_buffer_unref (buffer);
3274
3275   return res;
3276 }
3277
3278 static GstFlowReturn
3279 gst_rtspsrc_push_backchannel_buffer (GstRTSPSrc * src, guint id,
3280     GstSample * sample)
3281 {
3282   GstFlowReturn res = GST_FLOW_OK;
3283   GstRTSPStream *stream;
3284
3285   if (!src->conninfo.connected || src->state != GST_RTSP_STATE_PLAYING)
3286     goto out;
3287
3288   stream = find_stream (src, &id, (gpointer) find_stream_by_id);
3289   if (stream == NULL) {
3290     GST_ERROR_OBJECT (src, "no stream with id %u", id);
3291     goto out;
3292   }
3293
3294   if (src->interleaved) {
3295     GstBuffer *buffer;
3296     GstMapInfo map;
3297     guint8 *data;
3298     guint size;
3299     GstRTSPResult ret;
3300     GstRTSPMessage message = { 0 };
3301     GstRTSPConnInfo *conninfo;
3302
3303     buffer = gst_sample_get_buffer (sample);
3304
3305     gst_buffer_map (buffer, &map, GST_MAP_READ);
3306     size = map.size;
3307     data = map.data;
3308
3309     gst_rtsp_message_init_data (&message, stream->channel[0]);
3310
3311     /* lend the body data to the message */
3312     gst_rtsp_message_take_body (&message, data, size);
3313
3314     if (stream->conninfo.connection)
3315       conninfo = &stream->conninfo;
3316     else
3317       conninfo = &src->conninfo;
3318
3319     GST_DEBUG_OBJECT (src, "sending %u bytes backchannel RTP", size);
3320     ret = gst_rtspsrc_connection_send (src, conninfo, &message, NULL);
3321     GST_DEBUG_OBJECT (src, "sent backchannel RTP, %d", ret);
3322
3323     /* and steal it away again because we will free it when unreffing the
3324      * buffer */
3325     gst_rtsp_message_steal_body (&message, &data, &size);
3326     gst_rtsp_message_unset (&message);
3327
3328     gst_buffer_unmap (buffer, &map);
3329
3330     res = GST_FLOW_OK;
3331   } else {
3332     g_signal_emit_by_name (stream->rtpsrc, "push-sample", sample, &res);
3333     GST_DEBUG_OBJECT (src, "sent backchannel RTP sample %p: %s", sample,
3334         gst_flow_get_name (res));
3335   }
3336
3337 out:
3338   gst_sample_unref (sample);
3339
3340   return res;
3341 }
3342
3343 static GstPadProbeReturn
3344 pad_blocked (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
3345 {
3346   GstRTSPSrc *src = user_data;
3347
3348   GST_DEBUG_OBJECT (src, "pad %s:%s blocked, activating streams",
3349       GST_DEBUG_PAD_NAME (pad));
3350
3351   /* activate the streams */
3352   GST_OBJECT_LOCK (src);
3353   if (!src->need_activate)
3354     goto was_ok;
3355
3356   src->need_activate = FALSE;
3357   GST_OBJECT_UNLOCK (src);
3358
3359   gst_rtspsrc_activate_streams (src);
3360
3361   return GST_PAD_PROBE_OK;
3362
3363 was_ok:
3364   {
3365     GST_OBJECT_UNLOCK (src);
3366     return GST_PAD_PROBE_OK;
3367   }
3368 }
3369
3370 static GstPadProbeReturn
3371 udpsrc_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
3372 {
3373   guint32 *segment_seqnum = user_data;
3374
3375   switch (GST_EVENT_TYPE (info->data)) {
3376     case GST_EVENT_SEGMENT:
3377       if (!gst_event_is_writable (info->data))
3378         info->data = gst_event_make_writable (info->data);
3379
3380       *segment_seqnum = gst_event_get_seqnum (info->data);
3381     default:
3382       break;
3383   }
3384
3385   return GST_PAD_PROBE_OK;
3386 }
3387
3388 static gboolean
3389 copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
3390 {
3391   GstPad *gpad = GST_PAD_CAST (user_data);
3392
3393   GST_DEBUG_OBJECT (gpad, "store sticky event %" GST_PTR_FORMAT, *event);
3394   gst_pad_store_sticky_event (gpad, *event);
3395
3396   return TRUE;
3397 }
3398
3399 static gboolean
3400 add_backchannel_fakesink (GstRTSPSrc * src, GstRTSPStream * stream,
3401     GstPad * srcpad)
3402 {
3403   GstPad *sinkpad;
3404   GstElement *fakesink;
3405
3406   fakesink = gst_element_factory_make ("fakesink", NULL);
3407   if (fakesink == NULL) {
3408     GST_ERROR_OBJECT (src, "no fakesink");
3409     return FALSE;
3410   }
3411
3412   sinkpad = gst_element_get_static_pad (fakesink, "sink");
3413
3414   GST_DEBUG_OBJECT (src, "backchannel stream %p, hooking fakesink", stream);
3415
3416   gst_bin_add (GST_BIN_CAST (src), fakesink);
3417   if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK) {
3418     GST_WARNING_OBJECT (src, "could not link to fakesink");
3419     return FALSE;
3420   }
3421
3422   gst_object_unref (sinkpad);
3423
3424   gst_element_sync_state_with_parent (fakesink);
3425   return TRUE;
3426 }
3427
3428 /* this callback is called when the session manager generated a new src pad with
3429  * payloaded RTP packets. We simply ghost the pad here. */
3430 static void
3431 new_manager_pad (GstElement * manager, GstPad * pad, GstRTSPSrc * src)
3432 {
3433   gchar *name;
3434   GstPadTemplate *template;
3435   gint id, ssrc, pt;
3436   GList *ostreams;
3437   GstRTSPStream *stream;
3438   gboolean all_added;
3439   GstPad *internal_src;
3440
3441   GST_DEBUG_OBJECT (src, "got new manager pad %" GST_PTR_FORMAT, pad);
3442
3443   GST_RTSP_STATE_LOCK (src);
3444   /* find stream */
3445   name = gst_object_get_name (GST_OBJECT_CAST (pad));
3446   if (sscanf (name, "recv_rtp_src_%u_%u_%u", &id, &ssrc, &pt) != 3)
3447     goto unknown_stream;
3448
3449   GST_DEBUG_OBJECT (src, "stream: %u, SSRC %08x, PT %d", id, ssrc, pt);
3450
3451   stream = find_stream (src, &id, (gpointer) find_stream_by_id);
3452   if (stream == NULL)
3453     goto unknown_stream;
3454
3455   /* save SSRC */
3456   stream->ssrc = ssrc;
3457
3458   /* we'll add it later see below */
3459   stream->added = TRUE;
3460
3461   /* check if we added all streams */
3462   all_added = TRUE;
3463   for (ostreams = src->streams; ostreams; ostreams = g_list_next (ostreams)) {
3464     GstRTSPStream *ostream = (GstRTSPStream *) ostreams->data;
3465
3466     GST_DEBUG_OBJECT (src, "stream %p, container %d, added %d, setup %d",
3467         ostream, ostream->container, ostream->added, ostream->setup);
3468
3469     /* if we find a stream for which we did a setup that is not added, we
3470      * need to wait some more */
3471     if (ostream->setup && !ostream->added) {
3472       all_added = FALSE;
3473       break;
3474     }
3475   }
3476   GST_RTSP_STATE_UNLOCK (src);
3477
3478   /* create a new pad we will use to stream to */
3479   template = gst_static_pad_template_get (&rtptemplate);
3480   stream->srcpad = gst_ghost_pad_new_from_template (name, pad, template);
3481   gst_object_unref (template);
3482   g_free (name);
3483
3484   /* We intercept and modify the stream start event */
3485   internal_src =
3486       GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (stream->srcpad)));
3487   gst_pad_set_element_private (internal_src, stream);
3488   gst_pad_set_event_function (internal_src, gst_rtspsrc_handle_src_sink_event);
3489   gst_object_unref (internal_src);
3490
3491   gst_pad_set_event_function (stream->srcpad, gst_rtspsrc_handle_src_event);
3492   gst_pad_set_query_function (stream->srcpad, gst_rtspsrc_handle_src_query);
3493   gst_pad_set_active (stream->srcpad, TRUE);
3494   gst_pad_sticky_events_foreach (pad, copy_sticky_events, stream->srcpad);
3495
3496   /* don't add the srcpad if this is a sendonly stream */
3497   if (stream->is_backchannel)
3498     add_backchannel_fakesink (src, stream, stream->srcpad);
3499   else
3500     gst_element_add_pad (GST_ELEMENT_CAST (src), stream->srcpad);
3501
3502   if (all_added) {
3503     GST_DEBUG_OBJECT (src, "We added all streams");
3504     /* when we get here, all stream are added and we can fire the no-more-pads
3505      * signal. */
3506     gst_element_no_more_pads (GST_ELEMENT_CAST (src));
3507   }
3508
3509   return;
3510
3511   /* ERRORS */
3512 unknown_stream:
3513   {
3514     GST_DEBUG_OBJECT (src, "ignoring unknown stream");
3515     GST_RTSP_STATE_UNLOCK (src);
3516     g_free (name);
3517     return;
3518   }
3519 }
3520
3521 static GstCaps *
3522 stream_get_caps_for_pt (GstRTSPStream * stream, guint pt)
3523 {
3524   guint i, len;
3525
3526   len = stream->ptmap->len;
3527   for (i = 0; i < len; i++) {
3528     PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, i);
3529     if (item->pt == pt)
3530       return item->caps;
3531   }
3532   return NULL;
3533 }
3534
3535 static GstCaps *
3536 request_pt_map (GstElement * manager, guint session, guint pt, GstRTSPSrc * src)
3537 {
3538   GstRTSPStream *stream;
3539   GstCaps *caps;
3540
3541   GST_DEBUG_OBJECT (src, "getting pt map for pt %d in session %d", pt, session);
3542
3543   GST_RTSP_STATE_LOCK (src);
3544   stream = find_stream (src, &session, (gpointer) find_stream_by_id);
3545   if (!stream)
3546     goto unknown_stream;
3547
3548   if ((caps = stream_get_caps_for_pt (stream, pt)))
3549     gst_caps_ref (caps);
3550   GST_RTSP_STATE_UNLOCK (src);
3551
3552   return caps;
3553
3554 unknown_stream:
3555   {
3556     GST_DEBUG_OBJECT (src, "unknown stream %d", session);
3557     GST_RTSP_STATE_UNLOCK (src);
3558     return NULL;
3559   }
3560 }
3561
3562 static void
3563 gst_rtspsrc_do_stream_eos (GstRTSPSrc * src, GstRTSPStream * stream)
3564 {
3565   GST_DEBUG_OBJECT (src, "setting stream for session %u to EOS", stream->id);
3566
3567   if (stream->eos)
3568     goto was_eos;
3569
3570   stream->eos = TRUE;
3571   gst_rtspsrc_stream_push_event (src, stream, gst_event_new_eos ());
3572   return;
3573
3574   /* ERRORS */
3575 was_eos:
3576   {
3577     GST_DEBUG_OBJECT (src, "stream for session %u was already EOS", stream->id);
3578     return;
3579   }
3580 }
3581
3582 static void
3583 on_bye_ssrc (GObject * session, GObject * source, GstRTSPStream * stream)
3584 {
3585   GstRTSPSrc *src = stream->parent;
3586   guint ssrc;
3587
3588   g_object_get (source, "ssrc", &ssrc, NULL);
3589
3590   GST_DEBUG_OBJECT (src, "source %08x, stream %08x, session %u received BYE",
3591       ssrc, stream->ssrc, stream->id);
3592
3593   if (ssrc == stream->ssrc)
3594     gst_rtspsrc_do_stream_eos (src, stream);
3595 }
3596
3597 static void
3598 on_timeout_common (GObject * session, GObject * source, GstRTSPStream * stream)
3599 {
3600   GstRTSPSrc *src = stream->parent;
3601   guint ssrc;
3602
3603   g_object_get (source, "ssrc", &ssrc, NULL);
3604
3605   GST_WARNING_OBJECT (src, "source %08x, stream %08x in session %u timed out",
3606       ssrc, stream->ssrc, stream->id);
3607
3608   if (ssrc == stream->ssrc)
3609     gst_rtspsrc_do_stream_eos (src, stream);
3610 }
3611
3612 static void
3613 on_timeout (GObject * session, GObject * source, GstRTSPStream * stream)
3614 {
3615   GstRTSPSrc *src = stream->parent;
3616
3617   /* timeout, post element message */
3618   gst_element_post_message (GST_ELEMENT_CAST (src),
3619       gst_message_new_element (GST_OBJECT_CAST (src),
3620           gst_structure_new ("GstRTSPSrcTimeout",
3621               "cause", G_TYPE_ENUM, GST_RTSP_SRC_TIMEOUT_CAUSE_RTCP,
3622               "stream-number", G_TYPE_INT, stream->id, "ssrc", G_TYPE_UINT,
3623               stream->ssrc, NULL)));
3624
3625   on_timeout_common (session, source, stream);
3626 }
3627
3628 static void
3629 on_npt_stop (GstElement * rtpbin, guint session, guint ssrc, GstRTSPSrc * src)
3630 {
3631   GstRTSPStream *stream;
3632
3633   GST_DEBUG_OBJECT (src, "source in session %u reached NPT stop", session);
3634
3635   /* get stream for session */
3636   stream = find_stream (src, &session, (gpointer) find_stream_by_id);
3637   if (stream) {
3638     gst_rtspsrc_do_stream_eos (src, stream);
3639   }
3640 }
3641
3642 static void
3643 on_ssrc_active (GObject * session, GObject * source, GstRTSPStream * stream)
3644 {
3645   GST_DEBUG_OBJECT (stream->parent, "source in session %u is active",
3646       stream->id);
3647 }
3648
3649 static void
3650 set_manager_buffer_mode (GstRTSPSrc * src)
3651 {
3652   GObjectClass *klass;
3653
3654   if (src->manager == NULL)
3655     return;
3656
3657   klass = G_OBJECT_GET_CLASS (G_OBJECT (src->manager));
3658
3659   if (!g_object_class_find_property (klass, "buffer-mode"))
3660     return;
3661
3662   if (src->buffer_mode != BUFFER_MODE_AUTO) {
3663     g_object_set (src->manager, "buffer-mode", src->buffer_mode, NULL);
3664
3665     return;
3666   }
3667
3668   GST_DEBUG_OBJECT (src,
3669       "auto buffering mode, have clock %" GST_PTR_FORMAT, src->provided_clock);
3670
3671   if (src->provided_clock) {
3672     GstClock *clock = gst_element_get_clock (GST_ELEMENT_CAST (src));
3673
3674     if (clock == src->provided_clock) {
3675       GST_DEBUG_OBJECT (src, "selected synced");
3676       g_object_set (src->manager, "buffer-mode", BUFFER_MODE_SYNCED, NULL);
3677
3678       if (clock)
3679         gst_object_unref (clock);
3680
3681       return;
3682     }
3683
3684     /* Otherwise fall-through and use another buffer mode */
3685     if (clock)
3686       gst_object_unref (clock);
3687   }
3688
3689   GST_DEBUG_OBJECT (src, "auto buffering mode");
3690   if (src->use_buffering) {
3691     GST_DEBUG_OBJECT (src, "selected buffer");
3692     g_object_set (src->manager, "buffer-mode", BUFFER_MODE_BUFFER, NULL);
3693   } else {
3694     GST_DEBUG_OBJECT (src, "selected slave");
3695     g_object_set (src->manager, "buffer-mode", BUFFER_MODE_SLAVE, NULL);
3696   }
3697 }
3698
3699 static GstCaps *
3700 request_key (GstElement * srtpdec, guint ssrc, GstRTSPStream * stream)
3701 {
3702   guint i;
3703   GstCaps *caps;
3704   GstMIKEYMessage *msg = stream->mikey;
3705
3706   GST_DEBUG ("request key SSRC %u", ssrc);
3707
3708   caps = gst_caps_ref (stream_get_caps_for_pt (stream, stream->default_pt));
3709   caps = gst_caps_make_writable (caps);
3710
3711   /* parse crypto sessions and look for the SSRC rollover counter */
3712   msg = stream->mikey;
3713   for (i = 0; msg && i < gst_mikey_message_get_n_cs (msg); i++) {
3714     const GstMIKEYMapSRTP *map = gst_mikey_message_get_cs_srtp (msg, i);
3715
3716     if (ssrc == map->ssrc) {
3717       gst_caps_set_simple (caps, "roc", G_TYPE_UINT, map->roc, NULL);
3718       break;
3719     }
3720   }
3721
3722   return caps;
3723 }
3724
3725 static GstElement *
3726 request_rtp_decoder (GstElement * rtpbin, guint session, GstRTSPStream * stream)
3727 {
3728   GST_DEBUG ("decoder session %u, stream %p, %d", session, stream, stream->id);
3729   if (stream->id != session)
3730     return NULL;
3731
3732   if (stream->profile != GST_RTSP_PROFILE_SAVP &&
3733       stream->profile != GST_RTSP_PROFILE_SAVPF)
3734     return NULL;
3735
3736   if (stream->srtpdec == NULL) {
3737     gchar *name;
3738
3739     name = g_strdup_printf ("srtpdec_%u", session);
3740     stream->srtpdec = gst_element_factory_make ("srtpdec", name);
3741     g_free (name);
3742
3743     if (stream->srtpdec == NULL) {
3744       GST_ELEMENT_ERROR (stream->parent, CORE, MISSING_PLUGIN, (NULL),
3745           ("no srtpdec element present!"));
3746       return NULL;
3747     }
3748     g_signal_connect (stream->srtpdec, "request-key",
3749         (GCallback) request_key, stream);
3750   }
3751   return gst_object_ref (stream->srtpdec);
3752 }
3753
3754 static GstElement *
3755 request_rtcp_encoder (GstElement * rtpbin, guint session,
3756     GstRTSPStream * stream)
3757 {
3758   gchar *name;
3759   GstPad *pad;
3760
3761   GST_DEBUG ("decoder session %u, stream %p, %d", session, stream, stream->id);
3762   if (stream->id != session)
3763     return NULL;
3764
3765   if (stream->profile != GST_RTSP_PROFILE_SAVP &&
3766       stream->profile != GST_RTSP_PROFILE_SAVPF)
3767     return NULL;
3768
3769   if (stream->srtpenc == NULL) {
3770     GstStructure *s;
3771
3772     name = g_strdup_printf ("srtpenc_%u", session);
3773     stream->srtpenc = gst_element_factory_make ("srtpenc", name);
3774     g_free (name);
3775
3776     if (stream->srtpenc == NULL) {
3777       GST_ELEMENT_ERROR (stream->parent, CORE, MISSING_PLUGIN, (NULL),
3778           ("no srtpenc element present!"));
3779       return NULL;
3780     }
3781
3782     /* get RTCP crypto parameters from caps */
3783     s = gst_caps_get_structure (stream->srtcpparams, 0);
3784     if (s) {
3785       GstBuffer *buf;
3786       const gchar *str;
3787       GType ciphertype, authtype;
3788       GValue rtcp_cipher = G_VALUE_INIT, rtcp_auth = G_VALUE_INIT;
3789
3790       ciphertype = g_type_from_name ("GstSrtpCipherType");
3791       authtype = g_type_from_name ("GstSrtpAuthType");
3792       g_value_init (&rtcp_cipher, ciphertype);
3793       g_value_init (&rtcp_auth, authtype);
3794
3795       str = gst_structure_get_string (s, "srtcp-cipher");
3796       gst_value_deserialize (&rtcp_cipher, str);
3797       str = gst_structure_get_string (s, "srtcp-auth");
3798       gst_value_deserialize (&rtcp_auth, str);
3799       gst_structure_get (s, "srtp-key", GST_TYPE_BUFFER, &buf, NULL);
3800
3801       g_object_set_property (G_OBJECT (stream->srtpenc), "rtp-cipher",
3802           &rtcp_cipher);
3803       g_object_set_property (G_OBJECT (stream->srtpenc), "rtp-auth",
3804           &rtcp_auth);
3805       g_object_set_property (G_OBJECT (stream->srtpenc), "rtcp-cipher",
3806           &rtcp_cipher);
3807       g_object_set_property (G_OBJECT (stream->srtpenc), "rtcp-auth",
3808           &rtcp_auth);
3809       g_object_set (stream->srtpenc, "key", buf, NULL);
3810
3811       g_value_unset (&rtcp_cipher);
3812       g_value_unset (&rtcp_auth);
3813       gst_buffer_unref (buf);
3814     }
3815   }
3816   name = g_strdup_printf ("rtcp_sink_%d", session);
3817   pad = gst_element_get_request_pad (stream->srtpenc, name);
3818   g_free (name);
3819   gst_object_unref (pad);
3820
3821   return gst_object_ref (stream->srtpenc);
3822 }
3823
3824 static GstElement *
3825 request_aux_receiver (GstElement * rtpbin, guint sessid, GstRTSPSrc * src)
3826 {
3827   GstElement *rtx, *bin;
3828   GstPad *pad;
3829   gchar *name;
3830   GstRTSPStream *stream;
3831
3832   stream = find_stream (src, &sessid, (gpointer) find_stream_by_id);
3833   if (!stream) {
3834     GST_WARNING_OBJECT (src, "Stream %u not found", sessid);
3835     return NULL;
3836   }
3837
3838   GST_INFO_OBJECT (src, "creating retransmision receiver for session %u "
3839       "with map %" GST_PTR_FORMAT, sessid, stream->rtx_pt_map);
3840   bin = gst_bin_new (NULL);
3841   rtx = gst_element_factory_make ("rtprtxreceive", NULL);
3842   g_object_set (rtx, "payload-type-map", stream->rtx_pt_map, NULL);
3843   gst_bin_add (GST_BIN (bin), rtx);
3844
3845   pad = gst_element_get_static_pad (rtx, "src");
3846   name = g_strdup_printf ("src_%u", sessid);
3847   gst_element_add_pad (bin, gst_ghost_pad_new (name, pad));
3848   g_free (name);
3849   gst_object_unref (pad);
3850
3851   pad = gst_element_get_static_pad (rtx, "sink");
3852   name = g_strdup_printf ("sink_%u", sessid);
3853   gst_element_add_pad (bin, gst_ghost_pad_new (name, pad));
3854   g_free (name);
3855   gst_object_unref (pad);
3856
3857   return bin;
3858 }
3859
3860 static void
3861 add_retransmission (GstRTSPSrc * src, GstRTSPTransport * transport)
3862 {
3863   GList *walk;
3864   guint signal_id;
3865   gboolean do_retransmission = FALSE;
3866
3867   if (transport->trans != GST_RTSP_TRANS_RTP)
3868     return;
3869   if (transport->profile != GST_RTSP_PROFILE_AVPF &&
3870       transport->profile != GST_RTSP_PROFILE_SAVPF)
3871     return;
3872
3873   signal_id = g_signal_lookup ("request-aux-receiver",
3874       G_OBJECT_TYPE (src->manager));
3875   /* there's already something connected */
3876   if (g_signal_handler_find (src->manager, G_SIGNAL_MATCH_ID, signal_id, 0,
3877           NULL, NULL, NULL) != 0) {
3878     GST_DEBUG_OBJECT (src, "Not adding RTX AUX element as "
3879         "\"request-aux-receiver\" signal is "
3880         "already used by the application");
3881     return;
3882   }
3883
3884   /* build the retransmission payload type map */
3885   for (walk = src->streams; walk; walk = g_list_next (walk)) {
3886     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
3887     gboolean do_retransmission_stream = FALSE;
3888     int i;
3889
3890     if (stream->rtx_pt_map)
3891       gst_structure_free (stream->rtx_pt_map);
3892     stream->rtx_pt_map = gst_structure_new_empty ("application/x-rtp-pt-map");
3893
3894     for (i = 0; i < stream->ptmap->len; i++) {
3895       PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, i);
3896       GstStructure *s = gst_caps_get_structure (item->caps, 0);
3897       const gchar *encoding;
3898
3899       /* we only care about RTX streams */
3900       if ((encoding = gst_structure_get_string (s, "encoding-name"))
3901           && g_strcmp0 (encoding, "RTX") == 0) {
3902         const gchar *stream_pt_s;
3903         gint rtx_pt;
3904
3905         if (gst_structure_get_int (s, "payload", &rtx_pt)
3906             && (stream_pt_s = gst_structure_get_string (s, "apt"))) {
3907
3908           if (rtx_pt != 0) {
3909             gst_structure_set (stream->rtx_pt_map, stream_pt_s, G_TYPE_UINT,
3910                 rtx_pt, NULL);
3911             do_retransmission_stream = TRUE;
3912           }
3913         }
3914       }
3915     }
3916
3917     if (do_retransmission_stream) {
3918       GST_DEBUG_OBJECT (src, "built retransmission payload map for stream "
3919           "id %i: %" GST_PTR_FORMAT, stream->id, stream->rtx_pt_map);
3920       do_retransmission = TRUE;
3921     } else {
3922       GST_DEBUG_OBJECT (src, "no retransmission payload map for stream "
3923           "id %i", stream->id);
3924       gst_structure_free (stream->rtx_pt_map);
3925       stream->rtx_pt_map = NULL;
3926     }
3927   }
3928
3929   if (do_retransmission) {
3930     GST_DEBUG_OBJECT (src, "Enabling retransmissions");
3931
3932     g_object_set (src->manager, "do-retransmission", TRUE, NULL);
3933
3934     /* enable RFC4588 retransmission handling by setting rtprtxreceive
3935      * as the "aux" element of rtpbin */
3936     g_signal_connect (src->manager, "request-aux-receiver",
3937         (GCallback) request_aux_receiver, src);
3938   } else {
3939     GST_DEBUG_OBJECT (src,
3940         "Not enabling retransmissions as no stream had a retransmission payload map");
3941   }
3942 }
3943
3944 /* try to get and configure a manager */
3945 static gboolean
3946 gst_rtspsrc_stream_configure_manager (GstRTSPSrc * src, GstRTSPStream * stream,
3947     GstRTSPTransport * transport)
3948 {
3949   const gchar *manager;
3950   gchar *name;
3951   GstStateChangeReturn ret;
3952
3953   /* find a manager */
3954   if (gst_rtsp_transport_get_manager (transport->trans, &manager, 0) < 0)
3955     goto no_manager;
3956
3957   if (manager) {
3958     GST_DEBUG_OBJECT (src, "using manager %s", manager);
3959
3960     /* configure the manager */
3961     if (src->manager == NULL) {
3962       GObjectClass *klass;
3963
3964       if (!(src->manager = gst_element_factory_make (manager, "manager"))) {
3965         /* fallback */
3966         if (gst_rtsp_transport_get_manager (transport->trans, &manager, 1) < 0)
3967           goto no_manager;
3968
3969         if (!manager)
3970           goto use_no_manager;
3971
3972         if (!(src->manager = gst_element_factory_make (manager, "manager")))
3973           goto manager_failed;
3974       }
3975 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
3976       if (g_strcmp0 (manager, "rtpbin") == 0) {
3977           /* set for player rtsp buffering */
3978           g_object_set (src->manager, "use-rtsp-buffering", TRUE, NULL);
3979       }
3980 #endif
3981
3982       /* we manage this element */
3983       gst_element_set_locked_state (src->manager, TRUE);
3984       gst_bin_add (GST_BIN_CAST (src), src->manager);
3985
3986       ret = gst_element_set_state (src->manager, GST_STATE_PAUSED);
3987       if (ret == GST_STATE_CHANGE_FAILURE)
3988         goto start_manager_failure;
3989
3990       g_object_set (src->manager, "latency", src->latency, NULL);
3991
3992       klass = G_OBJECT_GET_CLASS (G_OBJECT (src->manager));
3993
3994       if (g_object_class_find_property (klass, "ntp-sync")) {
3995         g_object_set (src->manager, "ntp-sync", src->ntp_sync, NULL);
3996       }
3997
3998       if (g_object_class_find_property (klass, "rfc7273-sync")) {
3999         g_object_set (src->manager, "rfc7273-sync", src->rfc7273_sync, NULL);
4000       }
4001
4002       if (src->use_pipeline_clock) {
4003         if (g_object_class_find_property (klass, "use-pipeline-clock")) {
4004           g_object_set (src->manager, "use-pipeline-clock", TRUE, NULL);
4005         }
4006       } else {
4007         if (g_object_class_find_property (klass, "ntp-time-source")) {
4008           g_object_set (src->manager, "ntp-time-source", src->ntp_time_source,
4009               NULL);
4010         }
4011       }
4012
4013       if (src->sdes && g_object_class_find_property (klass, "sdes")) {
4014         g_object_set (src->manager, "sdes", src->sdes, NULL);
4015       }
4016
4017       if (g_object_class_find_property (klass, "drop-on-latency")) {
4018         g_object_set (src->manager, "drop-on-latency", src->drop_on_latency,
4019             NULL);
4020       }
4021
4022       if (g_object_class_find_property (klass, "max-rtcp-rtp-time-diff")) {
4023         g_object_set (src->manager, "max-rtcp-rtp-time-diff",
4024             src->max_rtcp_rtp_time_diff, NULL);
4025       }
4026
4027       if (g_object_class_find_property (klass, "max-ts-offset-adjustment")) {
4028         g_object_set (src->manager, "max-ts-offset-adjustment",
4029             src->max_ts_offset_adjustment, NULL);
4030       }
4031
4032       if (g_object_class_find_property (klass, "max-ts-offset")) {
4033         gint64 max_ts_offset;
4034
4035         /* setting max-ts-offset in the manager has side effects so only do it
4036          * if the value differs */
4037         g_object_get (src->manager, "max-ts-offset", &max_ts_offset, NULL);
4038         if (max_ts_offset != src->max_ts_offset) {
4039           g_object_set (src->manager, "max-ts-offset", src->max_ts_offset,
4040               NULL);
4041         }
4042       }
4043
4044       /* buffer mode pauses are handled by adding offsets to buffer times,
4045        * but some depayloaders may have a hard time syncing output times
4046        * with such input times, e.g. container ones, most notably ASF */
4047       /* TODO alternatives are having an event that indicates these shifts,
4048        * or having rtsp extensions provide suggestion on buffer mode */
4049       /* valid duration implies not likely live pipeline,
4050        * so slaving in jitterbuffer does not make much sense
4051        * (and might mess things up due to bursts) */
4052       if (GST_CLOCK_TIME_IS_VALID (src->segment.duration) &&
4053           src->segment.duration && stream->container) {
4054         src->use_buffering = TRUE;
4055       } else {
4056         src->use_buffering = FALSE;
4057       }
4058
4059       set_manager_buffer_mode (src);
4060
4061       /* connect to signals */
4062       GST_DEBUG_OBJECT (src, "connect to signals on session manager, stream %p",
4063           stream);
4064       src->manager_sig_id =
4065           g_signal_connect (src->manager, "pad-added",
4066           (GCallback) new_manager_pad, src);
4067       src->manager_ptmap_id =
4068           g_signal_connect (src->manager, "request-pt-map",
4069           (GCallback) request_pt_map, src);
4070
4071       g_signal_connect (src->manager, "on-npt-stop", (GCallback) on_npt_stop,
4072           src);
4073
4074       g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_NEW_MANAGER], 0,
4075           src->manager);
4076
4077       if (src->do_retransmission)
4078         add_retransmission (src, transport);
4079     }
4080     g_signal_connect (src->manager, "request-rtp-decoder",
4081         (GCallback) request_rtp_decoder, stream);
4082     g_signal_connect (src->manager, "request-rtcp-decoder",
4083         (GCallback) request_rtp_decoder, stream);
4084     g_signal_connect (src->manager, "request-rtcp-encoder",
4085         (GCallback) request_rtcp_encoder, stream);
4086
4087     /* we stream directly to the manager, get some pads. Each RTSP stream goes
4088      * into a separate RTP session. */
4089     name = g_strdup_printf ("recv_rtp_sink_%u", stream->id);
4090     stream->channelpad[0] = gst_element_get_request_pad (src->manager, name);
4091     g_free (name);
4092     name = g_strdup_printf ("recv_rtcp_sink_%u", stream->id);
4093     stream->channelpad[1] = gst_element_get_request_pad (src->manager, name);
4094     g_free (name);
4095
4096     /* now configure the bandwidth in the manager */
4097     if (g_signal_lookup ("get-internal-session",
4098             G_OBJECT_TYPE (src->manager)) != 0) {
4099       GObject *rtpsession;
4100
4101       g_signal_emit_by_name (src->manager, "get-internal-session", stream->id,
4102           &rtpsession);
4103       if (rtpsession) {
4104         GstRTPProfile rtp_profile;
4105
4106         GST_INFO_OBJECT (src, "configure bandwidth in session %p", rtpsession);
4107
4108         stream->session = rtpsession;
4109
4110         if (stream->as_bandwidth != -1) {
4111           GST_INFO_OBJECT (src, "setting AS: %f",
4112               (gdouble) (stream->as_bandwidth * 1000));
4113           g_object_set (rtpsession, "bandwidth",
4114               (gdouble) (stream->as_bandwidth * 1000), NULL);
4115         }
4116         if (stream->rr_bandwidth != -1) {
4117           GST_INFO_OBJECT (src, "setting RR: %u", stream->rr_bandwidth);
4118           g_object_set (rtpsession, "rtcp-rr-bandwidth", stream->rr_bandwidth,
4119               NULL);
4120         }
4121         if (stream->rs_bandwidth != -1) {
4122           GST_INFO_OBJECT (src, "setting RS: %u", stream->rs_bandwidth);
4123           g_object_set (rtpsession, "rtcp-rs-bandwidth", stream->rs_bandwidth,
4124               NULL);
4125         }
4126
4127         switch (stream->profile) {
4128           case GST_RTSP_PROFILE_AVPF:
4129             rtp_profile = GST_RTP_PROFILE_AVPF;
4130             break;
4131           case GST_RTSP_PROFILE_SAVP:
4132             rtp_profile = GST_RTP_PROFILE_SAVP;
4133             break;
4134           case GST_RTSP_PROFILE_SAVPF:
4135             rtp_profile = GST_RTP_PROFILE_SAVPF;
4136             break;
4137           case GST_RTSP_PROFILE_AVP:
4138           default:
4139             rtp_profile = GST_RTP_PROFILE_AVP;
4140             break;
4141         }
4142
4143         g_object_set (rtpsession, "rtp-profile", rtp_profile, NULL);
4144
4145         g_object_set (rtpsession, "probation", src->probation, NULL);
4146
4147         g_object_set (rtpsession, "internal-ssrc", stream->send_ssrc, NULL);
4148
4149         g_signal_connect (rtpsession, "on-bye-ssrc", (GCallback) on_bye_ssrc,
4150             stream);
4151         g_signal_connect (rtpsession, "on-bye-timeout",
4152             (GCallback) on_timeout_common, stream);
4153         g_signal_connect (rtpsession, "on-timeout", (GCallback) on_timeout,
4154             stream);
4155         g_signal_connect (rtpsession, "on-ssrc-active",
4156             (GCallback) on_ssrc_active, stream);
4157       }
4158     }
4159   }
4160
4161 use_no_manager:
4162   return TRUE;
4163
4164   /* ERRORS */
4165 no_manager:
4166   {
4167     GST_DEBUG_OBJECT (src, "cannot get a session manager");
4168     return FALSE;
4169   }
4170 manager_failed:
4171   {
4172     GST_DEBUG_OBJECT (src, "no session manager element %s found", manager);
4173     return FALSE;
4174   }
4175 start_manager_failure:
4176   {
4177     GST_DEBUG_OBJECT (src, "could not start session manager");
4178     return FALSE;
4179   }
4180 }
4181
4182 /* free the UDP sources allocated when negotiating a transport.
4183  * This function is called when the server negotiated to a transport where the
4184  * UDP sources are not needed anymore, such as TCP or multicast. */
4185 static void
4186 gst_rtspsrc_stream_free_udp (GstRTSPStream * stream)
4187 {
4188   gint i;
4189
4190   for (i = 0; i < 2; i++) {
4191     if (stream->udpsrc[i]) {
4192       GST_DEBUG ("free UDP source %d for stream %p", i, stream);
4193       gst_element_set_state (stream->udpsrc[i], GST_STATE_NULL);
4194       gst_object_unref (stream->udpsrc[i]);
4195       stream->udpsrc[i] = NULL;
4196     }
4197   }
4198 }
4199
4200 /* for TCP, create pads to send and receive data to and from the manager and to
4201  * intercept various events and queries
4202  */
4203 static gboolean
4204 gst_rtspsrc_stream_configure_tcp (GstRTSPSrc * src, GstRTSPStream * stream,
4205     GstRTSPTransport * transport, GstPad ** outpad)
4206 {
4207   gchar *name;
4208   GstPadTemplate *template;
4209   GstPad *pad0, *pad1;
4210
4211   /* configure for interleaved delivery, nothing needs to be done
4212    * here, the loop function will call the chain functions of the
4213    * session manager. */
4214   stream->channel[0] = transport->interleaved.min;
4215   stream->channel[1] = transport->interleaved.max;
4216   GST_DEBUG_OBJECT (src, "stream %p on channels %d-%d", stream,
4217       stream->channel[0], stream->channel[1]);
4218
4219   /* we can remove the allocated UDP ports now */
4220   gst_rtspsrc_stream_free_udp (stream);
4221
4222   /* no session manager, send data to srcpad directly */
4223   if (!stream->channelpad[0]) {
4224     GST_DEBUG_OBJECT (src, "no manager, creating pad");
4225
4226     /* create a new pad we will use to stream to */
4227     name = g_strdup_printf ("stream_%u", stream->id);
4228     template = gst_static_pad_template_get (&rtptemplate);
4229     stream->channelpad[0] = gst_pad_new_from_template (template, name);
4230     gst_object_unref (template);
4231     g_free (name);
4232
4233     /* set caps and activate */
4234     gst_pad_use_fixed_caps (stream->channelpad[0]);
4235     gst_pad_set_active (stream->channelpad[0], TRUE);
4236
4237     *outpad = gst_object_ref (stream->channelpad[0]);
4238   } else {
4239     GST_DEBUG_OBJECT (src, "using manager source pad");
4240
4241     template = gst_static_pad_template_get (&anysrctemplate);
4242
4243     /* allocate pads for sending the channel data into the manager */
4244     pad0 = gst_pad_new_from_template (template, "internalsrc_0");
4245     gst_pad_link_full (pad0, stream->channelpad[0], GST_PAD_LINK_CHECK_NOTHING);
4246     gst_object_unref (stream->channelpad[0]);
4247     stream->channelpad[0] = pad0;
4248     gst_pad_set_event_function (pad0, gst_rtspsrc_handle_internal_src_event);
4249     gst_pad_set_query_function (pad0, gst_rtspsrc_handle_internal_src_query);
4250     gst_pad_set_element_private (pad0, src);
4251     gst_pad_set_active (pad0, TRUE);
4252
4253     if (stream->channelpad[1]) {
4254       /* if we have a sinkpad for the other channel, create a pad and link to the
4255        * manager. */
4256       pad1 = gst_pad_new_from_template (template, "internalsrc_1");
4257       gst_pad_set_event_function (pad1, gst_rtspsrc_handle_internal_src_event);
4258       gst_pad_link_full (pad1, stream->channelpad[1],
4259           GST_PAD_LINK_CHECK_NOTHING);
4260       gst_object_unref (stream->channelpad[1]);
4261       stream->channelpad[1] = pad1;
4262       gst_pad_set_active (pad1, TRUE);
4263     }
4264     gst_object_unref (template);
4265   }
4266   /* setup RTCP transport back to the server if we have to. */
4267   if (src->manager && src->do_rtcp) {
4268     GstPad *pad;
4269
4270     template = gst_static_pad_template_get (&anysinktemplate);
4271
4272     stream->rtcppad = gst_pad_new_from_template (template, "internalsink_0");
4273     gst_pad_set_chain_function (stream->rtcppad, gst_rtspsrc_sink_chain);
4274     gst_pad_set_element_private (stream->rtcppad, stream);
4275     gst_pad_set_active (stream->rtcppad, TRUE);
4276
4277     /* get session RTCP pad */
4278     name = g_strdup_printf ("send_rtcp_src_%u", stream->id);
4279     pad = gst_element_get_request_pad (src->manager, name);
4280     g_free (name);
4281
4282     /* and link */
4283     if (pad) {
4284       gst_pad_link_full (pad, stream->rtcppad, GST_PAD_LINK_CHECK_NOTHING);
4285       gst_object_unref (pad);
4286     }
4287
4288     gst_object_unref (template);
4289   }
4290   return TRUE;
4291 }
4292
4293 static void
4294 gst_rtspsrc_get_transport_info (GstRTSPSrc * src, GstRTSPStream * stream,
4295     GstRTSPTransport * transport, const gchar ** destination, gint * min,
4296     gint * max, guint * ttl)
4297 {
4298   if (transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
4299     if (destination) {
4300       if (!(*destination = transport->destination))
4301         *destination = stream->destination;
4302     }
4303     if (min && max) {
4304       /* transport first */
4305       *min = transport->port.min;
4306       *max = transport->port.max;
4307       if (*min == -1 && *max == -1) {
4308         /* then try from SDP */
4309         if (stream->port != 0) {
4310           *min = stream->port;
4311           *max = stream->port + 1;
4312         }
4313       }
4314     }
4315
4316     if (ttl) {
4317       if (!(*ttl = transport->ttl))
4318         *ttl = stream->ttl;
4319     }
4320   } else {
4321     if (destination) {
4322       /* first take the source, then the endpoint to figure out where to send
4323        * the RTCP. */
4324       if (!(*destination = transport->source)) {
4325         if (src->conninfo.connection)
4326           *destination = gst_rtsp_connection_get_ip (src->conninfo.connection);
4327         else if (stream->conninfo.connection)
4328           *destination =
4329               gst_rtsp_connection_get_ip (stream->conninfo.connection);
4330       }
4331     }
4332     if (min && max) {
4333       /* for unicast we only expect the ports here */
4334       *min = transport->server_port.min;
4335       *max = transport->server_port.max;
4336     }
4337   }
4338 }
4339
4340 /* For multicast create UDP sources and join the multicast group. */
4341 static gboolean
4342 gst_rtspsrc_stream_configure_mcast (GstRTSPSrc * src, GstRTSPStream * stream,
4343     GstRTSPTransport * transport, GstPad ** outpad)
4344 {
4345   gchar *uri;
4346   const gchar *destination;
4347   gint min, max;
4348
4349   GST_DEBUG_OBJECT (src, "creating UDP sources for multicast");
4350
4351   /* we can remove the allocated UDP ports now */
4352   gst_rtspsrc_stream_free_udp (stream);
4353
4354   gst_rtspsrc_get_transport_info (src, stream, transport, &destination, &min,
4355       &max, NULL);
4356
4357   /* we need a destination now */
4358   if (destination == NULL)
4359     goto no_destination;
4360
4361   /* we really need ports now or we won't be able to receive anything at all */
4362   if (min == -1 && max == -1)
4363     goto no_ports;
4364
4365   GST_DEBUG_OBJECT (src, "have destination '%s' and ports (%d)-(%d)",
4366       destination, min, max);
4367
4368   /* creating UDP source for RTP */
4369   if (min != -1) {
4370     uri = g_strdup_printf ("udp://%s:%d", destination, min);
4371     stream->udpsrc[0] =
4372         gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
4373     g_free (uri);
4374     if (stream->udpsrc[0] == NULL)
4375       goto no_element;
4376
4377     /* take ownership */
4378     gst_object_ref_sink (stream->udpsrc[0]);
4379
4380     if (src->udp_buffer_size != 0)
4381       g_object_set (G_OBJECT (stream->udpsrc[0]), "buffer-size",
4382           src->udp_buffer_size, NULL);
4383
4384     if (src->multi_iface != NULL)
4385       g_object_set (G_OBJECT (stream->udpsrc[0]), "multicast-iface",
4386           src->multi_iface, NULL);
4387
4388     /* change state */
4389     gst_element_set_locked_state (stream->udpsrc[0], TRUE);
4390     gst_element_set_state (stream->udpsrc[0], GST_STATE_READY);
4391   }
4392
4393   /* creating another UDP source for RTCP */
4394   if (max != -1) {
4395     GstCaps *caps;
4396
4397     uri = g_strdup_printf ("udp://%s:%d", destination, max);
4398     stream->udpsrc[1] =
4399         gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
4400     g_free (uri);
4401     if (stream->udpsrc[1] == NULL)
4402       goto no_element;
4403
4404     if (stream->profile == GST_RTSP_PROFILE_SAVP ||
4405         stream->profile == GST_RTSP_PROFILE_SAVPF)
4406       caps = gst_caps_new_empty_simple ("application/x-srtcp");
4407     else
4408       caps = gst_caps_new_empty_simple ("application/x-rtcp");
4409     g_object_set (stream->udpsrc[1], "caps", caps, NULL);
4410     gst_caps_unref (caps);
4411
4412     /* take ownership */
4413     gst_object_ref_sink (stream->udpsrc[1]);
4414
4415     if (src->multi_iface != NULL)
4416       g_object_set (G_OBJECT (stream->udpsrc[1]), "multicast-iface",
4417           src->multi_iface, NULL);
4418
4419     gst_element_set_state (stream->udpsrc[1], GST_STATE_READY);
4420   }
4421   return TRUE;
4422
4423   /* ERRORS */
4424 no_element:
4425   {
4426     GST_DEBUG_OBJECT (src, "no UDP source element found");
4427     return FALSE;
4428   }
4429 no_destination:
4430   {
4431     GST_DEBUG_OBJECT (src, "no destination found");
4432     return FALSE;
4433   }
4434 no_ports:
4435   {
4436     GST_DEBUG_OBJECT (src, "no ports found");
4437     return FALSE;
4438   }
4439 }
4440
4441 /* configure the remainder of the UDP ports */
4442 static gboolean
4443 gst_rtspsrc_stream_configure_udp (GstRTSPSrc * src, GstRTSPStream * stream,
4444     GstRTSPTransport * transport, GstPad ** outpad)
4445 {
4446   /* we manage the UDP elements now. For unicast, the UDP sources where
4447    * allocated in the stream when we suggested a transport. */
4448   if (stream->udpsrc[0]) {
4449     GstCaps *caps;
4450
4451     gst_element_set_locked_state (stream->udpsrc[0], TRUE);
4452     gst_bin_add (GST_BIN_CAST (src), stream->udpsrc[0]);
4453
4454     GST_DEBUG_OBJECT (src, "setting up UDP source");
4455
4456     /* configure a timeout on the UDP port. When the timeout message is
4457      * posted, we assume UDP transport is not possible. We reconnect using TCP
4458      * if we can. */
4459     g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout",
4460         src->udp_timeout * 1000, NULL);
4461
4462     if ((caps = stream_get_caps_for_pt (stream, stream->default_pt)))
4463       g_object_set (stream->udpsrc[0], "caps", caps, NULL);
4464
4465     /* get output pad of the UDP source. */
4466     *outpad = gst_element_get_static_pad (stream->udpsrc[0], "src");
4467
4468     /* save it so we can unblock */
4469     stream->blockedpad = *outpad;
4470
4471     /* configure pad block on the pad. As soon as there is dataflow on the
4472      * UDP source, we know that UDP is not blocked by a firewall and we can
4473      * configure all the streams to let the application autoplug decoders. */
4474     stream->blockid =
4475         gst_pad_add_probe (stream->blockedpad,
4476         GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER |
4477         GST_PAD_PROBE_TYPE_BUFFER_LIST, pad_blocked, src, NULL);
4478
4479     gst_pad_add_probe (stream->blockedpad,
4480         GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, udpsrc_probe_cb,
4481         &(stream->segment_seqnum[0]), NULL);
4482
4483     if (stream->channelpad[0]) {
4484       GST_DEBUG_OBJECT (src, "connecting UDP source 0 to manager");
4485       /* configure for UDP delivery, we need to connect the UDP pads to
4486        * the session plugin. */
4487       gst_pad_link_full (*outpad, stream->channelpad[0],
4488           GST_PAD_LINK_CHECK_NOTHING);
4489       gst_object_unref (*outpad);
4490       *outpad = NULL;
4491       /* we connected to pad-added signal to get pads from the manager */
4492     } else {
4493       GST_DEBUG_OBJECT (src, "using UDP src pad as output");
4494     }
4495   }
4496
4497   /* RTCP port */
4498   if (stream->udpsrc[1]) {
4499     GstCaps *caps;
4500
4501     gst_element_set_locked_state (stream->udpsrc[1], TRUE);
4502     gst_bin_add (GST_BIN_CAST (src), stream->udpsrc[1]);
4503
4504     if (stream->profile == GST_RTSP_PROFILE_SAVP ||
4505         stream->profile == GST_RTSP_PROFILE_SAVPF)
4506       caps = gst_caps_new_empty_simple ("application/x-srtcp");
4507     else
4508       caps = gst_caps_new_empty_simple ("application/x-rtcp");
4509     g_object_set (stream->udpsrc[1], "caps", caps, NULL);
4510     gst_caps_unref (caps);
4511
4512     if (stream->channelpad[1]) {
4513       GstPad *pad;
4514
4515       GST_DEBUG_OBJECT (src, "connecting UDP source 1 to manager");
4516
4517       pad = gst_element_get_static_pad (stream->udpsrc[1], "src");
4518       gst_pad_add_probe (pad,
4519           GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, udpsrc_probe_cb,
4520           &(stream->segment_seqnum[1]), NULL);
4521       gst_pad_link_full (pad, stream->channelpad[1],
4522           GST_PAD_LINK_CHECK_NOTHING);
4523       gst_object_unref (pad);
4524     } else {
4525       /* leave unlinked */
4526     }
4527   }
4528   return TRUE;
4529 }
4530
4531 /* configure the UDP sink back to the server for status reports */
4532 static gboolean
4533 gst_rtspsrc_stream_configure_udp_sinks (GstRTSPSrc * src,
4534     GstRTSPStream * stream, GstRTSPTransport * transport)
4535 {
4536   GstPad *pad;
4537   gint rtp_port, rtcp_port;
4538   gboolean do_rtp, do_rtcp;
4539   const gchar *destination;
4540   gchar *uri, *name;
4541   guint ttl = 0;
4542   GSocket *socket;
4543
4544   /* get transport info */
4545   gst_rtspsrc_get_transport_info (src, stream, transport, &destination,
4546       &rtp_port, &rtcp_port, &ttl);
4547
4548   /* see what we need to do */
4549   do_rtp = (rtp_port != -1);
4550   /* it's possible that the server does not want us to send RTCP in which case
4551    * the port is -1 */
4552   do_rtcp = (rtcp_port != -1 && src->manager != NULL && src->do_rtcp);
4553
4554   /* we need a destination when we have RTP or RTCP ports */
4555   if (destination == NULL && (do_rtp || do_rtcp))
4556     goto no_destination;
4557
4558   /* try to construct the fakesrc to the RTP port of the server to open up any
4559    * NAT firewalls or, if backchannel, construct an appsrc */
4560   if (do_rtp) {
4561     GST_DEBUG_OBJECT (src, "configure RTP UDP sink for %s:%d", destination,
4562         rtp_port);
4563
4564     uri = g_strdup_printf ("udp://%s:%d", destination, rtp_port);
4565     stream->udpsink[0] =
4566         gst_element_make_from_uri (GST_URI_SINK, uri, NULL, NULL);
4567     g_free (uri);
4568     if (stream->udpsink[0] == NULL)
4569       goto no_sink_element;
4570
4571     /* don't join multicast group, we will have the source socket do that */
4572     /* no sync or async state changes needed */
4573     g_object_set (G_OBJECT (stream->udpsink[0]), "auto-multicast", FALSE,
4574         "loop", FALSE, "sync", FALSE, "async", FALSE, NULL);
4575     if (ttl > 0)
4576       g_object_set (G_OBJECT (stream->udpsink[0]), "ttl", ttl, NULL);
4577
4578     if (stream->udpsrc[0]) {
4579       /* configure socket, we give it the same UDP socket as the udpsrc for RTP
4580        * so that NAT firewalls will open a hole for us */
4581       g_object_get (G_OBJECT (stream->udpsrc[0]), "used-socket", &socket, NULL);
4582       if (!socket)
4583         goto no_socket;
4584
4585       GST_DEBUG_OBJECT (src, "RTP UDP src has sock %p", socket);
4586       /* configure socket and make sure udpsink does not close it when shutting
4587        * down, it belongs to udpsrc after all. */
4588       g_object_set (G_OBJECT (stream->udpsink[0]), "socket", socket,
4589           "close-socket", FALSE, NULL);
4590       g_object_unref (socket);
4591     }
4592
4593     if (stream->is_backchannel) {
4594       /* appsrc is for the app to shovel data using push-backchannel-buffer */
4595       stream->rtpsrc = gst_element_factory_make ("appsrc", NULL);
4596       if (stream->rtpsrc == NULL)
4597         goto no_appsrc_element;
4598
4599       /* interal use only, don't emit signals */
4600       g_object_set (G_OBJECT (stream->rtpsrc), "emit-signals", TRUE,
4601           "is-live", TRUE, NULL);
4602     } else {
4603       /* the source for the dummy packets to open up NAT */
4604       stream->rtpsrc = gst_element_factory_make ("fakesrc", NULL);
4605       if (stream->rtpsrc == NULL)
4606         goto no_fakesrc_element;
4607
4608       /* random data in 5 buffers, a size of 200 bytes should be fine */
4609       g_object_set (G_OBJECT (stream->rtpsrc), "filltype", 3, "num-buffers", 5,
4610           "sizetype", 2, "sizemax", 200, "silent", TRUE, NULL);
4611     }
4612
4613     /* keep everything locked */
4614     gst_element_set_locked_state (stream->udpsink[0], TRUE);
4615     gst_element_set_locked_state (stream->rtpsrc, TRUE);
4616
4617     gst_object_ref (stream->udpsink[0]);
4618     gst_bin_add (GST_BIN_CAST (src), stream->udpsink[0]);
4619     gst_object_ref (stream->rtpsrc);
4620     gst_bin_add (GST_BIN_CAST (src), stream->rtpsrc);
4621
4622     gst_element_link_pads_full (stream->rtpsrc, "src", stream->udpsink[0],
4623         "sink", GST_PAD_LINK_CHECK_NOTHING);
4624   }
4625   if (do_rtcp) {
4626     GST_DEBUG_OBJECT (src, "configure RTCP UDP sink for %s:%d", destination,
4627         rtcp_port);
4628
4629     uri = g_strdup_printf ("udp://%s:%d", destination, rtcp_port);
4630     stream->udpsink[1] =
4631         gst_element_make_from_uri (GST_URI_SINK, uri, NULL, NULL);
4632     g_free (uri);
4633     if (stream->udpsink[1] == NULL)
4634       goto no_sink_element;
4635
4636     /* don't join multicast group, we will have the source socket do that */
4637     /* no sync or async state changes needed */
4638     g_object_set (G_OBJECT (stream->udpsink[1]), "auto-multicast", FALSE,
4639         "loop", FALSE, "sync", FALSE, "async", FALSE, NULL);
4640     if (ttl > 0)
4641       g_object_set (G_OBJECT (stream->udpsink[0]), "ttl", ttl, NULL);
4642
4643     if (stream->udpsrc[1]) {
4644       /* configure socket, we give it the same UDP socket as the udpsrc for RTCP
4645        * because some servers check the port number of where it sends RTCP to identify
4646        * the RTCP packets it receives */
4647       g_object_get (G_OBJECT (stream->udpsrc[1]), "used-socket", &socket, NULL);
4648       if (!socket)
4649         goto no_socket;
4650
4651       GST_DEBUG_OBJECT (src, "RTCP UDP src has sock %p", socket);
4652       /* configure socket and make sure udpsink does not close it when shutting
4653        * down, it belongs to udpsrc after all. */
4654       g_object_set (G_OBJECT (stream->udpsink[1]), "socket", socket,
4655           "close-socket", FALSE, NULL);
4656       g_object_unref (socket);
4657     }
4658
4659     /* we keep this playing always */
4660     gst_element_set_locked_state (stream->udpsink[1], TRUE);
4661     gst_element_set_state (stream->udpsink[1], GST_STATE_PLAYING);
4662
4663     gst_object_ref (stream->udpsink[1]);
4664     gst_bin_add (GST_BIN_CAST (src), stream->udpsink[1]);
4665
4666     stream->rtcppad = gst_element_get_static_pad (stream->udpsink[1], "sink");
4667
4668     /* get session RTCP pad */
4669     name = g_strdup_printf ("send_rtcp_src_%u", stream->id);
4670     pad = gst_element_get_request_pad (src->manager, name);
4671     g_free (name);
4672
4673     /* and link */
4674     if (pad) {
4675       gst_pad_link_full (pad, stream->rtcppad, GST_PAD_LINK_CHECK_NOTHING);
4676       gst_object_unref (pad);
4677     }
4678   }
4679
4680   return TRUE;
4681
4682   /* ERRORS */
4683 no_destination:
4684   {
4685     GST_ERROR_OBJECT (src, "no destination address specified");
4686     return FALSE;
4687   }
4688 no_sink_element:
4689   {
4690     GST_ERROR_OBJECT (src, "no UDP sink element found");
4691     return FALSE;
4692   }
4693 no_appsrc_element:
4694   {
4695     GST_ERROR_OBJECT (src, "no appsrc element found");
4696     return FALSE;
4697   }
4698 no_fakesrc_element:
4699   {
4700     GST_ERROR_OBJECT (src, "no fakesrc element found");
4701     return FALSE;
4702   }
4703 no_socket:
4704   {
4705     GST_ERROR_OBJECT (src, "failed to create socket");
4706     return FALSE;
4707   }
4708 }
4709
4710 /* sets up all elements needed for streaming over the specified transport.
4711  * Does not yet expose the element pads, this will be done when there is actuall
4712  * dataflow detected, which might never happen when UDP is blocked in a
4713  * firewall, for example.
4714  */
4715 static gboolean
4716 gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
4717     GstRTSPTransport * transport)
4718 {
4719   GstRTSPSrc *src;
4720   GstPad *outpad = NULL;
4721   GstPadTemplate *template;
4722   gchar *name;
4723   const gchar *media_type;
4724   guint i, len;
4725
4726   src = stream->parent;
4727
4728   GST_DEBUG_OBJECT (src, "configuring transport for stream %p", stream);
4729
4730   /* get the proper media type for this stream now */
4731   if (gst_rtsp_transport_get_media_type (transport, &media_type) < 0)
4732     goto unknown_transport;
4733   if (!media_type)
4734     goto unknown_transport;
4735
4736   /* configure the final media type */
4737   GST_DEBUG_OBJECT (src, "setting media type to %s", media_type);
4738
4739   len = stream->ptmap->len;
4740   for (i = 0; i < len; i++) {
4741     GstStructure *s;
4742     PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, i);
4743
4744     if (item->caps == NULL)
4745       continue;
4746
4747     s = gst_caps_get_structure (item->caps, 0);
4748     gst_structure_set_name (s, media_type);
4749     /* set ssrc if known */
4750     if (transport->ssrc)
4751       gst_structure_set (s, "ssrc", G_TYPE_UINT, transport->ssrc, NULL);
4752   }
4753
4754   /* try to get and configure a manager, channelpad[0-1] will be configured with
4755    * the pads for the manager, or NULL when no manager is needed. */
4756   if (!gst_rtspsrc_stream_configure_manager (src, stream, transport))
4757     goto no_manager;
4758
4759   switch (transport->lower_transport) {
4760     case GST_RTSP_LOWER_TRANS_TCP:
4761       if (!gst_rtspsrc_stream_configure_tcp (src, stream, transport, &outpad))
4762         goto transport_failed;
4763       break;
4764     case GST_RTSP_LOWER_TRANS_UDP_MCAST:
4765       if (!gst_rtspsrc_stream_configure_mcast (src, stream, transport, &outpad))
4766         goto transport_failed;
4767       /* fallthrough, the rest is the same for UDP and MCAST */
4768     case GST_RTSP_LOWER_TRANS_UDP:
4769       if (!gst_rtspsrc_stream_configure_udp (src, stream, transport, &outpad))
4770         goto transport_failed;
4771       /* configure udpsinks back to the server for RTCP messages, for the
4772        * dummy RTP messages to open NAT, and for the backchannel */
4773       if (!gst_rtspsrc_stream_configure_udp_sinks (src, stream, transport))
4774         goto transport_failed;
4775       break;
4776     default:
4777       goto unknown_transport;
4778   }
4779
4780   /* using backchannel and no manager, hence no srcpad for this stream */
4781   if (outpad && stream->is_backchannel) {
4782     add_backchannel_fakesink (src, stream, outpad);
4783     gst_object_unref (outpad);
4784   } else if (outpad) {
4785     GST_DEBUG_OBJECT (src, "creating ghostpad for stream %p", stream);
4786
4787     gst_pad_use_fixed_caps (outpad);
4788
4789     /* create ghostpad, don't add just yet, this will be done when we activate
4790      * the stream. */
4791     name = g_strdup_printf ("stream_%u", stream->id);
4792     template = gst_static_pad_template_get (&rtptemplate);
4793     stream->srcpad = gst_ghost_pad_new_from_template (name, outpad, template);
4794     gst_pad_set_event_function (stream->srcpad, gst_rtspsrc_handle_src_event);
4795     gst_pad_set_query_function (stream->srcpad, gst_rtspsrc_handle_src_query);
4796     gst_object_unref (template);
4797     g_free (name);
4798
4799     gst_object_unref (outpad);
4800   }
4801   /* mark pad as ok */
4802   stream->last_ret = GST_FLOW_OK;
4803
4804   return TRUE;
4805
4806   /* ERRORS */
4807 transport_failed:
4808   {
4809     GST_WARNING_OBJECT (src, "failed to configure transport");
4810     return FALSE;
4811   }
4812 unknown_transport:
4813   {
4814     GST_WARNING_OBJECT (src, "unknown transport");
4815     return FALSE;
4816   }
4817 no_manager:
4818   {
4819     GST_WARNING_OBJECT (src, "cannot get a session manager");
4820     return FALSE;
4821   }
4822 }
4823
4824 /* send a couple of dummy random packets on the receiver RTP port to the server,
4825  * this should make a firewall think we initiated the data transfer and
4826  * hopefully allow packets to go from the sender port to our RTP receiver port */
4827 static gboolean
4828 gst_rtspsrc_send_dummy_packets (GstRTSPSrc * src)
4829 {
4830   GList *walk;
4831
4832   if (src->nat_method != GST_RTSP_NAT_DUMMY)
4833     return TRUE;
4834
4835   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4836     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4837
4838     if (!stream->rtpsrc || !stream->udpsink[0])
4839       continue;
4840
4841     if (stream->is_backchannel)
4842       GST_DEBUG_OBJECT (src, "starting backchannel stream %p", stream);
4843     else
4844       GST_DEBUG_OBJECT (src, "sending dummy packet to stream %p", stream);
4845
4846     gst_element_set_state (stream->udpsink[0], GST_STATE_NULL);
4847     gst_element_set_state (stream->rtpsrc, GST_STATE_NULL);
4848     gst_element_set_state (stream->udpsink[0], GST_STATE_PLAYING);
4849     gst_element_set_state (stream->rtpsrc, GST_STATE_PLAYING);
4850   }
4851   return TRUE;
4852 }
4853
4854 /* Adds the source pads of all configured streams to the element.
4855  * This code is performed when we detected dataflow.
4856  *
4857  * We detect dataflow from either the _loop function or with pad probes on the
4858  * udp sources.
4859  */
4860 static gboolean
4861 gst_rtspsrc_activate_streams (GstRTSPSrc * src)
4862 {
4863   GList *walk;
4864
4865   GST_DEBUG_OBJECT (src, "activating streams");
4866
4867   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4868     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4869
4870     if (stream->udpsrc[0]) {
4871       /* remove timeout, we are streaming now and timeouts will be handled by
4872        * the session manager and jitter buffer */
4873       g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout", (guint64) 0, NULL);
4874     }
4875     if (stream->srcpad) {
4876       GST_DEBUG_OBJECT (src, "activating stream pad %p", stream);
4877       gst_pad_set_active (stream->srcpad, TRUE);
4878
4879       /* if we don't have a session manager, set the caps now. If we have a
4880        * session, we will get a notification of the pad and the caps. */
4881       if (!src->manager) {
4882         GstCaps *caps;
4883
4884         caps = stream_get_caps_for_pt (stream, stream->default_pt);
4885         GST_DEBUG_OBJECT (src, "setting pad caps for stream %p", stream);
4886         gst_pad_set_caps (stream->srcpad, caps);
4887       }
4888       /* add the pad */
4889       if (!stream->added) {
4890         GST_DEBUG_OBJECT (src, "adding stream pad %p", stream);
4891         if (stream->is_backchannel)
4892           add_backchannel_fakesink (src, stream, stream->srcpad);
4893         else
4894           gst_element_add_pad (GST_ELEMENT_CAST (src), stream->srcpad);
4895         stream->added = TRUE;
4896       }
4897     }
4898   }
4899
4900   /* unblock all pads */
4901   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4902     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4903
4904     if (stream->blockid) {
4905       GST_DEBUG_OBJECT (src, "unblocking stream pad %p", stream);
4906       gst_pad_remove_probe (stream->blockedpad, stream->blockid);
4907       stream->blockid = 0;
4908     }
4909   }
4910
4911   return TRUE;
4912 }
4913
4914 static void
4915 gst_rtspsrc_configure_caps (GstRTSPSrc * src, GstSegment * segment,
4916     gboolean reset_manager)
4917 {
4918   GList *walk;
4919   guint64 start, stop;
4920   gdouble play_speed, play_scale;
4921
4922   GST_DEBUG_OBJECT (src, "configuring stream caps");
4923
4924   start = segment->position;
4925   stop = segment->duration;
4926   play_speed = segment->rate;
4927   play_scale = segment->applied_rate;
4928
4929   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4930     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4931     guint j, len;
4932
4933     if (!stream->setup)
4934       continue;
4935
4936     len = stream->ptmap->len;
4937     for (j = 0; j < len; j++) {
4938       GstCaps *caps;
4939       PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, j);
4940
4941       if (item->caps == NULL)
4942         continue;
4943
4944       caps = gst_caps_make_writable (item->caps);
4945       /* update caps */
4946       if (stream->timebase != -1)
4947         gst_caps_set_simple (caps, "clock-base", G_TYPE_UINT,
4948             (guint) stream->timebase, NULL);
4949       if (stream->seqbase != -1)
4950         gst_caps_set_simple (caps, "seqnum-base", G_TYPE_UINT,
4951             (guint) stream->seqbase, NULL);
4952       gst_caps_set_simple (caps, "npt-start", G_TYPE_UINT64, start, NULL);
4953       if (stop != -1)
4954         gst_caps_set_simple (caps, "npt-stop", G_TYPE_UINT64, stop, NULL);
4955       gst_caps_set_simple (caps, "play-speed", G_TYPE_DOUBLE, play_speed, NULL);
4956       gst_caps_set_simple (caps, "play-scale", G_TYPE_DOUBLE, play_scale, NULL);
4957
4958       item->caps = caps;
4959       GST_DEBUG_OBJECT (src, "stream %p, pt %d, caps %" GST_PTR_FORMAT, stream,
4960           item->pt, caps);
4961
4962       if (item->pt == stream->default_pt) {
4963         if (stream->udpsrc[0])
4964           g_object_set (stream->udpsrc[0], "caps", caps, NULL);
4965         stream->need_caps = TRUE;
4966       }
4967     }
4968   }
4969   if (reset_manager && src->manager) {
4970     GST_DEBUG_OBJECT (src, "clear session");
4971     g_signal_emit_by_name (src->manager, "clear-pt-map", NULL);
4972   }
4973 }
4974
4975 static GstFlowReturn
4976 gst_rtspsrc_combine_flows (GstRTSPSrc * src, GstRTSPStream * stream,
4977     GstFlowReturn ret)
4978 {
4979   GList *streams;
4980
4981   /* store the value */
4982   stream->last_ret = ret;
4983
4984   /* if it's success we can return the value right away */
4985   if (ret == GST_FLOW_OK)
4986     goto done;
4987
4988   /* any other error that is not-linked can be returned right
4989    * away */
4990   if (ret != GST_FLOW_NOT_LINKED)
4991     goto done;
4992
4993   /* only return NOT_LINKED if all other pads returned NOT_LINKED */
4994   for (streams = src->streams; streams; streams = g_list_next (streams)) {
4995     GstRTSPStream *ostream = (GstRTSPStream *) streams->data;
4996
4997     ret = ostream->last_ret;
4998     /* some other return value (must be SUCCESS but we can return
4999      * other values as well) */
5000     if (ret != GST_FLOW_NOT_LINKED)
5001       goto done;
5002   }
5003   /* if we get here, all other pads were unlinked and we return
5004    * NOT_LINKED then */
5005 done:
5006   return ret;
5007 }
5008
5009 static gboolean
5010 gst_rtspsrc_stream_push_event (GstRTSPSrc * src, GstRTSPStream * stream,
5011     GstEvent * event)
5012 {
5013   gboolean res = TRUE;
5014
5015   /* only streams that have a connection to the outside world */
5016   if (!stream->setup)
5017     goto done;
5018
5019   if (stream->udpsrc[0]) {
5020     GstEvent *sent_event;
5021
5022     if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
5023       sent_event = gst_event_new_eos ();
5024       gst_event_set_seqnum (sent_event, stream->segment_seqnum[0]);
5025     } else {
5026       sent_event = gst_event_ref (event);
5027     }
5028
5029     res = gst_element_send_event (stream->udpsrc[0], sent_event);
5030   } else if (stream->channelpad[0]) {
5031     gst_event_ref (event);
5032     if (GST_PAD_IS_SRC (stream->channelpad[0]))
5033       res = gst_pad_push_event (stream->channelpad[0], event);
5034     else
5035       res = gst_pad_send_event (stream->channelpad[0], event);
5036   }
5037
5038   if (stream->udpsrc[1]) {
5039     GstEvent *sent_event;
5040
5041     if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
5042       sent_event = gst_event_new_eos ();
5043       if (stream->segment_seqnum[1] != GST_SEQNUM_INVALID) {
5044         gst_event_set_seqnum (sent_event, stream->segment_seqnum[1]);
5045       }
5046     } else {
5047       sent_event = gst_event_ref (event);
5048     }
5049
5050     res &= gst_element_send_event (stream->udpsrc[1], sent_event);
5051   } else if (stream->channelpad[1]) {
5052     gst_event_ref (event);
5053     if (GST_PAD_IS_SRC (stream->channelpad[1]))
5054       res &= gst_pad_push_event (stream->channelpad[1], event);
5055     else
5056       res &= gst_pad_send_event (stream->channelpad[1], event);
5057   }
5058
5059 done:
5060   gst_event_unref (event);
5061
5062   return res;
5063 }
5064
5065 static gboolean
5066 gst_rtspsrc_push_event (GstRTSPSrc * src, GstEvent * event)
5067 {
5068   GList *streams;
5069   gboolean res = TRUE;
5070
5071   for (streams = src->streams; streams; streams = g_list_next (streams)) {
5072     GstRTSPStream *ostream = (GstRTSPStream *) streams->data;
5073
5074     gst_event_ref (event);
5075     res &= gst_rtspsrc_stream_push_event (src, ostream, event);
5076   }
5077   gst_event_unref (event);
5078
5079   return res;
5080 }
5081
5082 static gboolean
5083 accept_certificate_cb (GTlsConnection * conn, GTlsCertificate * peer_cert,
5084     GTlsCertificateFlags errors, gpointer user_data)
5085 {
5086   GstRTSPSrc *src = user_data;
5087   gboolean accept = FALSE;
5088
5089   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_ACCEPT_CERTIFICATE], 0, conn,
5090       peer_cert, errors, &accept);
5091
5092   return accept;
5093 }
5094
5095 static GstRTSPResult
5096 gst_rtsp_conninfo_connect (GstRTSPSrc * src, GstRTSPConnInfo * info,
5097     gboolean async)
5098 {
5099   GstRTSPResult res;
5100   GstRTSPMessage response;
5101   gboolean retry = FALSE;
5102   memset (&response, 0, sizeof (response));
5103   gst_rtsp_message_init (&response);
5104   do {
5105     if (info->connection == NULL) {
5106       if (info->url == NULL) {
5107         GST_DEBUG_OBJECT (src, "parsing uri (%s)...", info->location);
5108         if ((res = gst_rtsp_url_parse (info->location, &info->url)) < 0)
5109           goto parse_error;
5110       }
5111       /* create connection */
5112       GST_DEBUG_OBJECT (src, "creating connection (%s)...", info->location);
5113       if ((res = gst_rtsp_connection_create (info->url, &info->connection)) < 0)
5114         goto could_not_create;
5115
5116       if (retry) {
5117         gst_rtspsrc_setup_auth (src, &response);
5118       }
5119
5120       g_free (info->url_str);
5121       info->url_str = gst_rtsp_url_get_request_uri (info->url);
5122
5123       GST_DEBUG_OBJECT (src, "sanitized uri %s", info->url_str);
5124
5125       if (info->url->transports & GST_RTSP_LOWER_TRANS_TLS) {
5126         if (!gst_rtsp_connection_set_tls_validation_flags (info->connection,
5127                 src->tls_validation_flags))
5128           GST_WARNING_OBJECT (src, "Unable to set TLS validation flags");
5129
5130         if (src->tls_database)
5131           gst_rtsp_connection_set_tls_database (info->connection,
5132               src->tls_database);
5133
5134         if (src->tls_interaction)
5135           gst_rtsp_connection_set_tls_interaction (info->connection,
5136               src->tls_interaction);
5137         gst_rtsp_connection_set_accept_certificate_func (info->connection,
5138             accept_certificate_cb, src, NULL);
5139       }
5140
5141       if (info->url->transports & GST_RTSP_LOWER_TRANS_HTTP)
5142         gst_rtsp_connection_set_tunneled (info->connection, TRUE);
5143
5144       if (src->proxy_host) {
5145         GST_DEBUG_OBJECT (src, "setting proxy %s:%d", src->proxy_host,
5146             src->proxy_port);
5147         gst_rtsp_connection_set_proxy (info->connection, src->proxy_host,
5148             src->proxy_port);
5149       }
5150     }
5151
5152     if (!info->connected) {
5153       /* connect */
5154       if (async)
5155         GST_ELEMENT_PROGRESS (src, CONTINUE, "connect",
5156             ("Connecting to %s", info->location));
5157       GST_DEBUG_OBJECT (src, "connecting (%s)...", info->location);
5158       res = gst_rtsp_connection_connect_with_response (info->connection,
5159           src->ptcp_timeout, &response);
5160
5161       if (response.type == GST_RTSP_MESSAGE_HTTP_RESPONSE &&
5162           response.type_data.response.code == GST_RTSP_STS_UNAUTHORIZED) {
5163         gst_rtsp_conninfo_close (src, info, TRUE);
5164         if (!retry)
5165           retry = TRUE;
5166         else
5167           retry = FALSE;        // we should not retry more than once
5168       } else {
5169         retry = FALSE;
5170       }
5171
5172       if (res == GST_RTSP_OK)
5173         info->connected = TRUE;
5174       else if (!retry)
5175         goto could_not_connect;
5176     }
5177   } while (!info->connected && retry);
5178
5179   gst_rtsp_message_unset (&response);
5180   return GST_RTSP_OK;
5181
5182   /* ERRORS */
5183 parse_error:
5184   {
5185     GST_ERROR_OBJECT (src, "No valid RTSP URL was provided");
5186     gst_rtsp_message_unset (&response);
5187     return res;
5188   }
5189 could_not_create:
5190   {
5191     gchar *str = gst_rtsp_strresult (res);
5192     GST_ERROR_OBJECT (src, "Could not create connection. (%s)", str);
5193     g_free (str);
5194     gst_rtsp_message_unset (&response);
5195     return res;
5196   }
5197 could_not_connect:
5198   {
5199     gchar *str = gst_rtsp_strresult (res);
5200     GST_ERROR_OBJECT (src, "Could not connect to server. (%s)", str);
5201     g_free (str);
5202     gst_rtsp_message_unset (&response);
5203     return res;
5204   }
5205 }
5206
5207 static GstRTSPResult
5208 gst_rtsp_conninfo_close (GstRTSPSrc * src, GstRTSPConnInfo * info,
5209     gboolean free)
5210 {
5211   GST_RTSP_STATE_LOCK (src);
5212   if (info->connected) {
5213     GST_DEBUG_OBJECT (src, "closing connection...");
5214     gst_rtsp_connection_close (info->connection);
5215     info->connected = FALSE;
5216   }
5217   if (free && info->connection) {
5218     /* free connection */
5219     GST_DEBUG_OBJECT (src, "freeing connection...");
5220     gst_rtsp_connection_free (info->connection);
5221     info->connection = NULL;
5222     info->flushing = FALSE;
5223   }
5224   GST_RTSP_STATE_UNLOCK (src);
5225   return GST_RTSP_OK;
5226 }
5227
5228 static GstRTSPResult
5229 gst_rtsp_conninfo_reconnect (GstRTSPSrc * src, GstRTSPConnInfo * info,
5230     gboolean async)
5231 {
5232   GstRTSPResult res;
5233
5234   GST_DEBUG_OBJECT (src, "reconnecting connection...");
5235   gst_rtsp_conninfo_close (src, info, FALSE);
5236   res = gst_rtsp_conninfo_connect (src, info, async);
5237
5238   return res;
5239 }
5240
5241 static void
5242 gst_rtspsrc_connection_flush (GstRTSPSrc * src, gboolean flush)
5243 {
5244   GList *walk;
5245
5246   GST_DEBUG_OBJECT (src, "set flushing %d", flush);
5247   GST_RTSP_STATE_LOCK (src);
5248   if (src->conninfo.connection && src->conninfo.flushing != flush) {
5249     GST_DEBUG_OBJECT (src, "connection flush");
5250     gst_rtsp_connection_flush (src->conninfo.connection, flush);
5251     src->conninfo.flushing = flush;
5252   }
5253   for (walk = src->streams; walk; walk = g_list_next (walk)) {
5254     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
5255     if (stream->conninfo.connection && stream->conninfo.flushing != flush) {
5256       GST_DEBUG_OBJECT (src, "stream %p flush", stream);
5257       gst_rtsp_connection_flush (stream->conninfo.connection, flush);
5258       stream->conninfo.flushing = flush;
5259     }
5260   }
5261   GST_RTSP_STATE_UNLOCK (src);
5262 }
5263
5264 static GstRTSPResult
5265 gst_rtspsrc_init_request (GstRTSPSrc * src, GstRTSPMessage * msg,
5266     GstRTSPMethod method, const gchar * uri)
5267 {
5268   GstRTSPResult res;
5269
5270   res = gst_rtsp_message_init_request (msg, method, uri);
5271   if (res < 0)
5272     return res;
5273
5274   /* set user-agent */
5275   if (src->user_agent)
5276     gst_rtsp_message_add_header (msg, GST_RTSP_HDR_USER_AGENT, src->user_agent);
5277
5278   return res;
5279 }
5280
5281 /* FIXME, handle server request, reply with OK, for now */
5282 static GstRTSPResult
5283 gst_rtspsrc_handle_request (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
5284     GstRTSPMessage * request)
5285 {
5286   GstRTSPMessage response = { 0 };
5287   GstRTSPResult res;
5288
5289   GST_DEBUG_OBJECT (src, "got server request message");
5290
5291   DEBUG_RTSP (src, request);
5292
5293   res = gst_rtsp_ext_list_receive_request (src->extensions, request);
5294
5295   if (res == GST_RTSP_ENOTIMPL) {
5296     /* default implementation, send OK */
5297     GST_DEBUG_OBJECT (src, "prepare OK reply");
5298     res =
5299         gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, "OK",
5300         request);
5301     if (res < 0)
5302       goto send_error;
5303
5304     /* let app parse and reply */
5305     g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_HANDLE_REQUEST],
5306         0, request, &response);
5307
5308     DEBUG_RTSP (src, &response);
5309
5310     res = gst_rtspsrc_connection_send (src, conninfo, &response, NULL);
5311     if (res < 0)
5312       goto send_error;
5313
5314     gst_rtsp_message_unset (&response);
5315   } else if (res == GST_RTSP_EEOF)
5316     return res;
5317
5318   return GST_RTSP_OK;
5319
5320   /* ERRORS */
5321 send_error:
5322   {
5323     gst_rtsp_message_unset (&response);
5324     return res;
5325   }
5326 }
5327
5328 /* send server keep-alive */
5329 static GstRTSPResult
5330 gst_rtspsrc_send_keep_alive (GstRTSPSrc * src)
5331 {
5332   GstRTSPMessage request = { 0 };
5333   GstRTSPResult res;
5334   GstRTSPMethod method;
5335   const gchar *control;
5336
5337   if (src->do_rtsp_keep_alive == FALSE) {
5338     GST_DEBUG_OBJECT (src, "do-rtsp-keep-alive is FALSE, not sending.");
5339     gst_rtsp_connection_reset_timeout (src->conninfo.connection);
5340     return GST_RTSP_OK;
5341   }
5342
5343   GST_DEBUG_OBJECT (src, "creating server keep-alive");
5344
5345   /* find a method to use for keep-alive */
5346   if (src->methods & GST_RTSP_GET_PARAMETER)
5347     method = GST_RTSP_GET_PARAMETER;
5348   else
5349     method = GST_RTSP_OPTIONS;
5350
5351   control = get_aggregate_control (src);
5352   if (control == NULL)
5353     goto no_control;
5354
5355   res = gst_rtspsrc_init_request (src, &request, method, control);
5356   if (res < 0)
5357     goto send_error;
5358
5359   request.type_data.request.version = src->version;
5360
5361   res = gst_rtspsrc_connection_send (src, &src->conninfo, &request, NULL);
5362   if (res < 0)
5363     goto send_error;
5364
5365   gst_rtsp_connection_reset_timeout (src->conninfo.connection);
5366   gst_rtsp_message_unset (&request);
5367
5368   return GST_RTSP_OK;
5369
5370   /* ERRORS */
5371 no_control:
5372   {
5373     GST_WARNING_OBJECT (src, "no control url to send keepalive");
5374     return GST_RTSP_OK;
5375   }
5376 send_error:
5377   {
5378     gchar *str = gst_rtsp_strresult (res);
5379
5380     gst_rtsp_message_unset (&request);
5381     GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
5382         ("Could not send keep-alive. (%s)", str));
5383     g_free (str);
5384     return res;
5385   }
5386 }
5387
5388 static GstFlowReturn
5389 gst_rtspsrc_handle_data (GstRTSPSrc * src, GstRTSPMessage * message)
5390 {
5391   GstFlowReturn ret = GST_FLOW_OK;
5392   gint channel;
5393   GstRTSPStream *stream;
5394   GstPad *outpad = NULL;
5395   guint8 *data;
5396   guint size;
5397   GstBuffer *buf;
5398   gboolean is_rtcp;
5399
5400   channel = message->type_data.data.channel;
5401
5402   stream = find_stream (src, &channel, (gpointer) find_stream_by_channel);
5403   if (!stream)
5404     goto unknown_stream;
5405
5406   if (channel == stream->channel[0]) {
5407     outpad = stream->channelpad[0];
5408     is_rtcp = FALSE;
5409   } else if (channel == stream->channel[1]) {
5410     outpad = stream->channelpad[1];
5411     is_rtcp = TRUE;
5412   } else {
5413     is_rtcp = FALSE;
5414   }
5415
5416   /* take a look at the body to figure out what we have */
5417   gst_rtsp_message_get_body (message, &data, &size);
5418   if (size < 2)
5419     goto invalid_length;
5420
5421   /* channels are not correct on some servers, do extra check */
5422   if (data[1] >= 200 && data[1] <= 204) {
5423     /* hmm RTCP message switch to the RTCP pad of the same stream. */
5424     outpad = stream->channelpad[1];
5425     is_rtcp = TRUE;
5426   }
5427
5428   /* we have no clue what this is, just ignore then. */
5429   if (outpad == NULL)
5430     goto unknown_stream;
5431
5432   /* take the message body for further processing */
5433   gst_rtsp_message_steal_body (message, &data, &size);
5434
5435   /* strip the trailing \0 */
5436   size -= 1;
5437
5438   buf = gst_buffer_new ();
5439   gst_buffer_append_memory (buf,
5440       gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
5441
5442   /* don't need message anymore */
5443   gst_rtsp_message_unset (message);
5444
5445   GST_DEBUG_OBJECT (src, "pushing data of size %d on channel %d", size,
5446       channel);
5447
5448   if (src->need_activate) {
5449     gchar *stream_id;
5450     GstEvent *event;
5451     GChecksum *cs;
5452     gchar *uri;
5453     GList *streams;
5454     guint group_id = gst_util_group_id_next ();
5455
5456     /* generate an SHA256 sum of the URI */
5457     cs = g_checksum_new (G_CHECKSUM_SHA256);
5458     uri = src->conninfo.location;
5459     g_checksum_update (cs, (const guchar *) uri, strlen (uri));
5460
5461     for (streams = src->streams; streams; streams = g_list_next (streams)) {
5462       GstRTSPStream *ostream = (GstRTSPStream *) streams->data;
5463       GstCaps *caps;
5464
5465       stream_id =
5466           g_strdup_printf ("%s/%d", g_checksum_get_string (cs), ostream->id);
5467       event = gst_event_new_stream_start (stream_id);
5468       gst_event_set_group_id (event, group_id);
5469
5470       g_free (stream_id);
5471       gst_rtspsrc_stream_push_event (src, ostream, event);
5472
5473       if ((caps = stream_get_caps_for_pt (ostream, ostream->default_pt))) {
5474         /* only streams that have a connection to the outside world */
5475         if (ostream->setup) {
5476           if (ostream->udpsrc[0]) {
5477             gst_element_send_event (ostream->udpsrc[0],
5478                 gst_event_new_caps (caps));
5479           } else if (ostream->channelpad[0]) {
5480             if (GST_PAD_IS_SRC (ostream->channelpad[0]))
5481               gst_pad_push_event (ostream->channelpad[0],
5482                   gst_event_new_caps (caps));
5483             else
5484               gst_pad_send_event (ostream->channelpad[0],
5485                   gst_event_new_caps (caps));
5486           }
5487           ostream->need_caps = FALSE;
5488
5489           if (ostream->profile == GST_RTSP_PROFILE_SAVP ||
5490               ostream->profile == GST_RTSP_PROFILE_SAVPF)
5491             caps = gst_caps_new_empty_simple ("application/x-srtcp");
5492           else
5493             caps = gst_caps_new_empty_simple ("application/x-rtcp");
5494
5495           if (ostream->udpsrc[1]) {
5496             gst_element_send_event (ostream->udpsrc[1],
5497                 gst_event_new_caps (caps));
5498           } else if (ostream->channelpad[1]) {
5499             if (GST_PAD_IS_SRC (ostream->channelpad[1]))
5500               gst_pad_push_event (ostream->channelpad[1],
5501                   gst_event_new_caps (caps));
5502             else
5503               gst_pad_send_event (ostream->channelpad[1],
5504                   gst_event_new_caps (caps));
5505           }
5506
5507           gst_caps_unref (caps);
5508         }
5509       }
5510     }
5511     g_checksum_free (cs);
5512
5513     gst_rtspsrc_activate_streams (src);
5514     src->need_activate = FALSE;
5515     src->need_segment = TRUE;
5516   }
5517
5518   if (src->base_time == -1) {
5519     /* Take current running_time. This timestamp will be put on
5520      * the first buffer of each stream because we are a live source and so we
5521      * timestamp with the running_time. When we are dealing with TCP, we also
5522      * only timestamp the first buffer (using the DISCONT flag) because a server
5523      * typically bursts data, for which we don't want to compensate by speeding
5524      * up the media. The other timestamps will be interpollated from this one
5525      * using the RTP timestamps. */
5526     GST_OBJECT_LOCK (src);
5527     if (GST_ELEMENT_CLOCK (src)) {
5528       GstClockTime now;
5529       GstClockTime base_time;
5530
5531       now = gst_clock_get_time (GST_ELEMENT_CLOCK (src));
5532       base_time = GST_ELEMENT_CAST (src)->base_time;
5533
5534       src->base_time = now - base_time;
5535
5536       GST_DEBUG_OBJECT (src, "first buffer at time %" GST_TIME_FORMAT ", base %"
5537           GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
5538     }
5539     GST_OBJECT_UNLOCK (src);
5540   }
5541
5542   /* If needed send a new segment, don't forget we are live and buffer are
5543    * timestamped with running time */
5544   if (src->need_segment) {
5545     GstSegment segment;
5546     src->need_segment = FALSE;
5547     gst_segment_init (&segment, GST_FORMAT_TIME);
5548     gst_rtspsrc_push_event (src, gst_event_new_segment (&segment));
5549   }
5550
5551   if (stream->need_caps) {
5552     GstCaps *caps;
5553
5554     if ((caps = stream_get_caps_for_pt (stream, stream->default_pt))) {
5555       /* only streams that have a connection to the outside world */
5556       if (stream->setup) {
5557         /* Only need to update the TCP caps here, UDP is already handled */
5558         if (stream->channelpad[0]) {
5559           if (GST_PAD_IS_SRC (stream->channelpad[0]))
5560             gst_pad_push_event (stream->channelpad[0],
5561                 gst_event_new_caps (caps));
5562           else
5563             gst_pad_send_event (stream->channelpad[0],
5564                 gst_event_new_caps (caps));
5565         }
5566         stream->need_caps = FALSE;
5567       }
5568     }
5569
5570     stream->need_caps = FALSE;
5571   }
5572
5573   if (stream->discont && !is_rtcp) {
5574     /* mark first RTP buffer as discont */
5575     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5576     stream->discont = FALSE;
5577     /* first buffer gets the timestamp, other buffers are not timestamped and
5578      * their presentation time will be interpollated from the rtp timestamps. */
5579     GST_DEBUG_OBJECT (src, "setting timestamp %" GST_TIME_FORMAT,
5580         GST_TIME_ARGS (src->base_time));
5581
5582     GST_BUFFER_TIMESTAMP (buf) = src->base_time;
5583   }
5584
5585   /* chain to the peer pad */
5586   if (GST_PAD_IS_SINK (outpad))
5587     ret = gst_pad_chain (outpad, buf);
5588   else
5589     ret = gst_pad_push (outpad, buf);
5590
5591   if (!is_rtcp) {
5592     /* combine all stream flows for the data transport */
5593     ret = gst_rtspsrc_combine_flows (src, stream, ret);
5594   }
5595   return ret;
5596
5597   /* ERRORS */
5598 unknown_stream:
5599   {
5600     GST_DEBUG_OBJECT (src, "unknown stream on channel %d, ignored", channel);
5601     gst_rtsp_message_unset (message);
5602     return GST_FLOW_OK;
5603   }
5604 invalid_length:
5605   {
5606     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5607         ("Short message received, ignoring."));
5608     gst_rtsp_message_unset (message);
5609     return GST_FLOW_OK;
5610   }
5611 }
5612
5613 static GstFlowReturn
5614 gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
5615 {
5616   GstRTSPMessage message = { 0 };
5617   GstRTSPResult res;
5618   GstFlowReturn ret = GST_FLOW_OK;
5619   GTimeVal tv_timeout;
5620
5621   while (TRUE) {
5622     /* get the next timeout interval */
5623     gst_rtsp_connection_next_timeout (src->conninfo.connection, &tv_timeout);
5624
5625     /* see if the timeout period expired */
5626     if ((tv_timeout.tv_sec | tv_timeout.tv_usec) == 0) {
5627       GST_DEBUG_OBJECT (src, "timout, sending keep-alive");
5628       /* send keep-alive, only act on interrupt, a warning will be posted for
5629        * other errors. */
5630       if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5631         goto interrupt;
5632       /* get new timeout */
5633       gst_rtsp_connection_next_timeout (src->conninfo.connection, &tv_timeout);
5634     }
5635
5636     GST_DEBUG_OBJECT (src, "doing receive with timeout %ld seconds, %ld usec",
5637         tv_timeout.tv_sec, tv_timeout.tv_usec);
5638
5639     /* protect the connection with the connection lock so that we can see when
5640      * we are finished doing server communication */
5641     res =
5642         gst_rtspsrc_connection_receive (src, &src->conninfo,
5643         &message, src->ptcp_timeout);
5644
5645     switch (res) {
5646       case GST_RTSP_OK:
5647         GST_DEBUG_OBJECT (src, "we received a server message");
5648         break;
5649       case GST_RTSP_EINTR:
5650         /* we got interrupted this means we need to stop */
5651         goto interrupt;
5652       case GST_RTSP_ETIMEOUT:
5653         /* no reply, send keep alive */
5654         GST_DEBUG_OBJECT (src, "timeout, sending keep-alive");
5655         if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5656           goto interrupt;
5657         continue;
5658       case GST_RTSP_EEOF:
5659         /* go EOS when the server closed the connection */
5660         goto server_eof;
5661       default:
5662         goto receive_error;
5663     }
5664
5665     switch (message.type) {
5666       case GST_RTSP_MESSAGE_REQUEST:
5667         /* server sends us a request message, handle it */
5668         res = gst_rtspsrc_handle_request (src, &src->conninfo, &message);
5669         if (res == GST_RTSP_EEOF)
5670           goto server_eof;
5671         else if (res < 0)
5672           goto handle_request_failed;
5673         break;
5674       case GST_RTSP_MESSAGE_RESPONSE:
5675         /* we ignore response messages */
5676         GST_DEBUG_OBJECT (src, "ignoring response message");
5677         DEBUG_RTSP (src, &message);
5678         break;
5679       case GST_RTSP_MESSAGE_DATA:
5680         GST_DEBUG_OBJECT (src, "got data message");
5681         ret = gst_rtspsrc_handle_data (src, &message);
5682         if (ret != GST_FLOW_OK)
5683           goto handle_data_failed;
5684         break;
5685       default:
5686         GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
5687             message.type);
5688         break;
5689     }
5690   }
5691   g_assert_not_reached ();
5692
5693   /* ERRORS */
5694 server_eof:
5695   {
5696     GST_DEBUG_OBJECT (src, "we got an eof from the server");
5697     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5698         ("The server closed the connection."));
5699     src->conninfo.connected = FALSE;
5700     gst_rtsp_message_unset (&message);
5701     return GST_FLOW_EOS;
5702   }
5703 interrupt:
5704   {
5705     gst_rtsp_message_unset (&message);
5706     GST_DEBUG_OBJECT (src, "got interrupted");
5707     return GST_FLOW_FLUSHING;
5708   }
5709 receive_error:
5710   {
5711     gchar *str = gst_rtsp_strresult (res);
5712
5713 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5714     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_SERVER,
5715         "Could not receive message.");
5716 #else
5717     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
5718         ("Could not receive message. (%s)", str));
5719 #endif
5720     g_free (str);
5721
5722     gst_rtsp_message_unset (&message);
5723     return GST_FLOW_ERROR;
5724   }
5725 handle_request_failed:
5726   {
5727     gchar *str = gst_rtsp_strresult (res);
5728
5729 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5730     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_SERVICE_UNAVAILABLE,
5731         "Could not handle server message.");
5732 #else
5733     GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
5734         ("Could not handle server message. (%s)", str));
5735 #endif
5736     g_free (str);
5737     gst_rtsp_message_unset (&message);
5738     return GST_FLOW_ERROR;
5739   }
5740 handle_data_failed:
5741   {
5742     GST_DEBUG_OBJECT (src, "could no handle data message");
5743     return ret;
5744   }
5745 }
5746
5747 static GstFlowReturn
5748 gst_rtspsrc_loop_udp (GstRTSPSrc * src)
5749 {
5750   GstRTSPResult res;
5751   GstRTSPMessage message = { 0 };
5752   gint retry = 0;
5753
5754   while (TRUE) {
5755     GTimeVal tv_timeout;
5756
5757     /* get the next timeout interval */
5758     gst_rtsp_connection_next_timeout (src->conninfo.connection, &tv_timeout);
5759
5760     GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds",
5761         (gint) tv_timeout.tv_sec);
5762
5763     gst_rtsp_message_unset (&message);
5764
5765     /* we should continue reading the TCP socket because the server might
5766      * send us requests. When the session timeout expires, we need to send a
5767      * keep-alive request to keep the session open. */
5768     res = gst_rtspsrc_connection_receive (src, &src->conninfo,
5769         &message, &tv_timeout);
5770
5771     switch (res) {
5772       case GST_RTSP_OK:
5773         GST_DEBUG_OBJECT (src, "we received a server message");
5774         break;
5775       case GST_RTSP_EINTR:
5776         /* we got interrupted, see what we have to do */
5777         goto interrupt;
5778       case GST_RTSP_ETIMEOUT:
5779         /* send keep-alive, ignore the result, a warning will be posted. */
5780         GST_DEBUG_OBJECT (src, "timeout, sending keep-alive");
5781         if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5782           goto interrupt;
5783         continue;
5784       case GST_RTSP_EEOF:
5785         /* server closed the connection. not very fatal for UDP, reconnect and
5786          * see what happens. */
5787         GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5788             ("The server closed the connection."));
5789         if (src->udp_reconnect) {
5790           if ((res =
5791                   gst_rtsp_conninfo_reconnect (src, &src->conninfo, FALSE)) < 0)
5792             goto connect_error;
5793         } else {
5794           goto server_eof;
5795         }
5796         continue;
5797       case GST_RTSP_ENET:
5798         GST_DEBUG_OBJECT (src, "An ethernet problem occured.");
5799       default:
5800         GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5801             ("Unhandled return value %d.", res));
5802         goto receive_error;
5803     }
5804
5805     switch (message.type) {
5806       case GST_RTSP_MESSAGE_REQUEST:
5807         /* server sends us a request message, handle it */
5808         res = gst_rtspsrc_handle_request (src, &src->conninfo, &message);
5809         if (res == GST_RTSP_EEOF)
5810           goto server_eof;
5811         else if (res < 0)
5812           goto handle_request_failed;
5813         break;
5814       case GST_RTSP_MESSAGE_RESPONSE:
5815         /* we ignore response and data messages */
5816         GST_DEBUG_OBJECT (src, "ignoring response message");
5817         DEBUG_RTSP (src, &message);
5818         if (message.type_data.response.code == GST_RTSP_STS_UNAUTHORIZED) {
5819           GST_DEBUG_OBJECT (src, "but is Unauthorized response ...");
5820           if (gst_rtspsrc_setup_auth (src, &message) && !(retry++)) {
5821             GST_DEBUG_OBJECT (src, "so retrying keep-alive");
5822             if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5823               goto interrupt;
5824           }
5825         } else {
5826           retry = 0;
5827         }
5828         break;
5829       case GST_RTSP_MESSAGE_DATA:
5830         /* we ignore response and data messages */
5831         GST_DEBUG_OBJECT (src, "ignoring data message");
5832         break;
5833       default:
5834         GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
5835             message.type);
5836         break;
5837     }
5838   }
5839   g_assert_not_reached ();
5840
5841   /* we get here when the connection got interrupted */
5842 interrupt:
5843   {
5844     gst_rtsp_message_unset (&message);
5845     GST_DEBUG_OBJECT (src, "got interrupted");
5846     return GST_FLOW_FLUSHING;
5847   }
5848 connect_error:
5849   {
5850     gchar *str = gst_rtsp_strresult (res);
5851     GstFlowReturn ret;
5852
5853     src->conninfo.connected = FALSE;
5854     if (res != GST_RTSP_EINTR) {
5855 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5856       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
5857           "Could not connect to server.");
5858 #else
5859       GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
5860           ("Could not connect to server. (%s)", str));
5861 #endif
5862       g_free (str);
5863       ret = GST_FLOW_ERROR;
5864     } else {
5865       ret = GST_FLOW_FLUSHING;
5866     }
5867     return ret;
5868   }
5869 receive_error:
5870   {
5871     gchar *str = gst_rtsp_strresult (res);
5872
5873 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5874     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_SERVER_DISCONNECTED,
5875         "Could not receive message.");
5876 #else
5877     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
5878         ("Could not receive message. (%s)", str));
5879 #endif
5880     g_free (str);
5881     return GST_FLOW_ERROR;
5882   }
5883 handle_request_failed:
5884   {
5885     gchar *str = gst_rtsp_strresult (res);
5886     GstFlowReturn ret;
5887
5888     gst_rtsp_message_unset (&message);
5889     if (res != GST_RTSP_EINTR) {
5890 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5891       gst_rtspsrc_post_error_message (src,
5892           GST_RTSPSRC_ERROR_SERVICE_UNAVAILABLE,
5893           "Could not handle server message.");
5894 #else
5895       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
5896           ("Could not handle server message. (%s)", str));
5897 #endif
5898       g_free (str);
5899       ret = GST_FLOW_ERROR;
5900     } else {
5901       ret = GST_FLOW_FLUSHING;
5902     }
5903     return ret;
5904   }
5905 server_eof:
5906   {
5907     GST_DEBUG_OBJECT (src, "we got an eof from the server");
5908     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5909         ("The server closed the connection."));
5910     src->conninfo.connected = FALSE;
5911     gst_rtsp_message_unset (&message);
5912     return GST_FLOW_EOS;
5913   }
5914 }
5915
5916 static GstRTSPResult
5917 gst_rtspsrc_reconnect (GstRTSPSrc * src, gboolean async)
5918 {
5919   GstRTSPResult res = GST_RTSP_OK;
5920   gboolean restart;
5921
5922   GST_DEBUG_OBJECT (src, "doing reconnect");
5923
5924   GST_OBJECT_LOCK (src);
5925   /* only restart when the pads were not yet activated, else we were
5926    * streaming over UDP */
5927   restart = src->need_activate;
5928   GST_OBJECT_UNLOCK (src);
5929
5930   /* no need to restart, we're done */
5931   if (!restart)
5932     goto done;
5933
5934   /* we can try only TCP now */
5935   src->cur_protocols = GST_RTSP_LOWER_TRANS_TCP;
5936
5937   /* close and cleanup our state */
5938   if ((res = gst_rtspsrc_close (src, async, FALSE)) < 0)
5939     goto done;
5940
5941   /* see if we have TCP left to try. Also don't try TCP when we were configured
5942    * with an SDP. */
5943   if (!(src->protocols & GST_RTSP_LOWER_TRANS_TCP) || src->from_sdp)
5944     goto no_protocols;
5945
5946   /* We post a warning message now to inform the user
5947    * that nothing happened. It's most likely a firewall thing. */
5948   GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5949       ("Could not receive any UDP packets for %.4f seconds, maybe your "
5950           "firewall is blocking it. Retrying using a tcp connection.",
5951           gst_guint64_to_gdouble (src->udp_timeout) / 1000000.0));
5952
5953   /* open new connection using tcp */
5954   if (gst_rtspsrc_open (src, async) < 0)
5955     goto open_failed;
5956
5957   /* start playback */
5958   if (gst_rtspsrc_play (src, &src->segment, async, NULL) < 0)
5959     goto play_failed;
5960
5961 done:
5962   return res;
5963
5964   /* ERRORS */
5965 no_protocols:
5966   {
5967     src->cur_protocols = 0;
5968     /* no transport possible, post an error and stop */
5969 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5970     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_TRANSPORT,
5971         "Could not receive any UDP packets for seconds, maybe your firewall is blocking it. No other protocols to try.");
5972 #else
5973     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
5974         ("Could not receive any UDP packets for %.4f seconds, maybe your "
5975             "firewall is blocking it. No other protocols to try.",
5976             gst_guint64_to_gdouble (src->udp_timeout) / 1000000.0));
5977 #endif
5978     return GST_RTSP_ERROR;
5979   }
5980 open_failed:
5981   {
5982     GST_DEBUG_OBJECT (src, "open failed");
5983     return GST_RTSP_OK;
5984   }
5985 play_failed:
5986   {
5987     GST_DEBUG_OBJECT (src, "play failed");
5988     return GST_RTSP_OK;
5989   }
5990 }
5991
5992 static void
5993 gst_rtspsrc_loop_start_cmd (GstRTSPSrc * src, gint cmd)
5994 {
5995   switch (cmd) {
5996     case CMD_OPEN:
5997       GST_ELEMENT_PROGRESS (src, START, "open", ("Opening Stream"));
5998       break;
5999     case CMD_PLAY:
6000       GST_ELEMENT_PROGRESS (src, START, "request", ("Sending PLAY request"));
6001       break;
6002     case CMD_PAUSE:
6003       GST_ELEMENT_PROGRESS (src, START, "request", ("Sending PAUSE request"));
6004       break;
6005     case CMD_GET_PARAMETER:
6006       GST_ELEMENT_PROGRESS (src, START, "request",
6007           ("Sending GET_PARAMETER request"));
6008       break;
6009     case CMD_SET_PARAMETER:
6010       GST_ELEMENT_PROGRESS (src, START, "request",
6011           ("Sending SET_PARAMETER request"));
6012       break;
6013     case CMD_CLOSE:
6014       GST_ELEMENT_PROGRESS (src, START, "close", ("Closing Stream"));
6015       break;
6016     default:
6017       break;
6018   }
6019 }
6020
6021 static void
6022 gst_rtspsrc_loop_complete_cmd (GstRTSPSrc * src, gint cmd)
6023 {
6024 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6025   GstMessage *s;
6026   GST_WARNING_OBJECT (src, "Got cmd %s", cmd_to_string (cmd));
6027 #endif
6028
6029   switch (cmd) {
6030     case CMD_OPEN:
6031 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6032       GST_DEBUG_OBJECT (src,
6033           "rtsp_duration %" GST_TIME_FORMAT
6034           ", rtsp_audio_codec %s , rtsp_video_codec %s , rtsp_video_frame_size %s",
6035           GST_TIME_ARGS (src->segment.duration), src->audio_codec,
6036           src->video_codec, src->video_frame_size);
6037
6038       /* post message */
6039       s = gst_message_new_element (GST_OBJECT_CAST (src),
6040           gst_structure_new ("rtspsrc_properties",
6041               "rtsp_duration", G_TYPE_UINT64, src->segment.duration,
6042               "rtsp_audio_codec", G_TYPE_STRING, src->audio_codec,
6043               "rtsp_video_codec", G_TYPE_STRING, src->video_codec,
6044               "rtsp_video_frame_size", G_TYPE_STRING, src->video_frame_size,
6045               NULL));
6046
6047       gst_element_post_message (GST_ELEMENT_CAST (src), s);
6048 #endif
6049       GST_ELEMENT_PROGRESS (src, COMPLETE, "open", ("Opened Stream"));
6050 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6051       /* rtspsrc PAUSE state should be here for parsing sdp before PAUSE state changed. */
6052       g_mutex_lock (&(src)->pause_lock);
6053       g_cond_signal (&(src)->open_end);
6054       g_mutex_unlock (&(src)->pause_lock);
6055 #endif
6056       break;
6057     case CMD_PLAY:
6058       GST_ELEMENT_PROGRESS (src, COMPLETE, "request", ("Sent PLAY request"));
6059       break;
6060     case CMD_PAUSE:
6061       GST_ELEMENT_PROGRESS (src, COMPLETE, "request", ("Sent PAUSE request"));
6062       break;
6063     case CMD_GET_PARAMETER:
6064       GST_ELEMENT_PROGRESS (src, COMPLETE, "request",
6065           ("Sent GET_PARAMETER request"));
6066       break;
6067     case CMD_SET_PARAMETER:
6068       GST_ELEMENT_PROGRESS (src, COMPLETE, "request",
6069           ("Sent SET_PARAMETER request"));
6070       break;
6071     case CMD_CLOSE:
6072       GST_ELEMENT_PROGRESS (src, COMPLETE, "close", ("Closed Stream"));
6073       break;
6074     default:
6075       break;
6076   }
6077 }
6078
6079 static void
6080 gst_rtspsrc_loop_cancel_cmd (GstRTSPSrc * src, gint cmd)
6081 {
6082   switch (cmd) {
6083     case CMD_OPEN:
6084       GST_ELEMENT_PROGRESS (src, CANCELED, "open", ("Open canceled"));
6085       break;
6086     case CMD_PLAY:
6087       GST_ELEMENT_PROGRESS (src, CANCELED, "request", ("PLAY canceled"));
6088       break;
6089     case CMD_PAUSE:
6090       GST_ELEMENT_PROGRESS (src, CANCELED, "request", ("PAUSE canceled"));
6091       break;
6092     case CMD_GET_PARAMETER:
6093       GST_ELEMENT_PROGRESS (src, CANCELED, "request",
6094           ("GET_PARAMETER canceled"));
6095       break;
6096     case CMD_SET_PARAMETER:
6097       GST_ELEMENT_PROGRESS (src, CANCELED, "request",
6098           ("SET_PARAMETER canceled"));
6099       break;
6100     case CMD_CLOSE:
6101       GST_ELEMENT_PROGRESS (src, CANCELED, "close", ("Close canceled"));
6102       break;
6103     default:
6104       break;
6105   }
6106 }
6107
6108 static void
6109 gst_rtspsrc_loop_error_cmd (GstRTSPSrc * src, gint cmd)
6110 {
6111   switch (cmd) {
6112     case CMD_OPEN:
6113       GST_ELEMENT_PROGRESS (src, ERROR, "open", ("Open failed"));
6114 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6115       /* Ending conditional wait for pause when open fails.*/
6116       g_mutex_lock (&(src)->pause_lock);
6117       g_cond_signal (&(src)->open_end);
6118       g_mutex_unlock (&(src)->pause_lock);
6119       GST_WARNING_OBJECT (src,
6120           "ending conditional wait for pause as open is failed.");
6121 #endif
6122       break;
6123     case CMD_PLAY:
6124       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("PLAY failed"));
6125       break;
6126     case CMD_PAUSE:
6127       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("PAUSE failed"));
6128       break;
6129     case CMD_GET_PARAMETER:
6130       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("GET_PARAMETER failed"));
6131       break;
6132     case CMD_SET_PARAMETER:
6133       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("SET_PARAMETER failed"));
6134       break;
6135     case CMD_CLOSE:
6136       GST_ELEMENT_PROGRESS (src, ERROR, "close", ("Close failed"));
6137       break;
6138     default:
6139       break;
6140   }
6141 }
6142
6143 static void
6144 gst_rtspsrc_loop_end_cmd (GstRTSPSrc * src, gint cmd, GstRTSPResult ret)
6145 {
6146   if (ret == GST_RTSP_OK)
6147     gst_rtspsrc_loop_complete_cmd (src, cmd);
6148   else if (ret == GST_RTSP_EINTR)
6149     gst_rtspsrc_loop_cancel_cmd (src, cmd);
6150   else
6151     gst_rtspsrc_loop_error_cmd (src, cmd);
6152 }
6153
6154 static gboolean
6155 gst_rtspsrc_loop_send_cmd (GstRTSPSrc * src, gint cmd, gint mask)
6156 {
6157   gint old;
6158   gboolean flushed = FALSE;
6159
6160   /* start new request */
6161   gst_rtspsrc_loop_start_cmd (src, cmd);
6162
6163   GST_DEBUG_OBJECT (src, "sending cmd %s", cmd_to_string (cmd));
6164
6165   GST_OBJECT_LOCK (src);
6166   old = src->pending_cmd;
6167
6168   if (old == CMD_RECONNECT) {
6169     GST_DEBUG_OBJECT (src, "ignore, we were reconnecting");
6170     cmd = CMD_RECONNECT;
6171   } else if (old == CMD_CLOSE) {
6172     /* our CMD_CLOSE might have interrutped CMD_LOOP. gst_rtspsrc_loop
6173      * will send a CMD_WAIT which would cancel our pending CMD_CLOSE (if
6174      * still pending). We just avoid it here by making sure CMD_CLOSE is
6175      * still the pending command. */
6176     GST_DEBUG_OBJECT (src, "ignore, we were closing");
6177     cmd = CMD_CLOSE;
6178   } else if (old == CMD_SET_PARAMETER) {
6179     GST_DEBUG_OBJECT (src, "ignore, we have a pending %s", cmd_to_string (old));
6180     cmd = CMD_SET_PARAMETER;
6181   } else if (old == CMD_GET_PARAMETER) {
6182     GST_DEBUG_OBJECT (src, "ignore, we have a pending %s", cmd_to_string (old));
6183     cmd = CMD_GET_PARAMETER;
6184   } else if (old != CMD_WAIT) {
6185     src->pending_cmd = CMD_WAIT;
6186     GST_OBJECT_UNLOCK (src);
6187     /* cancel previous request */
6188     GST_DEBUG_OBJECT (src, "cancel previous request %s", cmd_to_string (old));
6189     gst_rtspsrc_loop_cancel_cmd (src, old);
6190     GST_OBJECT_LOCK (src);
6191   }
6192   src->pending_cmd = cmd;
6193   /* interrupt if allowed */
6194   if (src->busy_cmd & mask) {
6195     GST_DEBUG_OBJECT (src, "connection flush busy %s",
6196         cmd_to_string (src->busy_cmd));
6197     gst_rtspsrc_connection_flush (src, TRUE);
6198     flushed = TRUE;
6199   } else {
6200     GST_DEBUG_OBJECT (src, "not interrupting busy cmd %s",
6201         cmd_to_string (src->busy_cmd));
6202   }
6203   if (src->task)
6204     gst_task_start (src->task);
6205   GST_OBJECT_UNLOCK (src);
6206
6207   return flushed;
6208 }
6209
6210 static gboolean
6211 gst_rtspsrc_loop_send_cmd_and_wait (GstRTSPSrc * src, gint cmd, gint mask,
6212     GstClockTime timeout)
6213 {
6214   gboolean flushed = gst_rtspsrc_loop_send_cmd (src, cmd, mask);
6215
6216   if (timeout > 0) {
6217     gint64 end_time = g_get_monotonic_time () + (timeout / 1000);
6218     GST_OBJECT_LOCK (src);
6219     while (src->pending_cmd == cmd || src->busy_cmd == cmd) {
6220       if (!g_cond_wait_until (&src->cmd_cond, GST_OBJECT_GET_LOCK (src),
6221               end_time)) {
6222         GST_WARNING_OBJECT (src,
6223             "Timed out waiting for TEARDOWN to be processed.");
6224         break;                  /* timeout passed */
6225       }
6226     }
6227     GST_OBJECT_UNLOCK (src);
6228   }
6229   return flushed;
6230 }
6231
6232 static gboolean
6233 gst_rtspsrc_loop (GstRTSPSrc * src)
6234 {
6235   GstFlowReturn ret;
6236
6237   if (!src->conninfo.connection || !src->conninfo.connected)
6238     goto no_connection;
6239
6240   if (src->interleaved)
6241     ret = gst_rtspsrc_loop_interleaved (src);
6242   else
6243     ret = gst_rtspsrc_loop_udp (src);
6244
6245   if (ret != GST_FLOW_OK)
6246     goto pause;
6247
6248   return TRUE;
6249
6250   /* ERRORS */
6251 no_connection:
6252   {
6253     GST_WARNING_OBJECT (src, "we are not connected");
6254     ret = GST_FLOW_FLUSHING;
6255     goto pause;
6256   }
6257 pause:
6258   {
6259     const gchar *reason = gst_flow_get_name (ret);
6260
6261     GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
6262     src->running = FALSE;
6263     if (ret == GST_FLOW_EOS) {
6264       /* perform EOS logic */
6265       if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6266         gst_element_post_message (GST_ELEMENT_CAST (src),
6267             gst_message_new_segment_done (GST_OBJECT_CAST (src),
6268                 src->segment.format, src->segment.position));
6269         gst_rtspsrc_push_event (src,
6270             gst_event_new_segment_done (src->segment.format,
6271                 src->segment.position));
6272       } else {
6273         gst_rtspsrc_push_event (src, gst_event_new_eos ());
6274       }
6275     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6276       /* for fatal errors we post an error message, post the error before the
6277        * EOS so the app knows about the error first. */
6278       GST_ELEMENT_FLOW_ERROR (src, ret);
6279       gst_rtspsrc_push_event (src, gst_event_new_eos ());
6280     }
6281     gst_rtspsrc_loop_send_cmd (src, CMD_WAIT, CMD_LOOP);
6282     return FALSE;
6283   }
6284 }
6285
6286 #ifndef GST_DISABLE_GST_DEBUG
6287 static const gchar *
6288 gst_rtsp_auth_method_to_string (GstRTSPAuthMethod method)
6289 {
6290   gint index = 0;
6291
6292   while (method != 0) {
6293     index++;
6294     method >>= 1;
6295   }
6296   switch (index) {
6297     case 0:
6298       return "None";
6299     case 1:
6300       return "Basic";
6301     case 2:
6302       return "Digest";
6303   }
6304
6305   return "Unknown";
6306 }
6307 #endif
6308
6309 /* Parse a WWW-Authenticate Response header and determine the
6310  * available authentication methods
6311  *
6312  * This code should also cope with the fact that each WWW-Authenticate
6313  * header can contain multiple challenge methods + tokens
6314  *
6315  * At the moment, for Basic auth, we just do a minimal check and don't
6316  * even parse out the realm */
6317 static void
6318 gst_rtspsrc_parse_auth_hdr (GstRTSPMessage * response,
6319     GstRTSPAuthMethod * methods, GstRTSPConnection * conn, gboolean * stale)
6320 {
6321   GstRTSPAuthCredential **credentials, **credential;
6322
6323   g_return_if_fail (response != NULL);
6324   g_return_if_fail (methods != NULL);
6325   g_return_if_fail (stale != NULL);
6326
6327   credentials =
6328       gst_rtsp_message_parse_auth_credentials (response,
6329       GST_RTSP_HDR_WWW_AUTHENTICATE);
6330   if (!credentials)
6331     return;
6332
6333   credential = credentials;
6334   while (*credential) {
6335     if ((*credential)->scheme == GST_RTSP_AUTH_BASIC) {
6336       *methods |= GST_RTSP_AUTH_BASIC;
6337     } else if ((*credential)->scheme == GST_RTSP_AUTH_DIGEST) {
6338       GstRTSPAuthParam **param = (*credential)->params;
6339
6340       *methods |= GST_RTSP_AUTH_DIGEST;
6341
6342       gst_rtsp_connection_clear_auth_params (conn);
6343       *stale = FALSE;
6344
6345       while (*param) {
6346         if (strcmp ((*param)->name, "stale") == 0
6347             && g_ascii_strcasecmp ((*param)->value, "TRUE") == 0)
6348           *stale = TRUE;
6349         gst_rtsp_connection_set_auth_param (conn, (*param)->name,
6350             (*param)->value);
6351         param++;
6352       }
6353     }
6354
6355     credential++;
6356   }
6357
6358   gst_rtsp_auth_credentials_free (credentials);
6359 }
6360
6361 /**
6362  * gst_rtspsrc_setup_auth:
6363  * @src: the rtsp source
6364  *
6365  * Configure a username and password and auth method on the
6366  * connection object based on a response we received from the
6367  * peer.
6368  *
6369  * Currently, this requires that a username and password were supplied
6370  * in the uri. In the future, they may be requested on demand by sending
6371  * a message up the bus.
6372  *
6373  * Returns: TRUE if authentication information could be set up correctly.
6374  */
6375 static gboolean
6376 gst_rtspsrc_setup_auth (GstRTSPSrc * src, GstRTSPMessage * response)
6377 {
6378   gchar *user = NULL;
6379   gchar *pass = NULL;
6380   GstRTSPAuthMethod avail_methods = GST_RTSP_AUTH_NONE;
6381   GstRTSPAuthMethod method;
6382   GstRTSPResult auth_result;
6383   GstRTSPUrl *url;
6384   GstRTSPConnection *conn;
6385   gboolean stale = FALSE;
6386
6387   conn = src->conninfo.connection;
6388
6389   /* Identify the available auth methods and see if any are supported */
6390   gst_rtspsrc_parse_auth_hdr (response, &avail_methods, conn, &stale);
6391
6392   if (avail_methods == GST_RTSP_AUTH_NONE)
6393     goto no_auth_available;
6394
6395   /* For digest auth, if the response indicates that the session
6396    * data are stale, we just update them in the connection object and
6397    * return TRUE to retry the request */
6398   if (stale)
6399     src->tried_url_auth = FALSE;
6400
6401   url = gst_rtsp_connection_get_url (conn);
6402
6403   /* Do we have username and password available? */
6404   if (url != NULL && !src->tried_url_auth && url->user != NULL
6405       && url->passwd != NULL) {
6406     user = url->user;
6407     pass = url->passwd;
6408     src->tried_url_auth = TRUE;
6409     GST_DEBUG_OBJECT (src,
6410         "Attempting authentication using credentials from the URL");
6411   } else {
6412     user = src->user_id;
6413     pass = src->user_pw;
6414     GST_DEBUG_OBJECT (src,
6415         "Attempting authentication using credentials from the properties");
6416   }
6417
6418   /* FIXME: If the url didn't contain username and password or we tried them
6419    * already, request a username and passwd from the application via some kind
6420    * of credentials request message */
6421
6422   /* If we don't have a username and passwd at this point, bail out. */
6423   if (user == NULL || pass == NULL)
6424     goto no_user_pass;
6425
6426   /* Try to configure for each available authentication method, strongest to
6427    * weakest */
6428   for (method = GST_RTSP_AUTH_MAX; method != GST_RTSP_AUTH_NONE; method >>= 1) {
6429     /* Check if this method is available on the server */
6430     if ((method & avail_methods) == 0)
6431       continue;
6432
6433     /* Pass the credentials to the connection to try on the next request */
6434     auth_result = gst_rtsp_connection_set_auth (conn, method, user, pass);
6435     /* INVAL indicates an invalid username/passwd were supplied, so we'll just
6436      * ignore it and end up retrying later */
6437     if (auth_result == GST_RTSP_OK || auth_result == GST_RTSP_EINVAL) {
6438       GST_DEBUG_OBJECT (src, "Attempting %s authentication",
6439           gst_rtsp_auth_method_to_string (method));
6440       break;
6441     }
6442   }
6443
6444   if (method == GST_RTSP_AUTH_NONE)
6445     goto no_auth_available;
6446
6447   return TRUE;
6448
6449 no_auth_available:
6450   {
6451     /* Output an error indicating that we couldn't connect because there were
6452      * no supported authentication protocols */
6453 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6454     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_NOT_AUTHORIZED,
6455         "No supported authentication protocol was found");
6456 #else
6457     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
6458         ("No supported authentication protocol was found"));
6459 #endif
6460     return FALSE;
6461   }
6462 no_user_pass:
6463   {
6464     /* We don't fire an error message, we just return FALSE and let the
6465      * normal NOT_AUTHORIZED error be propagated */
6466     return FALSE;
6467   }
6468 }
6469
6470 static GstRTSPResult
6471 gst_rtsp_src_receive_response (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
6472     GstRTSPMessage * response, GstRTSPStatusCode * code)
6473 {
6474   GstRTSPStatusCode thecode;
6475   gchar *content_base = NULL;
6476   GstRTSPResult res = gst_rtspsrc_connection_receive (src, conninfo,
6477       response, src->ptcp_timeout);
6478
6479   if (res < 0)
6480     goto receive_error;
6481
6482   DEBUG_RTSP (src, response);
6483
6484   switch (response->type) {
6485     case GST_RTSP_MESSAGE_REQUEST:
6486       res = gst_rtspsrc_handle_request (src, conninfo, response);
6487       if (res == GST_RTSP_EEOF)
6488         goto server_eof;
6489       else if (res < 0)
6490         goto handle_request_failed;
6491
6492       /* Not a response, receive next message */
6493       return gst_rtsp_src_receive_response (src, conninfo, response, code);
6494     case GST_RTSP_MESSAGE_RESPONSE:
6495       /* ok, a response is good */
6496       GST_DEBUG_OBJECT (src, "received response message");
6497       break;
6498     case GST_RTSP_MESSAGE_DATA:
6499       /* get next response */
6500       GST_DEBUG_OBJECT (src, "handle data response message");
6501       gst_rtspsrc_handle_data (src, response);
6502
6503       /* Not a response, receive next message */
6504       return gst_rtsp_src_receive_response (src, conninfo, response, code);
6505     default:
6506       GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
6507           response->type);
6508
6509       /* Not a response, receive next message */
6510       return gst_rtsp_src_receive_response (src, conninfo, response, code);
6511   }
6512
6513   thecode = response->type_data.response.code;
6514
6515   GST_DEBUG_OBJECT (src, "got response message %d", thecode);
6516
6517   /* if the caller wanted the result code, we store it. */
6518   if (code)
6519     *code = thecode;
6520
6521   /* If the request didn't succeed, bail out before doing any more */
6522   if (thecode != GST_RTSP_STS_OK)
6523     return GST_RTSP_OK;
6524
6525   /* store new content base if any */
6526   gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_BASE,
6527       &content_base, 0);
6528   if (content_base) {
6529     g_free (src->content_base);
6530     src->content_base = g_strdup (content_base);
6531   }
6532
6533   return GST_RTSP_OK;
6534
6535   /* ERRORS */
6536 receive_error:
6537   {
6538     switch (res) {
6539       case GST_RTSP_EEOF:
6540         return GST_RTSP_EEOF;
6541       default:
6542       {
6543         gchar *str = gst_rtsp_strresult (res);
6544
6545         if (res != GST_RTSP_EINTR) {
6546 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6547           gst_rtspsrc_post_error_message (src,
6548               GST_RTSPSRC_ERROR_SERVER_DISCONNECTED,
6549               "Could not receive message.");
6550 #else
6551           GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
6552               ("Could not receive message. (%s)", str));
6553 #endif
6554         } else {
6555           GST_WARNING_OBJECT (src, "receive interrupted");
6556         }
6557         g_free (str);
6558         break;
6559       }
6560     }
6561     return res;
6562   }
6563 handle_request_failed:
6564   {
6565     /* ERROR was posted */
6566     gst_rtsp_message_unset (response);
6567     return res;
6568   }
6569 server_eof:
6570   {
6571     GST_DEBUG_OBJECT (src, "we got an eof from the server");
6572     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
6573         ("The server closed the connection."));
6574     gst_rtsp_message_unset (response);
6575     return res;
6576   }
6577 }
6578
6579
6580 static GstRTSPResult
6581 gst_rtspsrc_try_send (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
6582     GstRTSPMessage * request, GstRTSPMessage * response,
6583     GstRTSPStatusCode * code)
6584 {
6585   GstRTSPResult res;
6586   gint try = 0;
6587   gboolean allow_send = TRUE;
6588
6589 again:
6590   if (!src->short_header)
6591     gst_rtsp_ext_list_before_send (src->extensions, request);
6592
6593   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_BEFORE_SEND], 0,
6594       request, &allow_send);
6595   if (!allow_send) {
6596     GST_DEBUG_OBJECT (src, "skipping message, disabled by signal");
6597     return GST_RTSP_OK;
6598   }
6599
6600   GST_DEBUG_OBJECT (src, "sending message");
6601
6602   DEBUG_RTSP (src, request);
6603
6604   res = gst_rtspsrc_connection_send (src, conninfo, request, src->ptcp_timeout);
6605   if (res < 0)
6606     goto send_error;
6607
6608   gst_rtsp_connection_reset_timeout (conninfo->connection);
6609   if (!response)
6610     return res;
6611
6612   res = gst_rtsp_src_receive_response (src, conninfo, response, code);
6613   if (res == GST_RTSP_EEOF) {
6614     GST_WARNING_OBJECT (src, "server closed connection");
6615     /* only try once after reconnect, then fallthrough and error out */
6616     if ((try == 0) && !src->interleaved && src->udp_reconnect) {
6617       try++;
6618       /* if reconnect succeeds, try again */
6619       if ((res = gst_rtsp_conninfo_reconnect (src, &src->conninfo, FALSE)) == 0)
6620         goto again;
6621     }
6622   }
6623   gst_rtsp_ext_list_after_send (src->extensions, request, response);
6624
6625   return res;
6626
6627 send_error:
6628   {
6629     gchar *str = gst_rtsp_strresult (res);
6630
6631     if (res != GST_RTSP_EINTR) {
6632 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6633       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
6634           "Could not send message.");
6635 #else
6636       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
6637           ("Could not send message. (%s)", str));
6638 #endif
6639     } else {
6640       GST_WARNING_OBJECT (src, "send interrupted");
6641     }
6642     g_free (str);
6643     return res;
6644   }
6645 }
6646
6647 /**
6648  * gst_rtspsrc_send:
6649  * @src: the rtsp source
6650  * @conninfo: the connection information to send on
6651  * @request: must point to a valid request
6652  * @response: must point to an empty #GstRTSPMessage
6653  * @code: an optional code result
6654  * @versions: List of versions to try, setting it back onto the @request message
6655  *            if not set, `src->version` will be used as RTSP version.
6656  *
6657  * send @request and retrieve the response in @response. optionally @code can be
6658  * non-NULL in which case it will contain the status code of the response.
6659  *
6660  * If This function returns #GST_RTSP_OK, @response will contain a valid response
6661  * message that should be cleaned with gst_rtsp_message_unset() after usage.
6662  *
6663  * If @code is NULL, this function will return #GST_RTSP_ERROR (with an invalid
6664  * @response message) if the response code was not 200 (OK).
6665  *
6666  * If the attempt results in an authentication failure, then this will attempt
6667  * to retrieve authentication credentials via gst_rtspsrc_setup_auth and retry
6668  * the request.
6669  *
6670  * Returns: #GST_RTSP_OK if the processing was successful.
6671  */
6672 static GstRTSPResult
6673 gst_rtspsrc_send (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
6674     GstRTSPMessage * request, GstRTSPMessage * response,
6675     GstRTSPStatusCode * code, GstRTSPVersion * versions)
6676 {
6677   GstRTSPStatusCode int_code = GST_RTSP_STS_OK;
6678   GstRTSPResult res = GST_RTSP_ERROR;
6679   gint count;
6680   gboolean retry;
6681   GstRTSPMethod method = GST_RTSP_INVALID;
6682   gint version_retry = 0;
6683
6684   count = 0;
6685   do {
6686     retry = FALSE;
6687
6688     /* make sure we don't loop forever */
6689     if (count++ > 8)
6690       break;
6691
6692     /* save method so we can disable it when the server complains */
6693     method = request->type_data.request.method;
6694
6695     if (!versions)
6696       request->type_data.request.version = src->version;
6697
6698     if ((res =
6699             gst_rtspsrc_try_send (src, conninfo, request, response,
6700                 &int_code)) < 0)
6701       goto error;
6702
6703     switch (int_code) {
6704       case GST_RTSP_STS_UNAUTHORIZED:
6705       case GST_RTSP_STS_NOT_FOUND:
6706         if (gst_rtspsrc_setup_auth (src, response)) {
6707           /* Try the request/response again after configuring the auth info
6708            * and loop again */
6709           retry = TRUE;
6710         }
6711         break;
6712       case GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED:
6713         GST_INFO_OBJECT (src, "Version %s not supported by the server",
6714             versions ? gst_rtsp_version_as_text (versions[version_retry]) :
6715             "unknown");
6716         if (versions && versions[version_retry] != GST_RTSP_VERSION_INVALID) {
6717           GST_INFO_OBJECT (src, "Unsupported version %s => trying %s",
6718               gst_rtsp_version_as_text (request->type_data.request.version),
6719               gst_rtsp_version_as_text (versions[version_retry]));
6720           request->type_data.request.version = versions[version_retry];
6721           retry = TRUE;
6722           version_retry++;
6723           break;
6724         }
6725         /* falltrough */
6726       default:
6727         break;
6728     }
6729   } while (retry == TRUE);
6730
6731   /* If the user requested the code, let them handle errors, otherwise
6732    * post an error below */
6733   if (code != NULL)
6734     *code = int_code;
6735   else if (int_code != GST_RTSP_STS_OK)
6736     goto error_response;
6737
6738   return res;
6739
6740   /* ERRORS */
6741 error:
6742   {
6743     GST_DEBUG_OBJECT (src, "got error %d", res);
6744     return res;
6745   }
6746 error_response:
6747   {
6748     res = GST_RTSP_ERROR;
6749
6750     switch (response->type_data.response.code) {
6751       case GST_RTSP_STS_NOT_FOUND:
6752 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6753         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
6754             "STS NOT FOUND");
6755 #else
6756         RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, NOT_FOUND,
6757             "Not found");
6758 #endif
6759         break;
6760       case GST_RTSP_STS_UNAUTHORIZED:
6761 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6762         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_NOT_AUTHORIZED,
6763             "STS NOT AUTHORIZED");
6764 #else
6765         RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, NOT_AUTHORIZED,
6766             "Unauthorized");
6767 #endif
6768         break;
6769       case GST_RTSP_STS_MOVED_PERMANENTLY:
6770       case GST_RTSP_STS_MOVE_TEMPORARILY:
6771       {
6772         gchar *new_location;
6773         GstRTSPLowerTrans transports;
6774
6775         GST_DEBUG_OBJECT (src, "got redirection");
6776         /* if we don't have a Location Header, we must error */
6777         if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_LOCATION,
6778                 &new_location, 0) < 0)
6779           break;
6780
6781         /* When we receive a redirect result, we go back to the INIT state after
6782          * parsing the new URI. The caller should do the needed steps to issue
6783          * a new setup when it detects this state change. */
6784         GST_DEBUG_OBJECT (src, "redirection to %s", new_location);
6785
6786         /* save current transports */
6787         if (src->conninfo.url)
6788           transports = src->conninfo.url->transports;
6789         else
6790           transports = GST_RTSP_LOWER_TRANS_UNKNOWN;
6791
6792         gst_rtspsrc_uri_set_uri (GST_URI_HANDLER (src), new_location, NULL);
6793
6794         /* set old transports */
6795         if (src->conninfo.url && transports != GST_RTSP_LOWER_TRANS_UNKNOWN)
6796           src->conninfo.url->transports = transports;
6797
6798         src->need_redirect = TRUE;
6799         res = GST_RTSP_OK;
6800         break;
6801       }
6802       case GST_RTSP_STS_NOT_ACCEPTABLE:
6803       case GST_RTSP_STS_NOT_IMPLEMENTED:
6804       case GST_RTSP_STS_METHOD_NOT_ALLOWED:
6805         GST_WARNING_OBJECT (src, "got NOT IMPLEMENTED, disable method %s",
6806             gst_rtsp_method_as_text (method));
6807         src->methods &= ~method;
6808         res = GST_RTSP_OK;
6809         break;
6810       default:
6811 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6812         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_UNEXPECTED_MSG,
6813             "Got error response from Server");
6814 #else
6815         RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, READ,
6816             "Unhandled error");
6817 #endif
6818         break;
6819     }
6820     /* if we return ERROR we should unset the response ourselves */
6821     if (res == GST_RTSP_ERROR)
6822       gst_rtsp_message_unset (response);
6823
6824     return res;
6825   }
6826 }
6827
6828 static GstRTSPResult
6829 gst_rtspsrc_send_cb (GstRTSPExtension * ext, GstRTSPMessage * request,
6830     GstRTSPMessage * response, GstRTSPSrc * src)
6831 {
6832   return gst_rtspsrc_send (src, &src->conninfo, request, response, NULL, NULL);
6833 }
6834
6835
6836 /* parse the response and collect all the supported methods. We need this
6837  * information so that we don't try to send an unsupported request to the
6838  * server.
6839  */
6840 static gboolean
6841 gst_rtspsrc_parse_methods (GstRTSPSrc * src, GstRTSPMessage * response)
6842 {
6843   GstRTSPHeaderField field;
6844   gchar *respoptions;
6845   gint indx = 0;
6846
6847   /* reset supported methods */
6848   src->methods = 0;
6849
6850   /* Try Allow Header first */
6851   field = GST_RTSP_HDR_ALLOW;
6852   while (TRUE) {
6853     respoptions = NULL;
6854     gst_rtsp_message_get_header (response, field, &respoptions, indx);
6855     if (!respoptions)
6856       break;
6857
6858     src->methods |= gst_rtsp_options_from_text (respoptions);
6859
6860     indx++;
6861   }
6862
6863   indx = 0;
6864   field = GST_RTSP_HDR_PUBLIC;
6865   while (TRUE) {
6866     respoptions = NULL;
6867     gst_rtsp_message_get_header (response, field, &respoptions, indx);
6868     if (!respoptions)
6869       break;
6870
6871     src->methods |= gst_rtsp_options_from_text (respoptions);
6872
6873     indx++;
6874   }
6875
6876   if (src->methods == 0) {
6877     /* neither Allow nor Public are required, assume the server supports
6878      * at least DESCRIBE, SETUP, we always assume it supports PLAY as
6879      * well. */
6880     GST_DEBUG_OBJECT (src, "could not get OPTIONS");
6881     src->methods = GST_RTSP_DESCRIBE | GST_RTSP_SETUP;
6882   }
6883   /* always assume PLAY, FIXME, extensions should be able to override
6884    * this */
6885   src->methods |= GST_RTSP_PLAY;
6886   /* also assume it will support Range */
6887   src->seekable = G_MAXFLOAT;
6888
6889   /* we need describe and setup */
6890   if (!(src->methods & GST_RTSP_DESCRIBE))
6891     goto no_describe;
6892   if (!(src->methods & GST_RTSP_SETUP))
6893     goto no_setup;
6894
6895   return TRUE;
6896
6897   /* ERRORS */
6898 no_describe:
6899   {
6900 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6901     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_METHOD_NOT_ALLOWED,
6902         "Server does not support DESCRIBE.");
6903 #else
6904     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
6905         ("Server does not support DESCRIBE."));
6906 #endif
6907     return FALSE;
6908   }
6909 no_setup:
6910   {
6911 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6912     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_METHOD_NOT_ALLOWED,
6913         "Server does not support SETUP.");
6914 #else
6915     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
6916         ("Server does not support SETUP."));
6917 #endif
6918     return FALSE;
6919   }
6920 }
6921
6922 /* masks to be kept in sync with the hardcoded protocol order of preference
6923  * in code below */
6924 static const guint protocol_masks[] = {
6925   GST_RTSP_LOWER_TRANS_UDP,
6926   GST_RTSP_LOWER_TRANS_UDP_MCAST,
6927   GST_RTSP_LOWER_TRANS_TCP,
6928   0
6929 };
6930
6931 static GstRTSPResult
6932 gst_rtspsrc_create_transports_string (GstRTSPSrc * src,
6933     GstRTSPLowerTrans protocols, GstRTSPProfile profile, gchar ** transports)
6934 {
6935   GstRTSPResult res;
6936   GString *result;
6937   gboolean add_udp_str;
6938
6939   *transports = NULL;
6940
6941   res =
6942       gst_rtsp_ext_list_get_transports (src->extensions, protocols, transports);
6943
6944   if (res < 0)
6945     goto failed;
6946
6947   GST_DEBUG_OBJECT (src, "got transports %s", GST_STR_NULL (*transports));
6948
6949   /* extension listed transports, use those */
6950   if (*transports != NULL)
6951     return GST_RTSP_OK;
6952
6953   /* it's the default */
6954   add_udp_str = FALSE;
6955
6956   /* the default RTSP transports */
6957   result = g_string_new ("RTP");
6958
6959   switch (profile) {
6960     case GST_RTSP_PROFILE_AVP:
6961       g_string_append (result, "/AVP");
6962       break;
6963     case GST_RTSP_PROFILE_SAVP:
6964       g_string_append (result, "/SAVP");
6965       break;
6966     case GST_RTSP_PROFILE_AVPF:
6967       g_string_append (result, "/AVPF");
6968       break;
6969     case GST_RTSP_PROFILE_SAVPF:
6970       g_string_append (result, "/SAVPF");
6971       break;
6972     default:
6973       break;
6974   }
6975
6976   if (protocols & GST_RTSP_LOWER_TRANS_UDP) {
6977     GST_DEBUG_OBJECT (src, "adding UDP unicast");
6978     if (add_udp_str)
6979       g_string_append (result, "/UDP");
6980     g_string_append (result, ";unicast;client_port=%%u1-%%u2");
6981   } else if (protocols & GST_RTSP_LOWER_TRANS_UDP_MCAST) {
6982     GST_DEBUG_OBJECT (src, "adding UDP multicast");
6983     /* we don't have to allocate any UDP ports yet, if the selected transport
6984      * turns out to be multicast we can create them and join the multicast
6985      * group indicated in the transport reply */
6986     if (add_udp_str)
6987       g_string_append (result, "/UDP");
6988     g_string_append (result, ";multicast");
6989     if (src->next_port_num != 0) {
6990       if (src->client_port_range.max > 0 &&
6991           src->next_port_num >= src->client_port_range.max)
6992         goto no_ports;
6993
6994       g_string_append_printf (result, ";client_port=%d-%d",
6995           src->next_port_num, src->next_port_num + 1);
6996     }
6997   } else if (protocols & GST_RTSP_LOWER_TRANS_TCP) {
6998     GST_DEBUG_OBJECT (src, "adding TCP");
6999
7000     g_string_append (result, "/TCP;unicast;interleaved=%%i1-%%i2");
7001   }
7002   *transports = g_string_free (result, FALSE);
7003
7004   GST_DEBUG_OBJECT (src, "prepared transports %s", GST_STR_NULL (*transports));
7005
7006   return GST_RTSP_OK;
7007
7008   /* ERRORS */
7009 failed:
7010   {
7011     GST_ERROR ("extension gave error %d", res);
7012     return res;
7013   }
7014 no_ports:
7015   {
7016     GST_ERROR ("no more ports available");
7017     return GST_RTSP_ERROR;
7018   }
7019 }
7020
7021 static GstRTSPResult
7022 gst_rtspsrc_prepare_transports (GstRTSPStream * stream, gchar ** transports,
7023     gint orig_rtpport, gint orig_rtcpport)
7024 {
7025   GstRTSPSrc *src;
7026   gint nr_udp, nr_int;
7027   gchar *next, *p;
7028   gint rtpport = 0, rtcpport = 0;
7029   GString *str;
7030
7031   src = stream->parent;
7032
7033   /* find number of placeholders first */
7034   if (strstr (*transports, "%%i2"))
7035     nr_int = 2;
7036   else if (strstr (*transports, "%%i1"))
7037     nr_int = 1;
7038   else
7039     nr_int = 0;
7040
7041   if (strstr (*transports, "%%u2"))
7042     nr_udp = 2;
7043   else if (strstr (*transports, "%%u1"))
7044     nr_udp = 1;
7045   else
7046     nr_udp = 0;
7047
7048   if (nr_udp == 0 && nr_int == 0)
7049     goto done;
7050
7051   if (nr_udp > 0) {
7052     if (!orig_rtpport || !orig_rtcpport) {
7053       if (!gst_rtspsrc_alloc_udp_ports (stream, &rtpport, &rtcpport))
7054         goto failed;
7055     } else {
7056       rtpport = orig_rtpport;
7057       rtcpport = orig_rtcpport;
7058     }
7059   }
7060
7061   str = g_string_new ("");
7062   p = *transports;
7063   while ((next = strstr (p, "%%"))) {
7064     g_string_append_len (str, p, next - p);
7065     if (next[2] == 'u') {
7066       if (next[3] == '1')
7067         g_string_append_printf (str, "%d", rtpport);
7068       else if (next[3] == '2')
7069         g_string_append_printf (str, "%d", rtcpport);
7070     }
7071     if (next[2] == 'i') {
7072       if (next[3] == '1')
7073         g_string_append_printf (str, "%d", src->free_channel);
7074       else if (next[3] == '2')
7075         g_string_append_printf (str, "%d", src->free_channel + 1);
7076
7077     }
7078
7079     p = next + 4;
7080   }
7081   if (src->version >= GST_RTSP_VERSION_2_0)
7082     src->free_channel += 2;
7083
7084   /* append final part */
7085   g_string_append (str, p);
7086
7087   g_free (*transports);
7088   *transports = g_string_free (str, FALSE);
7089
7090 done:
7091   return GST_RTSP_OK;
7092
7093   /* ERRORS */
7094 failed:
7095   {
7096     GST_ERROR ("failed to allocate udp ports");
7097     return GST_RTSP_ERROR;
7098   }
7099 }
7100
7101 static GstCaps *
7102 signal_get_srtcp_params (GstRTSPSrc * src, GstRTSPStream * stream)
7103 {
7104   GstCaps *caps = NULL;
7105
7106   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_REQUEST_RTCP_KEY], 0,
7107       stream->id, &caps);
7108
7109   if (caps != NULL)
7110     GST_DEBUG_OBJECT (src, "SRTP parameters received");
7111
7112   return caps;
7113 }
7114
7115 static GstCaps *
7116 default_srtcp_params (void)
7117 {
7118   guint i;
7119   GstCaps *caps;
7120   GstBuffer *buf;
7121   guint8 *key_data;
7122 #define KEY_SIZE 30
7123   guint data_size = GST_ROUND_UP_4 (KEY_SIZE);
7124
7125   /* create a random key */
7126   key_data = g_malloc (data_size);
7127   for (i = 0; i < data_size; i += 4)
7128     GST_WRITE_UINT32_BE (key_data + i, g_random_int ());
7129
7130   buf = gst_buffer_new_wrapped (key_data, KEY_SIZE);
7131
7132   caps = gst_caps_new_simple ("application/x-srtcp",
7133       "srtp-key", GST_TYPE_BUFFER, buf,
7134       "srtp-cipher", G_TYPE_STRING, "aes-128-icm",
7135       "srtp-auth", G_TYPE_STRING, "hmac-sha1-80",
7136       "srtcp-cipher", G_TYPE_STRING, "aes-128-icm",
7137       "srtcp-auth", G_TYPE_STRING, "hmac-sha1-80", NULL);
7138
7139   gst_buffer_unref (buf);
7140
7141   return caps;
7142 }
7143
7144 static gchar *
7145 gst_rtspsrc_stream_make_keymgmt (GstRTSPSrc * src, GstRTSPStream * stream)
7146 {
7147   gchar *base64, *result = NULL;
7148   GstMIKEYMessage *mikey_msg;
7149
7150   stream->srtcpparams = signal_get_srtcp_params (src, stream);
7151   if (stream->srtcpparams == NULL)
7152     stream->srtcpparams = default_srtcp_params ();
7153
7154   mikey_msg = gst_mikey_message_new_from_caps (stream->srtcpparams);
7155   if (mikey_msg) {
7156     /* add policy '0' for our SSRC */
7157     gst_mikey_message_add_cs_srtp (mikey_msg, 0, stream->send_ssrc, 0);
7158
7159     base64 = gst_mikey_message_base64_encode (mikey_msg);
7160     gst_mikey_message_unref (mikey_msg);
7161
7162     if (base64) {
7163       result = gst_sdp_make_keymgmt (stream->conninfo.location, base64);
7164       g_free (base64);
7165     }
7166   }
7167
7168   return result;
7169 }
7170
7171 static GstRTSPResult
7172 gst_rtsp_src_setup_stream_from_response (GstRTSPSrc * src,
7173     GstRTSPStream * stream, GstRTSPMessage * response,
7174     GstRTSPLowerTrans * protocols, gint retry, gint * rtpport, gint * rtcpport)
7175 {
7176   gchar *resptrans = NULL;
7177   GstRTSPTransport transport = { 0 };
7178
7179   gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT, &resptrans, 0);
7180   if (!resptrans) {
7181     gst_rtspsrc_stream_free_udp (stream);
7182     goto no_transport;
7183   }
7184
7185   /* parse transport, go to next stream on parse error */
7186   if (gst_rtsp_transport_parse (resptrans, &transport) != GST_RTSP_OK) {
7187     GST_WARNING_OBJECT (src, "failed to parse transport %s", resptrans);
7188     return GST_RTSP_ELAST;
7189   }
7190
7191   /* update allowed transports for other streams. once the transport of
7192    * one stream has been determined, we make sure that all other streams
7193    * are configured in the same way */
7194   switch (transport.lower_transport) {
7195     case GST_RTSP_LOWER_TRANS_TCP:
7196       GST_DEBUG_OBJECT (src, "stream %p as TCP interleaved", stream);
7197       if (protocols)
7198         *protocols = GST_RTSP_LOWER_TRANS_TCP;
7199       src->interleaved = TRUE;
7200       if (src->version < GST_RTSP_VERSION_2_0) {
7201         /* update free channels */
7202         src->free_channel = MAX (transport.interleaved.min, src->free_channel);
7203         src->free_channel = MAX (transport.interleaved.max, src->free_channel);
7204         src->free_channel++;
7205       }
7206       break;
7207     case GST_RTSP_LOWER_TRANS_UDP_MCAST:
7208       /* only allow multicast for other streams */
7209       GST_DEBUG_OBJECT (src, "stream %p as UDP multicast", stream);
7210       if (protocols)
7211         *protocols = GST_RTSP_LOWER_TRANS_UDP_MCAST;
7212       /* if the server selected our ports, increment our counters so that
7213        * we select a new port later */
7214       if (src->next_port_num == transport.port.min &&
7215           src->next_port_num + 1 == transport.port.max) {
7216         src->next_port_num += 2;
7217       }
7218       break;
7219     case GST_RTSP_LOWER_TRANS_UDP:
7220       /* only allow unicast for other streams */
7221       GST_DEBUG_OBJECT (src, "stream %p as UDP unicast", stream);
7222       if (protocols)
7223         *protocols = GST_RTSP_LOWER_TRANS_UDP;
7224       break;
7225     default:
7226       GST_DEBUG_OBJECT (src, "stream %p unknown transport %d", stream,
7227           transport.lower_transport);
7228       break;
7229   }
7230
7231   if (!src->interleaved || !retry) {
7232     /* now configure the stream with the selected transport */
7233     if (!gst_rtspsrc_stream_configure_transport (stream, &transport)) {
7234       GST_DEBUG_OBJECT (src,
7235           "could not configure stream %p transport, skipping stream", stream);
7236       goto done;
7237     } else if (stream->udpsrc[0] && stream->udpsrc[1] && rtpport && rtcpport) {
7238       /* retain the first allocated UDP port pair */
7239       g_object_get (G_OBJECT (stream->udpsrc[0]), "port", rtpport, NULL);
7240       g_object_get (G_OBJECT (stream->udpsrc[1]), "port", rtcpport, NULL);
7241     }
7242   }
7243   /* we need to activate at least one stream when we detect activity */
7244   src->need_activate = TRUE;
7245
7246   /* stream is setup now */
7247   stream->setup = TRUE;
7248   stream->waiting_setup_response = FALSE;
7249
7250   if (src->version >= GST_RTSP_VERSION_2_0) {
7251     gchar *prop, *media_properties;
7252     gchar **props;
7253     gint i;
7254
7255     if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_MEDIA_PROPERTIES,
7256             &media_properties, 0) != GST_RTSP_OK) {
7257       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
7258           ("Error: No MEDIA_PROPERTY header in a SETUP request in RTSP 2.0"
7259               " - this header is mandatory."));
7260
7261       gst_rtsp_message_unset (response);
7262       return GST_RTSP_ERROR;
7263     }
7264
7265     props = g_strsplit (media_properties, ",", -2);
7266     for (i = 0; props[i]; i++) {
7267       prop = props[i];
7268
7269       while (*prop == ' ')
7270         prop++;
7271
7272       if (strstr (prop, "Random-Access")) {
7273         gchar **random_seekable_val = g_strsplit (prop, "=", 2);
7274
7275         if (!random_seekable_val[1])
7276           src->seekable = G_MAXFLOAT;
7277         else
7278           src->seekable = g_ascii_strtod (random_seekable_val[1], NULL);
7279
7280         g_strfreev (random_seekable_val);
7281       } else if (!g_strcmp0 (prop, "No-Seeking")) {
7282         src->seekable = -1.0;
7283       } else if (!g_strcmp0 (prop, "Beginning-Only")) {
7284         src->seekable = 0.0;
7285       }
7286     }
7287
7288     g_strfreev (props);
7289   }
7290
7291 done:
7292   /* clean up our transport struct */
7293   gst_rtsp_transport_init (&transport);
7294   /* clean up used RTSP messages */
7295   gst_rtsp_message_unset (response);
7296
7297   return GST_RTSP_OK;
7298
7299 no_transport:
7300   {
7301     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
7302         ("Server did not select transport."));
7303
7304     gst_rtsp_message_unset (response);
7305     return GST_RTSP_ERROR;
7306   }
7307 }
7308
7309 static GstRTSPResult
7310 gst_rtspsrc_setup_streams_end (GstRTSPSrc * src, gboolean async)
7311 {
7312   GList *tmp;
7313   GstRTSPConnInfo *conninfo;
7314
7315   g_assert (src->version >= GST_RTSP_VERSION_2_0);
7316
7317   conninfo = &src->conninfo;
7318   for (tmp = src->streams; tmp; tmp = tmp->next) {
7319     GstRTSPStream *stream = (GstRTSPStream *) tmp->data;
7320     GstRTSPMessage response = { 0, };
7321
7322     if (!stream->waiting_setup_response)
7323       continue;
7324
7325     if (!src->conninfo.connection)
7326       conninfo = &((GstRTSPStream *) tmp->data)->conninfo;
7327
7328     gst_rtsp_src_receive_response (src, conninfo, &response, NULL);
7329
7330     gst_rtsp_src_setup_stream_from_response (src, stream,
7331         &response, NULL, 0, NULL, NULL);
7332   }
7333
7334   return GST_RTSP_OK;
7335 }
7336
7337 /* Perform the SETUP request for all the streams.
7338  *
7339  * We ask the server for a specific transport, which initially includes all the
7340  * ones we can support (UDP/TCP/MULTICAST). For the UDP transport we allocate
7341  * two local UDP ports that we send to the server.
7342  *
7343  * Once the server replied with a transport, we configure the other streams
7344  * with the same transport.
7345  *
7346  * In case setup request are not pipelined, this function will also configure the
7347  * stream for the selected transport, * which basically means creating the pipeline.
7348  * Otherwise, the first stream is setup right away from the reply and a
7349  * CMD_FINALIZE_SETUP command is set for the stream pipelines to happen on the
7350  * remaining streams from the RTSP thread.
7351  */
7352 static GstRTSPResult
7353 gst_rtspsrc_setup_streams_start (GstRTSPSrc * src, gboolean async)
7354 {
7355   GList *walk;
7356   GstRTSPResult res = GST_RTSP_ERROR;
7357   GstRTSPMessage request = { 0 };
7358   GstRTSPMessage response = { 0 };
7359   GstRTSPStream *stream = NULL;
7360   GstRTSPLowerTrans protocols;
7361   GstRTSPStatusCode code;
7362   gboolean unsupported_real = FALSE;
7363   gint rtpport, rtcpport;
7364   GstRTSPUrl *url;
7365   gchar *hval;
7366   gchar *pipelined_request_id = NULL;
7367
7368   if (src->conninfo.connection) {
7369     url = gst_rtsp_connection_get_url (src->conninfo.connection);
7370     /* we initially allow all configured lower transports. based on the URL
7371      * transports and the replies from the server we narrow them down. */
7372     protocols = url->transports & src->cur_protocols;
7373   } else {
7374     url = NULL;
7375     protocols = src->cur_protocols;
7376   }
7377
7378   if (protocols == 0)
7379     goto no_protocols;
7380
7381   /* reset some state */
7382   src->free_channel = 0;
7383   src->interleaved = FALSE;
7384   src->need_activate = FALSE;
7385   /* keep track of next port number, 0 is random */
7386   src->next_port_num = src->client_port_range.min;
7387   rtpport = rtcpport = 0;
7388
7389   if (G_UNLIKELY (src->streams == NULL))
7390     goto no_streams;
7391
7392   for (walk = src->streams; walk; walk = g_list_next (walk)) {
7393     GstRTSPConnInfo *conninfo;
7394     gchar *transports;
7395     gint retry = 0;
7396     guint mask = 0;
7397     gboolean selected;
7398     GstCaps *caps;
7399
7400     stream = (GstRTSPStream *) walk->data;
7401
7402     caps = stream_get_caps_for_pt (stream, stream->default_pt);
7403     if (caps == NULL) {
7404       GST_WARNING_OBJECT (src, "skipping stream %p, no caps", stream);
7405       continue;
7406     }
7407
7408     if (stream->skipped) {
7409       GST_DEBUG_OBJECT (src, "skipping stream %p", stream);
7410       continue;
7411     }
7412
7413     /* see if we need to configure this stream */
7414     if (!gst_rtsp_ext_list_configure_stream (src->extensions, caps)) {
7415       GST_DEBUG_OBJECT (src, "skipping stream %p, disabled by extension",
7416           stream);
7417       continue;
7418     }
7419
7420     g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_SELECT_STREAM], 0,
7421         stream->id, caps, &selected);
7422     if (!selected) {
7423       GST_DEBUG_OBJECT (src, "skipping stream %p, disabled by signal", stream);
7424       continue;
7425     }
7426
7427     /* merge/overwrite global caps */
7428     if (caps) {
7429       guint j, num;
7430       GstStructure *s;
7431
7432       s = gst_caps_get_structure (caps, 0);
7433
7434       num = gst_structure_n_fields (src->props);
7435       for (j = 0; j < num; j++) {
7436         const gchar *name;
7437         const GValue *val;
7438
7439         name = gst_structure_nth_field_name (src->props, j);
7440         val = gst_structure_get_value (src->props, name);
7441         gst_structure_set_value (s, name, val);
7442
7443         GST_DEBUG_OBJECT (src, "copied %s", name);
7444       }
7445     }
7446
7447     /* skip setup if we have no URL for it */
7448     if (stream->conninfo.location == NULL) {
7449       GST_WARNING_OBJECT (src, "skipping stream %p, no setup", stream);
7450       continue;
7451     }
7452
7453     if (src->conninfo.connection == NULL) {
7454       if (!gst_rtsp_conninfo_connect (src, &stream->conninfo, async)) {
7455         GST_WARNING_OBJECT (src, "skipping stream %p, failed to connect",
7456             stream);
7457         continue;
7458       }
7459       conninfo = &stream->conninfo;
7460     } else {
7461       conninfo = &src->conninfo;
7462     }
7463     GST_DEBUG_OBJECT (src, "doing setup of stream %p with %s", stream,
7464         stream->conninfo.location);
7465
7466     /* if we have a multicast connection, only suggest multicast from now on */
7467     if (stream->is_multicast)
7468       protocols &= GST_RTSP_LOWER_TRANS_UDP_MCAST;
7469
7470   next_protocol:
7471     /* first selectable protocol */
7472     while (protocol_masks[mask] && !(protocols & protocol_masks[mask]))
7473       mask++;
7474     if (!protocol_masks[mask])
7475       goto no_protocols;
7476
7477   retry:
7478     GST_DEBUG_OBJECT (src, "protocols = 0x%x, protocol mask = 0x%x", protocols,
7479         protocol_masks[mask]);
7480     /* create a string with first transport in line */
7481     transports = NULL;
7482     res = gst_rtspsrc_create_transports_string (src,
7483         protocols & protocol_masks[mask], stream->profile, &transports);
7484     if (res < 0 || transports == NULL)
7485       goto setup_transport_failed;
7486
7487     if (strlen (transports) == 0) {
7488       g_free (transports);
7489       GST_DEBUG_OBJECT (src, "no transports found");
7490       mask++;
7491       goto next_protocol;
7492     }
7493
7494     GST_DEBUG_OBJECT (src, "replace ports in %s", GST_STR_NULL (transports));
7495
7496     /* replace placeholders with real values, this function will optionally
7497      * allocate UDP ports and other info needed to execute the setup request */
7498     res = gst_rtspsrc_prepare_transports (stream, &transports,
7499         retry > 0 ? rtpport : 0, retry > 0 ? rtcpport : 0);
7500     if (res < 0) {
7501       g_free (transports);
7502       goto setup_transport_failed;
7503     }
7504
7505     GST_DEBUG_OBJECT (src, "transport is now %s", GST_STR_NULL (transports));
7506     /* create SETUP request */
7507     res =
7508         gst_rtspsrc_init_request (src, &request, GST_RTSP_SETUP,
7509         stream->conninfo.location);
7510     if (res < 0) {
7511       g_free (transports);
7512       goto create_request_failed;
7513     }
7514
7515     if (src->version >= GST_RTSP_VERSION_2_0) {
7516       if (!pipelined_request_id)
7517         pipelined_request_id = g_strdup_printf ("%d",
7518             g_random_int_range (0, G_MAXINT32));
7519
7520       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_PIPELINED_REQUESTS,
7521           pipelined_request_id);
7522       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_ACCEPT_RANGES,
7523           "npt, clock, smpte, clock");
7524     }
7525
7526     /* select transport */
7527     gst_rtsp_message_take_header (&request, GST_RTSP_HDR_TRANSPORT, transports);
7528
7529     if (stream->is_backchannel && src->backchannel == BACKCHANNEL_ONVIF)
7530       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
7531           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
7532
7533     /* set up keys */
7534     if (stream->profile == GST_RTSP_PROFILE_SAVP ||
7535         stream->profile == GST_RTSP_PROFILE_SAVPF) {
7536       hval = gst_rtspsrc_stream_make_keymgmt (src, stream);
7537       gst_rtsp_message_take_header (&request, GST_RTSP_HDR_KEYMGMT, hval);
7538     }
7539
7540     /* if the user wants a non default RTP packet size we add the blocksize
7541      * parameter */
7542     if (src->rtp_blocksize > 0) {
7543       hval = g_strdup_printf ("%d", src->rtp_blocksize);
7544       gst_rtsp_message_take_header (&request, GST_RTSP_HDR_BLOCKSIZE, hval);
7545     }
7546
7547     if (async)
7548       GST_ELEMENT_PROGRESS (src, CONTINUE, "request", ("SETUP stream %d",
7549               stream->id));
7550
7551     /* handle the code ourselves */
7552     res =
7553         gst_rtspsrc_send (src, conninfo, &request,
7554         pipelined_request_id ? NULL : &response, &code, NULL);
7555     if (res < 0)
7556       goto send_error;
7557
7558     switch (code) {
7559       case GST_RTSP_STS_OK:
7560         break;
7561       case GST_RTSP_STS_UNSUPPORTED_TRANSPORT:
7562         gst_rtsp_message_unset (&request);
7563         gst_rtsp_message_unset (&response);
7564         /* cleanup of leftover transport */
7565         gst_rtspsrc_stream_free_udp (stream);
7566         /* MS WMServer RTSP MUST use same UDP pair in all SETUP requests;
7567          * we might be in this case */
7568         if (stream->container && rtpport && rtcpport && !retry) {
7569           GST_DEBUG_OBJECT (src, "retrying with original port pair %u-%u",
7570               rtpport, rtcpport);
7571           retry++;
7572           goto retry;
7573         }
7574         /* this transport did not go down well, but we may have others to try
7575          * that we did not send yet, try those and only give up then
7576          * but not without checking for lost cause/extension so we can
7577          * post a nicer/more useful error message later */
7578         if (!unsupported_real)
7579           unsupported_real = stream->is_real;
7580         /* select next available protocol, give up on this stream if none */
7581         mask++;
7582         while (protocol_masks[mask] && !(protocols & protocol_masks[mask]))
7583           mask++;
7584         if (!protocol_masks[mask] || unsupported_real)
7585           continue;
7586         else
7587           goto retry;
7588       default:
7589         /* cleanup of leftover transport and move to the next stream */
7590         gst_rtspsrc_stream_free_udp (stream);
7591         goto response_error;
7592     }
7593
7594
7595     if (!pipelined_request_id) {
7596       /* parse response transport */
7597       res = gst_rtsp_src_setup_stream_from_response (src, stream,
7598           &response, &protocols, retry, &rtpport, &rtcpport);
7599       switch (res) {
7600         case GST_RTSP_ERROR:
7601           goto cleanup_error;
7602         case GST_RTSP_ELAST:
7603           goto retry;
7604         default:
7605           break;
7606       }
7607     } else {
7608       stream->waiting_setup_response = TRUE;
7609       /* we need to activate at least one stream when we detect activity */
7610       src->need_activate = TRUE;
7611     }
7612
7613     {
7614       GList *skip = walk;
7615
7616       while (TRUE) {
7617         GstRTSPStream *sskip;
7618
7619         skip = g_list_next (skip);
7620         if (skip == NULL)
7621           break;
7622
7623         sskip = (GstRTSPStream *) skip->data;
7624
7625         /* skip all streams with the same control url */
7626         if (g_str_equal (stream->conninfo.location, sskip->conninfo.location)) {
7627           GST_DEBUG_OBJECT (src, "found stream %p with same control %s",
7628               sskip, sskip->conninfo.location);
7629           sskip->skipped = TRUE;
7630         }
7631       }
7632     }
7633     gst_rtsp_message_unset (&request);
7634   }
7635
7636   if (pipelined_request_id) {
7637     gst_rtspsrc_setup_streams_end (src, TRUE);
7638   }
7639
7640   /* store the transport protocol that was configured */
7641   src->cur_protocols = protocols;
7642
7643   gst_rtsp_ext_list_stream_select (src->extensions, url);
7644
7645   if (pipelined_request_id)
7646     g_free (pipelined_request_id);
7647
7648   /* if there is nothing to activate, error out */
7649   if (!src->need_activate)
7650     goto nothing_to_activate;
7651
7652   return res;
7653
7654   /* ERRORS */
7655 no_protocols:
7656   {
7657 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7658     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_INVALID_PROTOCOL,
7659         "Could not connect to server, no protocols left");
7660 #else
7661     /* no transport possible, post an error and stop */
7662     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
7663         ("Could not connect to server, no protocols left"));
7664 #endif
7665     return GST_RTSP_ERROR;
7666   }
7667 no_streams:
7668   {
7669 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7670     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONTENT_NOT_FOUND,
7671         "SDP contains no streams");
7672 #else
7673     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
7674         ("SDP contains no streams"));
7675 #endif
7676     return GST_RTSP_ERROR;
7677   }
7678 create_request_failed:
7679   {
7680     gchar *str = gst_rtsp_strresult (res);
7681
7682 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7683     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
7684         "Could not create request.");
7685 #else
7686     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
7687         ("Could not create request. (%s)", str));
7688 #endif
7689     g_free (str);
7690     goto cleanup_error;
7691   }
7692 setup_transport_failed:
7693   {
7694 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7695     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
7696         "Could not setup transport.");
7697 #else
7698     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
7699         ("Could not setup transport."));
7700 #endif
7701     res = GST_RTSP_ERROR;
7702     goto cleanup_error;
7703   }
7704 response_error:
7705   {
7706 #ifndef TIZEN_FEATURE_RTSP_MODIFICATION
7707     const gchar *str = gst_rtsp_status_as_text (code);
7708 #endif
7709
7710 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7711     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_UNEXPECTED_MSG,
7712         "Error from Server .");
7713 #else
7714     GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
7715         ("Error (%d): %s", code, GST_STR_NULL (str)));
7716 #endif
7717     res = GST_RTSP_ERROR;
7718     goto cleanup_error;
7719   }
7720 send_error:
7721   {
7722     gchar *str = gst_rtsp_strresult (res);
7723
7724     if (res != GST_RTSP_EINTR) {
7725 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7726       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
7727           "Could not send message.");
7728 #else
7729       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
7730           ("Could not send message. (%s)", str));
7731 #endif
7732     } else {
7733       GST_WARNING_OBJECT (src, "send interrupted");
7734     }
7735     g_free (str);
7736     goto cleanup_error;
7737   }
7738 nothing_to_activate:
7739   {
7740     /* none of the available error codes is really right .. */
7741     if (unsupported_real) {
7742 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7743       gst_rtspsrc_post_error_message (src,
7744           GST_RTSPSRC_ERROR_UNSUPPORTED_MEDIA_TYPE,
7745           "No supported stream was found. You might need to install a GStreamer RTSP extension plugin for Real media streams.");
7746 #else
7747       GST_ELEMENT_ERROR (src, STREAM, CODEC_NOT_FOUND,
7748           (_("No supported stream was found. You might need to install a "
7749                   "GStreamer RTSP extension plugin for Real media streams.")),
7750           (NULL));
7751 #endif
7752     } else {
7753 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7754       gst_rtspsrc_post_error_message (src,
7755           GST_RTSPSRC_ERROR_UNSUPPORTED_MEDIA_TYPE,
7756           "No supported stream was found. You might need to allow more transport protocols or may otherwise be missing the right GStreamer RTSP extension plugin.");
7757 #else
7758       GST_ELEMENT_ERROR (src, STREAM, CODEC_NOT_FOUND,
7759           (_("No supported stream was found. You might need to allow "
7760                   "more transport protocols or may otherwise be missing "
7761                   "the right GStreamer RTSP extension plugin.")), (NULL));
7762 #endif
7763     }
7764     return GST_RTSP_ERROR;
7765   }
7766 cleanup_error:
7767   {
7768     if (pipelined_request_id)
7769       g_free (pipelined_request_id);
7770     gst_rtsp_message_unset (&request);
7771     gst_rtsp_message_unset (&response);
7772     return res;
7773   }
7774 }
7775
7776 static gboolean
7777 gst_rtspsrc_parse_range (GstRTSPSrc * src, const gchar * range,
7778     GstSegment * segment)
7779 {
7780   gint64 seconds;
7781   GstRTSPTimeRange *therange;
7782
7783   if (src->range)
7784     gst_rtsp_range_free (src->range);
7785
7786   if (gst_rtsp_range_parse (range, &therange) == GST_RTSP_OK) {
7787     GST_DEBUG_OBJECT (src, "parsed range %s", range);
7788     src->range = therange;
7789   } else {
7790     GST_DEBUG_OBJECT (src, "failed to parse range %s", range);
7791     src->range = NULL;
7792     gst_segment_init (segment, GST_FORMAT_TIME);
7793     return FALSE;
7794   }
7795
7796   GST_DEBUG_OBJECT (src, "range: type %d, min %f - type %d,  max %f ",
7797       therange->min.type, therange->min.seconds, therange->max.type,
7798       therange->max.seconds);
7799
7800   if (therange->min.type == GST_RTSP_TIME_NOW)
7801     seconds = 0;
7802   else if (therange->min.type == GST_RTSP_TIME_END)
7803     seconds = 0;
7804   else
7805     seconds = therange->min.seconds * GST_SECOND;
7806
7807   GST_DEBUG_OBJECT (src, "range: min %" GST_TIME_FORMAT,
7808       GST_TIME_ARGS (seconds));
7809
7810   /* we need to start playback without clipping from the position reported by
7811    * the server */
7812   segment->start = seconds;
7813 #ifndef TIZEN_FEATURE_RTSP_MODIFICATION
7814 /*
7815 The range-min points to the start of the segment , not the current position.
7816 After getting the current position from MSL during normal pause/resume or during seek , we should not
7817 update the segment->position again with the rtp header npt timestamp.
7818 */
7819   segment->position = seconds;
7820 #endif
7821
7822   if (therange->max.type == GST_RTSP_TIME_NOW)
7823 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7824     seconds = 0;
7825 #else
7826     seconds = -1;
7827 #endif
7828   else if (therange->max.type == GST_RTSP_TIME_END)
7829     seconds = -1;
7830   else
7831     seconds = therange->max.seconds * GST_SECOND;
7832
7833   GST_DEBUG_OBJECT (src, "range: max %" GST_TIME_FORMAT,
7834       GST_TIME_ARGS (seconds));
7835
7836   /* live (WMS) server might send overflowed large max as its idea of infinity,
7837    * compensate to prevent problems later on */
7838   if (seconds != -1 && seconds < 0) {
7839     seconds = -1;
7840     GST_DEBUG_OBJECT (src, "insane range, set to NONE");
7841   }
7842
7843   /* live (WMS) might send min == max, which is not worth recording */
7844   if (segment->duration == -1 && seconds == segment->start)
7845     seconds = -1;
7846
7847   /* don't change duration with unknown value, we might have a valid value
7848    * there that we want to keep. */
7849   if (seconds != -1)
7850     segment->duration = seconds;
7851
7852   return TRUE;
7853 }
7854
7855 /* Parse clock profived by the server with following syntax:
7856  *
7857  * "GstNetTimeProvider <wrapped-clock> <server-IP:port> <clock-time>"
7858  */
7859 static gboolean
7860 gst_rtspsrc_parse_gst_clock (GstRTSPSrc * src, const gchar * gstclock)
7861 {
7862   gboolean res = FALSE;
7863
7864   if (g_str_has_prefix (gstclock, "GstNetTimeProvider ")) {
7865     gchar **fields = NULL, **parts = NULL;
7866     gchar *remote_ip, *str;
7867     gint port;
7868     GstClockTime base_time;
7869     GstClock *netclock;
7870
7871     fields = g_strsplit (gstclock, " ", 0);
7872
7873     /* wrapped clock, not very interesting for now */
7874     if (fields[1] == NULL)
7875       goto cleanup;
7876
7877     /* remote IP address and port */
7878     if ((str = fields[2]) == NULL)
7879       goto cleanup;
7880
7881     parts = g_strsplit (str, ":", 0);
7882
7883     if ((remote_ip = parts[0]) == NULL)
7884       goto cleanup;
7885
7886     if ((str = parts[1]) == NULL)
7887       goto cleanup;
7888
7889     port = atoi (str);
7890     if (port == 0)
7891       goto cleanup;
7892
7893     /* base-time */
7894     if ((str = fields[3]) == NULL)
7895       goto cleanup;
7896
7897     base_time = g_ascii_strtoull (str, NULL, 10);
7898
7899     netclock =
7900         gst_net_client_clock_new ((gchar *) "GstRTSPClock", remote_ip, port,
7901         base_time);
7902
7903     if (src->provided_clock)
7904       gst_object_unref (src->provided_clock);
7905     src->provided_clock = netclock;
7906
7907     gst_element_post_message (GST_ELEMENT_CAST (src),
7908         gst_message_new_clock_provide (GST_OBJECT_CAST (src),
7909             src->provided_clock, TRUE));
7910
7911     res = TRUE;
7912   cleanup:
7913     g_strfreev (fields);
7914     g_strfreev (parts);
7915   }
7916   return res;
7917 }
7918
7919 /* must be called with the RTSP state lock */
7920 static GstRTSPResult
7921 gst_rtspsrc_open_from_sdp (GstRTSPSrc * src, GstSDPMessage * sdp,
7922     gboolean async)
7923 {
7924   GstRTSPResult res;
7925   gint i, n_streams;
7926
7927   /* prepare global stream caps properties */
7928   if (src->props)
7929     gst_structure_remove_all_fields (src->props);
7930   else
7931     src->props = gst_structure_new_empty ("RTSPProperties");
7932
7933   DEBUG_SDP (src, sdp);
7934
7935   gst_rtsp_ext_list_parse_sdp (src->extensions, sdp, src->props);
7936
7937   /* let the app inspect and change the SDP */
7938   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_ON_SDP], 0, sdp);
7939
7940   gst_segment_init (&src->segment, GST_FORMAT_TIME);
7941
7942   /* parse range for duration reporting. */
7943   {
7944     const gchar *range;
7945
7946     for (i = 0;; i++) {
7947       range = gst_sdp_message_get_attribute_val_n (sdp, "range", i);
7948       if (range == NULL)
7949         break;
7950
7951       /* keep track of the range and configure it in the segment */
7952       if (gst_rtspsrc_parse_range (src, range, &src->segment))
7953         break;
7954     }
7955   }
7956   /* parse clock information. This is GStreamer specific, a server can tell the
7957    * client what clock it is using and wrap that in a network clock. The
7958    * advantage of that is that we can slave to it. */
7959   {
7960     const gchar *gstclock;
7961
7962     for (i = 0;; i++) {
7963       gstclock = gst_sdp_message_get_attribute_val_n (sdp, "x-gst-clock", i);
7964       if (gstclock == NULL)
7965         break;
7966
7967       /* parse the clock and expose it in the provide_clock method */
7968       if (gst_rtspsrc_parse_gst_clock (src, gstclock))
7969         break;
7970     }
7971   }
7972   /* try to find a global control attribute. Note that a '*' means that we should
7973    * do aggregate control with the current url (so we don't do anything and
7974    * leave the current connection as is) */
7975   {
7976     const gchar *control;
7977
7978     for (i = 0;; i++) {
7979       control = gst_sdp_message_get_attribute_val_n (sdp, "control", i);
7980       if (control == NULL)
7981         break;
7982
7983       /* only take fully qualified urls */
7984       if (g_str_has_prefix (control, "rtsp://"))
7985         break;
7986     }
7987     if (control) {
7988       g_free (src->conninfo.location);
7989       src->conninfo.location = g_strdup (control);
7990       /* make a connection for this, if there was a connection already, nothing
7991        * happens. */
7992       if (gst_rtsp_conninfo_connect (src, &src->conninfo, async) < 0) {
7993         GST_ERROR_OBJECT (src, "could not connect");
7994       }
7995     }
7996     /* we need to keep the control url separate from the connection url because
7997      * the rules for constructing the media control url need it */
7998     g_free (src->control);
7999     src->control = g_strdup (control);
8000   }
8001
8002 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8003   src->is_audio_codec_supported = FALSE;
8004   src->is_video_codec_supported = FALSE;
8005 #endif
8006
8007   /* create streams */
8008   n_streams = gst_sdp_message_medias_len (sdp);
8009   for (i = 0; i < n_streams; i++) {
8010     gst_rtspsrc_create_stream (src, sdp, i, n_streams);
8011   }
8012
8013   src->state = GST_RTSP_STATE_INIT;
8014 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8015   /* Check for the support for the Media codecs */
8016   if ((!src->is_audio_codec_supported) && (!src->is_video_codec_supported)) {
8017     GST_ERROR_OBJECT (src, "UnSupported Media Type !!!! \n");
8018     goto unsupported_file_type;
8019   } else {
8020     GST_DEBUG_OBJECT (src, "Supported Media Type. \n");
8021   }
8022 #endif
8023   /* setup streams */
8024   if ((res = gst_rtspsrc_setup_streams_start (src, async)) < 0)
8025     goto setup_failed;
8026
8027   /* reset our state */
8028   src->need_range = TRUE;
8029   src->skip = FALSE;
8030
8031   src->state = GST_RTSP_STATE_READY;
8032
8033   return res;
8034
8035   /* ERRORS */
8036 setup_failed:
8037   {
8038     GST_ERROR_OBJECT (src, "setup failed");
8039     gst_rtspsrc_cleanup (src);
8040     return res;
8041   }
8042 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8043 unsupported_file_type:
8044   {
8045     gst_rtspsrc_post_error_message (src,
8046         GST_RTSPSRC_ERROR_UNSUPPORTED_MEDIA_TYPE,
8047         "No supported stream was found");
8048     res = GST_RTSP_ERROR;
8049     gst_rtspsrc_cleanup (src);
8050     return res;
8051   }
8052 #endif
8053 }
8054
8055 static GstRTSPResult
8056 gst_rtspsrc_retrieve_sdp (GstRTSPSrc * src, GstSDPMessage ** sdp,
8057     gboolean async)
8058 {
8059   GstRTSPResult res;
8060   GstRTSPMessage request = { 0 };
8061   GstRTSPMessage response = { 0 };
8062   guint8 *data;
8063   guint size;
8064   gchar *respcont = NULL;
8065   GstRTSPVersion versions[] =
8066       { GST_RTSP_VERSION_2_0, GST_RTSP_VERSION_INVALID };
8067
8068   src->version = src->default_version;
8069   if (src->default_version == GST_RTSP_VERSION_2_0) {
8070     versions[0] = GST_RTSP_VERSION_1_0;
8071   }
8072
8073 restart:
8074   src->need_redirect = FALSE;
8075
8076   /* can't continue without a valid url */
8077   if (G_UNLIKELY (src->conninfo.url == NULL)) {
8078     res = GST_RTSP_EINVAL;
8079     goto no_url;
8080   }
8081   src->tried_url_auth = FALSE;
8082
8083   if ((res = gst_rtsp_conninfo_connect (src, &src->conninfo, async)) < 0)
8084     goto connect_failed;
8085
8086   /* create OPTIONS */
8087   GST_DEBUG_OBJECT (src, "create options... (%s)", async ? "async" : "sync");
8088   res =
8089       gst_rtspsrc_init_request (src, &request, GST_RTSP_OPTIONS,
8090       src->conninfo.url_str);
8091   if (res < 0)
8092     goto create_request_failed;
8093
8094   /* send OPTIONS */
8095   request.type_data.request.version = src->version;
8096   GST_DEBUG_OBJECT (src, "send options...");
8097
8098   if (async)
8099     GST_ELEMENT_PROGRESS (src, CONTINUE, "open", ("Retrieving server options"));
8100
8101   if ((res =
8102           gst_rtspsrc_send (src, &src->conninfo, &request, &response,
8103               NULL, versions)) < 0) {
8104     goto send_error;
8105   }
8106
8107   src->version = request.type_data.request.version;
8108   GST_INFO_OBJECT (src, "Now using version: %s",
8109       gst_rtsp_version_as_text (src->version));
8110
8111   /* parse OPTIONS */
8112   if (!gst_rtspsrc_parse_methods (src, &response))
8113     goto methods_error;
8114
8115   /* create DESCRIBE */
8116   GST_DEBUG_OBJECT (src, "create describe...");
8117   res =
8118       gst_rtspsrc_init_request (src, &request, GST_RTSP_DESCRIBE,
8119       src->conninfo.url_str);
8120   if (res < 0)
8121     goto create_request_failed;
8122
8123   /* we only accept SDP for now */
8124   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_ACCEPT,
8125       "application/sdp");
8126
8127   if (src->backchannel == BACKCHANNEL_ONVIF)
8128     gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
8129         BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
8130   /* TODO: Handle the case when backchannel is unsupported and goto restart */
8131
8132   /* send DESCRIBE */
8133   GST_DEBUG_OBJECT (src, "send describe...");
8134
8135   if (async)
8136     GST_ELEMENT_PROGRESS (src, CONTINUE, "open", ("Retrieving media info"));
8137
8138   if ((res =
8139           gst_rtspsrc_send (src, &src->conninfo, &request, &response,
8140               NULL, NULL)) < 0)
8141     goto send_error;
8142
8143   /* we only perform redirect for describe and play, currently */
8144   if (src->need_redirect) {
8145     /* close connection, we don't have to send a TEARDOWN yet, ignore the
8146      * result. */
8147     gst_rtsp_conninfo_close (src, &src->conninfo, TRUE);
8148
8149     gst_rtsp_message_unset (&request);
8150     gst_rtsp_message_unset (&response);
8151
8152     /* and now retry */
8153     goto restart;
8154   }
8155
8156   /* it could be that the DESCRIBE method was not implemented */
8157   if (!(src->methods & GST_RTSP_DESCRIBE))
8158     goto no_describe;
8159
8160   /* check if reply is SDP */
8161   gst_rtsp_message_get_header (&response, GST_RTSP_HDR_CONTENT_TYPE, &respcont,
8162       0);
8163   /* could not be set but since the request returned OK, we assume it
8164    * was SDP, else check it. */
8165   if (respcont) {
8166     const gchar *props = strchr (respcont, ';');
8167
8168     if (props) {
8169       gchar *mimetype = g_strndup (respcont, props - respcont);
8170
8171       mimetype = g_strstrip (mimetype);
8172       if (g_ascii_strcasecmp (mimetype, "application/sdp") != 0) {
8173         g_free (mimetype);
8174         goto wrong_content_type;
8175       }
8176
8177       /* TODO: Check for charset property and do conversions of all messages if
8178        * needed. Some servers actually send that property */
8179
8180       g_free (mimetype);
8181     } else if (g_ascii_strcasecmp (respcont, "application/sdp") != 0) {
8182       goto wrong_content_type;
8183     }
8184   }
8185
8186   /* get message body and parse as SDP */
8187   gst_rtsp_message_get_body (&response, &data, &size);
8188   if (data == NULL || size == 0)
8189     goto no_describe;
8190
8191   GST_DEBUG_OBJECT (src, "parse SDP...");
8192   gst_sdp_message_new (sdp);
8193   gst_sdp_message_parse_buffer (data, size, *sdp);
8194
8195   /* clean up any messages */
8196   gst_rtsp_message_unset (&request);
8197   gst_rtsp_message_unset (&response);
8198
8199   return res;
8200
8201   /* ERRORS */
8202 no_url:
8203   {
8204 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8205     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_INVALID_URL,
8206         "No valid RTSP URL was provided");
8207 #else
8208     GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
8209         ("No valid RTSP URL was provided"));
8210 #endif
8211     goto cleanup_error;
8212   }
8213 connect_failed:
8214   {
8215     gchar *str = gst_rtsp_strresult (res);
8216
8217     if (res != GST_RTSP_EINTR) {
8218 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8219       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
8220           "Failed to connect.");
8221 #else
8222       GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
8223           ("Failed to connect. (%s)", str));
8224 #endif
8225     } else {
8226       GST_WARNING_OBJECT (src, "connect interrupted");
8227     }
8228     g_free (str);
8229     goto cleanup_error;
8230   }
8231 create_request_failed:
8232   {
8233     gchar *str = gst_rtsp_strresult (res);
8234
8235 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8236     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
8237         "Could not create request.");
8238 #else
8239     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
8240         ("Could not create request. (%s)", str));
8241 #endif
8242     g_free (str);
8243     goto cleanup_error;
8244   }
8245 send_error:
8246   {
8247     /* Don't post a message - the rtsp_send method will have
8248      * taken care of it because we passed NULL for the response code */
8249     goto cleanup_error;
8250   }
8251 methods_error:
8252   {
8253     /* error was posted */
8254     res = GST_RTSP_ERROR;
8255     goto cleanup_error;
8256   }
8257 wrong_content_type:
8258   {
8259 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8260     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_OPTION_NOT_SUPPORTED,
8261         "Server does not support SDP. ");
8262 #else
8263     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
8264         ("Server does not support SDP, got %s.", respcont));
8265 #endif
8266     res = GST_RTSP_ERROR;
8267     goto cleanup_error;
8268   }
8269 no_describe:
8270   {
8271 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8272     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_METHOD_NOT_ALLOWED,
8273         "Server can not provide an SDP.");
8274 #else
8275     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
8276         ("Server can not provide an SDP."));
8277 #endif
8278     res = GST_RTSP_ERROR;
8279     goto cleanup_error;
8280   }
8281 cleanup_error:
8282   {
8283     if (src->conninfo.connection) {
8284       GST_DEBUG_OBJECT (src, "free connection");
8285       gst_rtsp_conninfo_close (src, &src->conninfo, TRUE);
8286     }
8287     gst_rtsp_message_unset (&request);
8288     gst_rtsp_message_unset (&response);
8289     return res;
8290   }
8291 }
8292
8293 static GstRTSPResult
8294 gst_rtspsrc_open (GstRTSPSrc * src, gboolean async)
8295 {
8296   GstRTSPResult ret;
8297
8298   src->methods =
8299       GST_RTSP_SETUP | GST_RTSP_PLAY | GST_RTSP_PAUSE | GST_RTSP_TEARDOWN;
8300
8301   if (src->sdp == NULL) {
8302     if ((ret = gst_rtspsrc_retrieve_sdp (src, &src->sdp, async)) < 0)
8303       goto no_sdp;
8304   }
8305
8306   if ((ret = gst_rtspsrc_open_from_sdp (src, src->sdp, async)) < 0)
8307     goto open_failed;
8308
8309 done:
8310   if (async)
8311     gst_rtspsrc_loop_end_cmd (src, CMD_OPEN, ret);
8312
8313   return ret;
8314
8315   /* ERRORS */
8316 no_sdp:
8317   {
8318     GST_WARNING_OBJECT (src, "can't get sdp");
8319     src->open_error = TRUE;
8320     goto done;
8321   }
8322 open_failed:
8323   {
8324     GST_WARNING_OBJECT (src, "can't setup streaming from sdp");
8325     src->open_error = TRUE;
8326     goto done;
8327   }
8328 }
8329
8330 static GstRTSPResult
8331 gst_rtspsrc_close (GstRTSPSrc * src, gboolean async, gboolean only_close)
8332 {
8333   GstRTSPMessage request = { 0 };
8334   GstRTSPMessage response = { 0 };
8335   GstRTSPResult res = GST_RTSP_OK;
8336   GList *walk;
8337   const gchar *control;
8338
8339   GST_DEBUG_OBJECT (src, "TEARDOWN...");
8340
8341   gst_rtspsrc_set_state (src, GST_STATE_READY);
8342
8343   if (src->state < GST_RTSP_STATE_READY) {
8344     GST_DEBUG_OBJECT (src, "not ready, doing cleanup");
8345     goto close;
8346   }
8347
8348   if (only_close)
8349     goto close;
8350
8351   /* construct a control url */
8352   control = get_aggregate_control (src);
8353
8354   if (!(src->methods & (GST_RTSP_PLAY | GST_RTSP_TEARDOWN)))
8355     goto not_supported;
8356
8357   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8358     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8359     const gchar *setup_url;
8360     GstRTSPConnInfo *info;
8361
8362     /* try aggregate control first but do non-aggregate control otherwise */
8363     if (control)
8364       setup_url = control;
8365     else if ((setup_url = stream->conninfo.location) == NULL)
8366       continue;
8367
8368     if (src->conninfo.connection) {
8369       info = &src->conninfo;
8370     } else if (stream->conninfo.connection) {
8371       info = &stream->conninfo;
8372     } else {
8373       continue;
8374     }
8375     if (!info->connected)
8376       goto next;
8377
8378     /* do TEARDOWN */
8379     res =
8380         gst_rtspsrc_init_request (src, &request, GST_RTSP_TEARDOWN, setup_url);
8381     GST_LOG_OBJECT (src, "Teardown on %s", setup_url);
8382     if (res < 0)
8383       goto create_request_failed;
8384
8385     if (stream->is_backchannel && src->backchannel == BACKCHANNEL_ONVIF)
8386       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
8387           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
8388
8389     if (async)
8390       GST_ELEMENT_PROGRESS (src, CONTINUE, "close", ("Closing stream"));
8391
8392     if ((res =
8393             gst_rtspsrc_send (src, info, &request, &response, NULL, NULL)) < 0)
8394       goto send_error;
8395
8396     /* FIXME, parse result? */
8397     gst_rtsp_message_unset (&request);
8398     gst_rtsp_message_unset (&response);
8399
8400   next:
8401     /* early exit when we did aggregate control */
8402     if (control)
8403       break;
8404   }
8405
8406 close:
8407   /* close connections */
8408   GST_DEBUG_OBJECT (src, "closing connection...");
8409   gst_rtsp_conninfo_close (src, &src->conninfo, TRUE);
8410   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8411     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8412     gst_rtsp_conninfo_close (src, &stream->conninfo, TRUE);
8413   }
8414
8415   /* cleanup */
8416   gst_rtspsrc_cleanup (src);
8417
8418   src->state = GST_RTSP_STATE_INVALID;
8419
8420   if (async)
8421     gst_rtspsrc_loop_end_cmd (src, CMD_CLOSE, res);
8422
8423   return res;
8424
8425   /* ERRORS */
8426 create_request_failed:
8427   {
8428     gchar *str = gst_rtsp_strresult (res);
8429
8430 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8431     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
8432         "Could not create request.");
8433 #else
8434     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
8435         ("Could not create request. (%s)", str));
8436 #endif
8437     g_free (str);
8438     goto close;
8439   }
8440 send_error:
8441   {
8442     gchar *str = gst_rtsp_strresult (res);
8443
8444     gst_rtsp_message_unset (&request);
8445     if (res != GST_RTSP_EINTR) {
8446 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8447       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
8448           "Could not send message.");
8449 #else
8450       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
8451           ("Could not send message. (%s)", str));
8452 #endif
8453     } else {
8454       GST_WARNING_OBJECT (src, "TEARDOWN interrupted");
8455     }
8456     g_free (str);
8457     goto close;
8458   }
8459 not_supported:
8460   {
8461     GST_DEBUG_OBJECT (src,
8462         "TEARDOWN and PLAY not supported, can't do TEARDOWN");
8463     goto close;
8464   }
8465 }
8466
8467 /* RTP-Info is of the format:
8468  *
8469  * url=<URL>;[seq=<seqbase>;rtptime=<timebase>] [, url=...]
8470  *
8471  * rtptime corresponds to the timestamp for the NPT time given in the header
8472  * seqbase corresponds to the next sequence number we received. This number
8473  * indicates the first seqnum after the seek and should be used to discard
8474  * packets that are from before the seek.
8475  */
8476 static gboolean
8477 gst_rtspsrc_parse_rtpinfo (GstRTSPSrc * src, gchar * rtpinfo)
8478 {
8479   gchar **infos;
8480   gint i, j;
8481
8482   GST_DEBUG_OBJECT (src, "parsing RTP-Info %s", rtpinfo);
8483
8484   infos = g_strsplit (rtpinfo, ",", 0);
8485   for (i = 0; infos[i]; i++) {
8486     gchar **fields;
8487     GstRTSPStream *stream;
8488     gint32 seqbase;
8489     gint64 timebase;
8490
8491     GST_DEBUG_OBJECT (src, "parsing info %s", infos[i]);
8492
8493     /* init values, types of seqbase and timebase are bigger than needed so we
8494      * can store -1 as uninitialized values */
8495     stream = NULL;
8496     seqbase = -1;
8497     timebase = -1;
8498
8499     /* parse url, find stream for url.
8500      * parse seq and rtptime. The seq number should be configured in the rtp
8501      * depayloader or session manager to detect gaps. Same for the rtptime, it
8502      * should be used to create an initial time newsegment. */
8503     fields = g_strsplit (infos[i], ";", 0);
8504     for (j = 0; fields[j]; j++) {
8505       GST_DEBUG_OBJECT (src, "parsing field %s", fields[j]);
8506       /* remove leading whitespace */
8507       fields[j] = g_strchug (fields[j]);
8508       if (g_str_has_prefix (fields[j], "url=")) {
8509         /* get the url and the stream */
8510         stream =
8511             find_stream (src, (fields[j] + 4), (gpointer) find_stream_by_setup);
8512       } else if (g_str_has_prefix (fields[j], "seq=")) {
8513         seqbase = atoi (fields[j] + 4);
8514       } else if (g_str_has_prefix (fields[j], "rtptime=")) {
8515         timebase = g_ascii_strtoll (fields[j] + 8, NULL, 10);
8516       }
8517     }
8518     g_strfreev (fields);
8519     /* now we need to store the values for the caps of the stream */
8520     if (stream != NULL) {
8521       GST_DEBUG_OBJECT (src,
8522           "found stream %p, setting: seqbase %d, timebase %" G_GINT64_FORMAT,
8523           stream, seqbase, timebase);
8524
8525       /* we have a stream, configure detected params */
8526       stream->seqbase = seqbase;
8527       stream->timebase = timebase;
8528     }
8529   }
8530   g_strfreev (infos);
8531
8532   return TRUE;
8533 }
8534
8535 static void
8536 gst_rtspsrc_handle_rtcp_interval (GstRTSPSrc * src, gchar * rtcp)
8537 {
8538   guint64 interval;
8539   GList *walk;
8540
8541   interval = strtoul (rtcp, NULL, 10);
8542   GST_DEBUG_OBJECT (src, "rtcp interval: %" G_GUINT64_FORMAT " ms", interval);
8543
8544   if (!interval)
8545     return;
8546
8547   interval *= GST_MSECOND;
8548
8549   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8550     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8551
8552     /* already (optionally) retrieved this when configuring manager */
8553     if (stream->session) {
8554       GObject *rtpsession = stream->session;
8555
8556       GST_DEBUG_OBJECT (src, "configure rtcp interval in session %p",
8557           rtpsession);
8558       g_object_set (rtpsession, "rtcp-min-interval", interval, NULL);
8559     }
8560   }
8561
8562   /* now it happens that (Xenon) server sending this may also provide bogus
8563    * RTCP SR sync data (i.e. with quite some jitter), so never mind those
8564    * and just use RTP-Info to sync */
8565   if (src->manager) {
8566     GObjectClass *klass;
8567
8568     klass = G_OBJECT_GET_CLASS (G_OBJECT (src->manager));
8569     if (g_object_class_find_property (klass, "rtcp-sync")) {
8570       GST_DEBUG_OBJECT (src, "configuring rtp sync method");
8571       g_object_set (src->manager, "rtcp-sync", RTCP_SYNC_RTP, NULL);
8572     }
8573   }
8574 }
8575
8576 static gdouble
8577 gst_rtspsrc_get_float (const gchar * dstr)
8578 {
8579   gchar s[G_ASCII_DTOSTR_BUF_SIZE] = { 0, };
8580
8581   /* canonicalise floating point string so we can handle float strings
8582    * in the form "24.930" or "24,930" irrespective of the current locale */
8583   g_strlcpy (s, dstr, sizeof (s));
8584   g_strdelimit (s, ",", '.');
8585   return g_ascii_strtod (s, NULL);
8586 }
8587
8588 static gchar *
8589 gen_range_header (GstRTSPSrc * src, GstSegment * segment)
8590 {
8591   gchar val_str[G_ASCII_DTOSTR_BUF_SIZE] = { 0, };
8592 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8593   if (src->start_position != 0 && segment->position == 0) {
8594     segment->position = src->start_position;
8595     src->start_position = 0;
8596   }
8597 #endif
8598   if (src->range && src->range->min.type == GST_RTSP_TIME_NOW) {
8599     g_strlcpy (val_str, "now", sizeof (val_str));
8600   } else {
8601     if (segment->position == 0) {
8602       g_strlcpy (val_str, "0", sizeof (val_str));
8603     } else {
8604       g_ascii_dtostr (val_str, sizeof (val_str),
8605           ((gdouble) segment->position) / GST_SECOND);
8606     }
8607   }
8608 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8609   GST_DEBUG_OBJECT (src, "Range Header Added : npt=%s-", val_str);
8610 #endif
8611   return g_strdup_printf ("npt=%s-", val_str);
8612 }
8613
8614 static void
8615 clear_rtp_base (GstRTSPSrc * src, GstRTSPStream * stream)
8616 {
8617   guint i, len;
8618
8619   stream->timebase = -1;
8620   stream->seqbase = -1;
8621
8622   len = stream->ptmap->len;
8623   for (i = 0; i < len; i++) {
8624     PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, i);
8625     GstStructure *s;
8626
8627     if (item->caps == NULL)
8628       continue;
8629
8630     item->caps = gst_caps_make_writable (item->caps);
8631     s = gst_caps_get_structure (item->caps, 0);
8632     gst_structure_remove_fields (s, "clock-base", "seqnum-base", NULL);
8633     if (item->pt == stream->default_pt && stream->udpsrc[0])
8634       g_object_set (stream->udpsrc[0], "caps", item->caps, NULL);
8635   }
8636   stream->need_caps = TRUE;
8637 }
8638
8639 static GstRTSPResult
8640 gst_rtspsrc_ensure_open (GstRTSPSrc * src, gboolean async)
8641 {
8642   GstRTSPResult res = GST_RTSP_OK;
8643
8644   if (src->state < GST_RTSP_STATE_READY) {
8645     res = GST_RTSP_ERROR;
8646     if (src->open_error) {
8647       GST_DEBUG_OBJECT (src, "the stream was in error");
8648       goto done;
8649     }
8650     if (async)
8651       gst_rtspsrc_loop_start_cmd (src, CMD_OPEN);
8652
8653     if ((res = gst_rtspsrc_open (src, async)) < 0) {
8654       GST_DEBUG_OBJECT (src, "failed to open stream");
8655       goto done;
8656     }
8657   }
8658
8659 done:
8660   return res;
8661 }
8662
8663 static GstRTSPResult
8664 gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment, gboolean async,
8665     const gchar * seek_style)
8666 {
8667   GstRTSPMessage request = { 0 };
8668   GstRTSPMessage response = { 0 };
8669   GstRTSPResult res = GST_RTSP_OK;
8670   GList *walk;
8671   gchar *hval;
8672   gint hval_idx;
8673   const gchar *control;
8674
8675   GST_DEBUG_OBJECT (src, "PLAY...");
8676
8677 restart:
8678   if ((res = gst_rtspsrc_ensure_open (src, async)) < 0)
8679     goto open_failed;
8680
8681   if (!(src->methods & GST_RTSP_PLAY))
8682     goto not_supported;
8683
8684   if (src->state == GST_RTSP_STATE_PLAYING)
8685     goto was_playing;
8686
8687   if (!src->conninfo.connection || !src->conninfo.connected)
8688     goto done;
8689
8690   /* send some dummy packets before we activate the receive in the
8691    * udp sources */
8692   gst_rtspsrc_send_dummy_packets (src);
8693
8694   /* require new SR packets */
8695   if (src->manager)
8696     g_signal_emit_by_name (src->manager, "reset-sync", NULL);
8697
8698   /* construct a control url */
8699   control = get_aggregate_control (src);
8700
8701   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8702     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8703     const gchar *setup_url;
8704     GstRTSPConnInfo *conninfo;
8705
8706     /* try aggregate control first but do non-aggregate control otherwise */
8707     if (control)
8708       setup_url = control;
8709     else if ((setup_url = stream->conninfo.location) == NULL)
8710       continue;
8711
8712     if (src->conninfo.connection) {
8713       conninfo = &src->conninfo;
8714     } else if (stream->conninfo.connection) {
8715       conninfo = &stream->conninfo;
8716     } else {
8717       continue;
8718     }
8719
8720     /* do play */
8721     res = gst_rtspsrc_init_request (src, &request, GST_RTSP_PLAY, setup_url);
8722     if (res < 0)
8723       goto create_request_failed;
8724
8725     if (src->need_range && src->seekable >= 0.0) {
8726 #ifndef TIZEN_FEATURE_RTSP_MODIFICATION
8727       hval = gen_range_header (src, segment);
8728
8729       gst_rtsp_message_take_header (&request, GST_RTSP_HDR_RANGE, hval);
8730
8731 #endif
8732       /* store the newsegment event so it can be sent from the streaming thread. */
8733       src->need_segment = TRUE;
8734     }
8735 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8736     else {
8737 /*
8738  Updating position with the MSL current position as gst_rtspsrc_get_position() does not return correct position.
8739 */
8740       GST_DEBUG_OBJECT (src,
8741           " During normal pause-resume , segment->position=%" GST_TIME_FORMAT
8742           ",src->start_position=%" GST_TIME_FORMAT,
8743           GST_TIME_ARGS (segment->position),
8744           GST_TIME_ARGS (src->start_position));
8745       segment->position = src->last_pos;
8746     }
8747
8748 /*
8749  Sending the npt range request for each play request for updating the segment position properly.
8750 */
8751     hval = gen_range_header (src, segment);
8752     gst_rtsp_message_take_header (&request, GST_RTSP_HDR_RANGE, hval);
8753 #endif
8754
8755     if (segment->rate != 1.0) {
8756       gchar hval[G_ASCII_DTOSTR_BUF_SIZE];
8757
8758       g_ascii_dtostr (hval, sizeof (hval), segment->rate);
8759       if (src->skip)
8760         gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SCALE, hval);
8761       else
8762         gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SPEED, hval);
8763     }
8764
8765     if (seek_style)
8766       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SEEK_STYLE,
8767           seek_style);
8768
8769     /* when we have an ONVIF audio backchannel, the PLAY request must have the
8770      * Require: header when doing either aggregate or non-aggregate control */
8771     if (src->backchannel == BACKCHANNEL_ONVIF &&
8772         (control || stream->is_backchannel))
8773       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
8774           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
8775
8776     if (async)
8777       GST_ELEMENT_PROGRESS (src, CONTINUE, "request", ("Sending PLAY request"));
8778
8779     if ((res =
8780             gst_rtspsrc_send (src, conninfo, &request, &response, NULL, NULL))
8781         < 0)
8782       goto send_error;
8783
8784     if (src->need_redirect) {
8785       GST_DEBUG_OBJECT (src,
8786           "redirect: tearing down and restarting with new url");
8787       /* teardown and restart with new url */
8788       gst_rtspsrc_close (src, TRUE, FALSE);
8789       /* reset protocols to force re-negotiation with redirected url */
8790       src->cur_protocols = src->protocols;
8791       gst_rtsp_message_unset (&request);
8792       gst_rtsp_message_unset (&response);
8793       goto restart;
8794     }
8795
8796     /* seek may have silently failed as it is not supported */
8797     if (!(src->methods & GST_RTSP_PLAY)) {
8798       GST_DEBUG_OBJECT (src, "PLAY Range not supported; re-enable PLAY");
8799
8800       if (src->version >= GST_RTSP_VERSION_2_0 && src->seekable >= 0.0) {
8801         GST_WARNING_OBJECT (src, "Server declared stream as seekable but"
8802             " playing with range failed... Ignoring information.");
8803       }
8804       /* obviously it is supported as we made it here */
8805       src->methods |= GST_RTSP_PLAY;
8806       src->seekable = -1.0;
8807       /* but there is nothing to parse in the response,
8808        * so convey we have no idea and not to expect anything particular */
8809       clear_rtp_base (src, stream);
8810       if (control) {
8811         GList *run;
8812
8813         /* need to do for all streams */
8814         for (run = src->streams; run; run = g_list_next (run))
8815           clear_rtp_base (src, (GstRTSPStream *) run->data);
8816       }
8817       /* NOTE the above also disables npt based eos detection */
8818       /* and below forces position to 0,
8819        * which is visible feedback we lost the plot */
8820       segment->start = segment->position = src->last_pos;
8821     }
8822
8823     gst_rtsp_message_unset (&request);
8824
8825     /* parse RTP npt field. This is the current position in the stream (Normal
8826      * Play Time) and should be put in the NEWSEGMENT position field. */
8827     if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_RANGE, &hval,
8828             0) == GST_RTSP_OK)
8829       gst_rtspsrc_parse_range (src, hval, segment);
8830
8831     /* assume 1.0 rate now, overwrite when the SCALE or SPEED headers are present. */
8832     segment->rate = 1.0;
8833
8834     /* parse Speed header. This is the intended playback rate of the stream
8835      * and should be put in the NEWSEGMENT rate field. */
8836     if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_SPEED, &hval,
8837             0) == GST_RTSP_OK) {
8838       segment->rate = gst_rtspsrc_get_float (hval);
8839     } else if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_SCALE,
8840             &hval, 0) == GST_RTSP_OK) {
8841       segment->rate = gst_rtspsrc_get_float (hval);
8842     }
8843
8844     /* parse the RTP-Info header field (if ANY) to get the base seqnum and timestamp
8845      * for the RTP packets. If this is not present, we assume all starts from 0...
8846      * This is info for the RTP session manager that we pass to it in caps. */
8847     hval_idx = 0;
8848     while (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_RTP_INFO,
8849             &hval, hval_idx++) == GST_RTSP_OK)
8850       gst_rtspsrc_parse_rtpinfo (src, hval);
8851
8852     /* some servers indicate RTCP parameters in PLAY response,
8853      * rather than properly in SDP */
8854     if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_RTCP_INTERVAL,
8855             &hval, 0) == GST_RTSP_OK)
8856       gst_rtspsrc_handle_rtcp_interval (src, hval);
8857
8858     gst_rtsp_message_unset (&response);
8859
8860     /* early exit when we did aggregate control */
8861     if (control)
8862       break;
8863   }
8864   /* configure the caps of the streams after we parsed all headers. Only reset
8865    * the manager object when we set a new Range header (we did a seek) */
8866   gst_rtspsrc_configure_caps (src, segment, src->need_range);
8867
8868   /* set to PLAYING after we have configured the caps, otherwise we
8869    * might end up calling request_key (with SRTP) while caps are still
8870    * being configured. */
8871   gst_rtspsrc_set_state (src, GST_STATE_PLAYING);
8872
8873   /* set again when needed */
8874   src->need_range = FALSE;
8875
8876   src->running = TRUE;
8877   src->base_time = -1;
8878   src->state = GST_RTSP_STATE_PLAYING;
8879
8880   /* mark discont */
8881   GST_DEBUG_OBJECT (src, "mark DISCONT, we did a seek to another position");
8882   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8883     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8884     stream->discont = TRUE;
8885   }
8886
8887 done:
8888   if (async)
8889     gst_rtspsrc_loop_end_cmd (src, CMD_PLAY, res);
8890
8891   return res;
8892
8893   /* ERRORS */
8894 open_failed:
8895   {
8896     GST_WARNING_OBJECT (src, "failed to open stream");
8897     goto done;
8898   }
8899 not_supported:
8900   {
8901     GST_WARNING_OBJECT (src, "PLAY is not supported");
8902     goto done;
8903   }
8904 was_playing:
8905   {
8906     GST_WARNING_OBJECT (src, "we were already PLAYING");
8907     goto done;
8908   }
8909 create_request_failed:
8910   {
8911     gchar *str = gst_rtsp_strresult (res);
8912
8913 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8914     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
8915         "Could not create request. ");
8916 #else
8917     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
8918         ("Could not create request. (%s)", str));
8919 #endif
8920     g_free (str);
8921     goto done;
8922   }
8923 send_error:
8924   {
8925     gchar *str = gst_rtsp_strresult (res);
8926
8927     gst_rtsp_message_unset (&request);
8928     if (res != GST_RTSP_EINTR) {
8929 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8930       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
8931           "Could not send message.");
8932 #else
8933       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
8934           ("Could not send message. (%s)", str));
8935 #endif
8936     } else {
8937       GST_WARNING_OBJECT (src, "PLAY interrupted");
8938     }
8939     g_free (str);
8940     goto done;
8941   }
8942 }
8943
8944 static GstRTSPResult
8945 gst_rtspsrc_pause (GstRTSPSrc * src, gboolean async)
8946 {
8947   GstRTSPResult res = GST_RTSP_OK;
8948   GstRTSPMessage request = { 0 };
8949   GstRTSPMessage response = { 0 };
8950   GList *walk;
8951   const gchar *control;
8952
8953   GST_DEBUG_OBJECT (src, "PAUSE...");
8954
8955   if ((res = gst_rtspsrc_ensure_open (src, async)) < 0)
8956     goto open_failed;
8957
8958   if (!(src->methods & GST_RTSP_PAUSE))
8959     goto not_supported;
8960
8961   if (src->state == GST_RTSP_STATE_READY)
8962     goto was_paused;
8963
8964   if (!src->conninfo.connection || !src->conninfo.connected)
8965     goto no_connection;
8966
8967   /* construct a control url */
8968   control = get_aggregate_control (src);
8969
8970   /* loop over the streams. We might exit the loop early when we could do an
8971    * aggregate control */
8972   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8973     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8974     GstRTSPConnInfo *conninfo;
8975     const gchar *setup_url;
8976
8977     /* try aggregate control first but do non-aggregate control otherwise */
8978     if (control)
8979       setup_url = control;
8980     else if ((setup_url = stream->conninfo.location) == NULL)
8981       continue;
8982
8983     if (src->conninfo.connection) {
8984       conninfo = &src->conninfo;
8985     } else if (stream->conninfo.connection) {
8986       conninfo = &stream->conninfo;
8987     } else {
8988       continue;
8989     }
8990
8991     if (async)
8992       GST_ELEMENT_PROGRESS (src, CONTINUE, "request",
8993           ("Sending PAUSE request"));
8994
8995     if ((res =
8996             gst_rtspsrc_init_request (src, &request, GST_RTSP_PAUSE,
8997                 setup_url)) < 0)
8998       goto create_request_failed;
8999
9000     /* when we have an ONVIF audio backchannel, the PAUSE request must have the
9001      * Require: header when doing either aggregate or non-aggregate control */
9002     if (src->backchannel == BACKCHANNEL_ONVIF &&
9003         (control || stream->is_backchannel))
9004       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
9005           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
9006
9007     if ((res =
9008             gst_rtspsrc_send (src, conninfo, &request, &response, NULL,
9009                 NULL)) < 0)
9010       goto send_error;
9011
9012     gst_rtsp_message_unset (&request);
9013     gst_rtsp_message_unset (&response);
9014
9015     /* exit early when we did agregate control */
9016     if (control)
9017       break;
9018   }
9019
9020   /* change element states now */
9021   gst_rtspsrc_set_state (src, GST_STATE_PAUSED);
9022
9023 no_connection:
9024   src->state = GST_RTSP_STATE_READY;
9025
9026 done:
9027   if (async)
9028     gst_rtspsrc_loop_end_cmd (src, CMD_PAUSE, res);
9029
9030   return res;
9031
9032   /* ERRORS */
9033 open_failed:
9034   {
9035     GST_DEBUG_OBJECT (src, "failed to open stream");
9036     goto done;
9037   }
9038 not_supported:
9039   {
9040     GST_DEBUG_OBJECT (src, "PAUSE is not supported");
9041     goto done;
9042   }
9043 was_paused:
9044   {
9045     GST_DEBUG_OBJECT (src, "we were already PAUSED");
9046     goto done;
9047   }
9048 create_request_failed:
9049   {
9050     gchar *str = gst_rtsp_strresult (res);
9051
9052 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9053     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
9054         "Could not create request.");
9055 #else
9056     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
9057         ("Could not create request. (%s)", str));
9058 #endif
9059     g_free (str);
9060     goto done;
9061   }
9062 send_error:
9063   {
9064     gchar *str = gst_rtsp_strresult (res);
9065
9066     gst_rtsp_message_unset (&request);
9067     if (res != GST_RTSP_EINTR) {
9068 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9069       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
9070           "Could not send message.");
9071 #else
9072       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
9073           ("Could not send message. (%s)", str));
9074 #endif
9075     } else {
9076       GST_WARNING_OBJECT (src, "PAUSE interrupted");
9077     }
9078     g_free (str);
9079     goto done;
9080   }
9081 }
9082
9083 static void
9084 gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message)
9085 {
9086   GstRTSPSrc *rtspsrc;
9087
9088   rtspsrc = GST_RTSPSRC (bin);
9089
9090   switch (GST_MESSAGE_TYPE (message)) {
9091     case GST_MESSAGE_EOS:
9092       gst_message_unref (message);
9093       break;
9094     case GST_MESSAGE_ELEMENT:
9095     {
9096       const GstStructure *s = gst_message_get_structure (message);
9097
9098       if (gst_structure_has_name (s, "GstUDPSrcTimeout")) {
9099         gboolean ignore_timeout;
9100
9101         GST_DEBUG_OBJECT (bin, "timeout on UDP port");
9102
9103         GST_OBJECT_LOCK (rtspsrc);
9104         ignore_timeout = rtspsrc->ignore_timeout;
9105         rtspsrc->ignore_timeout = TRUE;
9106         GST_OBJECT_UNLOCK (rtspsrc);
9107
9108         /* we only act on the first udp timeout message, others are irrelevant
9109          * and can be ignored. */
9110         if (!ignore_timeout)
9111           gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_RECONNECT, CMD_LOOP);
9112         /* eat and free */
9113         gst_message_unref (message);
9114         return;
9115       }
9116       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
9117       break;
9118     }
9119     case GST_MESSAGE_ERROR:
9120     {
9121       GstObject *udpsrc;
9122       GstRTSPStream *stream;
9123       GstFlowReturn ret;
9124
9125       udpsrc = GST_MESSAGE_SRC (message);
9126
9127       GST_DEBUG_OBJECT (rtspsrc, "got error from %s",
9128           GST_ELEMENT_NAME (udpsrc));
9129
9130       stream = find_stream (rtspsrc, udpsrc, (gpointer) find_stream_by_udpsrc);
9131       if (!stream)
9132         goto forward;
9133
9134       /* we ignore the RTCP udpsrc */
9135       if (stream->udpsrc[1] == GST_ELEMENT_CAST (udpsrc))
9136         goto done;
9137
9138       /* if we get error messages from the udp sources, that's not a problem as
9139        * long as not all of them error out. We also don't really know what the
9140        * problem is, the message does not give enough detail... */
9141       ret = gst_rtspsrc_combine_flows (rtspsrc, stream, GST_FLOW_NOT_LINKED);
9142       GST_DEBUG_OBJECT (rtspsrc, "combined flows: %s", gst_flow_get_name (ret));
9143       if (ret != GST_FLOW_OK)
9144         goto forward;
9145
9146     done:
9147       gst_message_unref (message);
9148       break;
9149
9150     forward:
9151       /* fatal but not our message, forward */
9152       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
9153       break;
9154     }
9155     default:
9156     {
9157       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
9158       break;
9159     }
9160   }
9161 }
9162
9163 /* the thread where everything happens */
9164 static void
9165 gst_rtspsrc_thread (GstRTSPSrc * src)
9166 {
9167   gint cmd;
9168   ParameterRequest *req = NULL;
9169
9170   GST_OBJECT_LOCK (src);
9171   cmd = src->pending_cmd;
9172   if (cmd == CMD_RECONNECT || cmd == CMD_PLAY || cmd == CMD_PAUSE
9173       || cmd == CMD_LOOP || cmd == CMD_OPEN || cmd == CMD_GET_PARAMETER
9174       || cmd == CMD_SET_PARAMETER) {
9175     if (g_queue_is_empty (&src->set_get_param_q)) {
9176       src->pending_cmd = CMD_LOOP;
9177     } else {
9178       ParameterRequest *next_req;
9179       req = g_queue_pop_head (&src->set_get_param_q);
9180       next_req = g_queue_peek_head (&src->set_get_param_q);
9181       src->pending_cmd = next_req ? next_req->cmd : CMD_LOOP;
9182     }
9183   } else
9184     src->pending_cmd = CMD_WAIT;
9185   GST_DEBUG_OBJECT (src, "got command %s", cmd_to_string (cmd));
9186
9187   /* we got the message command, so ensure communication is possible again */
9188   gst_rtspsrc_connection_flush (src, FALSE);
9189
9190   src->busy_cmd = cmd;
9191   GST_OBJECT_UNLOCK (src);
9192
9193   switch (cmd) {
9194     case CMD_OPEN:
9195       gst_rtspsrc_open (src, TRUE);
9196       break;
9197     case CMD_PLAY:
9198       gst_rtspsrc_play (src, &src->segment, TRUE, NULL);
9199       break;
9200     case CMD_PAUSE:
9201       gst_rtspsrc_pause (src, TRUE);
9202       break;
9203     case CMD_CLOSE:
9204       gst_rtspsrc_close (src, TRUE, FALSE);
9205       break;
9206     case CMD_GET_PARAMETER:
9207       gst_rtspsrc_get_parameter (src, req);
9208       break;
9209     case CMD_SET_PARAMETER:
9210       gst_rtspsrc_set_parameter (src, req);
9211       break;
9212     case CMD_LOOP:
9213       gst_rtspsrc_loop (src);
9214       break;
9215     case CMD_RECONNECT:
9216       gst_rtspsrc_reconnect (src, FALSE);
9217       break;
9218     default:
9219       break;
9220   }
9221
9222   GST_OBJECT_LOCK (src);
9223   /* No more cmds, wake any waiters */
9224   g_cond_broadcast (&src->cmd_cond);
9225   /* and go back to sleep */
9226   if (src->pending_cmd == CMD_WAIT) {
9227     if (src->task)
9228       gst_task_pause (src->task);
9229   }
9230   /* reset waiting */
9231   src->busy_cmd = CMD_WAIT;
9232   GST_OBJECT_UNLOCK (src);
9233 }
9234
9235 static gboolean
9236 gst_rtspsrc_start (GstRTSPSrc * src)
9237 {
9238   GST_DEBUG_OBJECT (src, "starting");
9239
9240   GST_OBJECT_LOCK (src);
9241
9242   src->pending_cmd = CMD_WAIT;
9243
9244   if (src->task == NULL) {
9245     src->task = gst_task_new ((GstTaskFunction) gst_rtspsrc_thread, src, NULL);
9246     if (src->task == NULL)
9247       goto task_error;
9248
9249     gst_task_set_lock (src->task, GST_RTSP_STREAM_GET_LOCK (src));
9250   }
9251   GST_OBJECT_UNLOCK (src);
9252
9253   return TRUE;
9254
9255   /* ERRORS */
9256 task_error:
9257   {
9258     GST_OBJECT_UNLOCK (src);
9259     GST_ERROR_OBJECT (src, "failed to create task");
9260     return FALSE;
9261   }
9262 }
9263
9264 static gboolean
9265 gst_rtspsrc_stop (GstRTSPSrc * src)
9266 {
9267   GstTask *task;
9268
9269   GST_DEBUG_OBJECT (src, "stopping");
9270
9271   /* also cancels pending task */
9272   gst_rtspsrc_loop_send_cmd (src, CMD_WAIT, CMD_ALL);
9273
9274   GST_OBJECT_LOCK (src);
9275   if ((task = src->task)) {
9276     src->task = NULL;
9277     GST_OBJECT_UNLOCK (src);
9278
9279     gst_task_stop (task);
9280
9281     /* make sure it is not running */
9282     GST_RTSP_STREAM_LOCK (src);
9283     GST_RTSP_STREAM_UNLOCK (src);
9284
9285     /* now wait for the task to finish */
9286     gst_task_join (task);
9287
9288     /* and free the task */
9289     gst_object_unref (GST_OBJECT (task));
9290
9291     GST_OBJECT_LOCK (src);
9292   }
9293   GST_OBJECT_UNLOCK (src);
9294
9295   /* ensure synchronously all is closed and clean */
9296   gst_rtspsrc_close (src, FALSE, TRUE);
9297
9298   return TRUE;
9299 }
9300
9301 static GstStateChangeReturn
9302 gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
9303 {
9304   GstRTSPSrc *rtspsrc;
9305   GstStateChangeReturn ret;
9306 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9307   guint64 end_time;
9308 #endif
9309
9310   rtspsrc = GST_RTSPSRC (element);
9311 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9312   GST_WARNING_OBJECT (rtspsrc, "State change transition: %d \n", transition);
9313 #endif
9314
9315   switch (transition) {
9316     case GST_STATE_CHANGE_NULL_TO_READY:
9317       if (!gst_rtspsrc_start (rtspsrc))
9318         goto start_failed;
9319       break;
9320     case GST_STATE_CHANGE_READY_TO_PAUSED:
9321       /* init some state */
9322       rtspsrc->cur_protocols = rtspsrc->protocols;
9323       /* first attempt, don't ignore timeouts */
9324       rtspsrc->ignore_timeout = FALSE;
9325       rtspsrc->open_error = FALSE;
9326       gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_OPEN, 0);
9327       break;
9328     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
9329       set_manager_buffer_mode (rtspsrc);
9330       /* fall-through */
9331     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
9332       /* unblock the tcp tasks and make the loop waiting */
9333       if (gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_WAIT, CMD_LOOP)) {
9334         /* make sure it is waiting before we send PAUSE or PLAY below */
9335         GST_RTSP_STREAM_LOCK (rtspsrc);
9336         GST_RTSP_STREAM_UNLOCK (rtspsrc);
9337       }
9338       break;
9339     case GST_STATE_CHANGE_PAUSED_TO_READY:
9340       break;
9341     default:
9342       break;
9343   }
9344
9345   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
9346   if (ret == GST_STATE_CHANGE_FAILURE)
9347     goto done;
9348
9349   switch (transition) {
9350     case GST_STATE_CHANGE_NULL_TO_READY:
9351       ret = GST_STATE_CHANGE_SUCCESS;
9352       break;
9353     case GST_STATE_CHANGE_READY_TO_PAUSED:
9354 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9355       /* don't change to PAUSE state before complete stream opend.
9356          see gst_rtspsrc_loop_complete_cmd() */
9357       g_mutex_lock (&(rtspsrc)->pause_lock);
9358       end_time = g_get_monotonic_time () + 10 * G_TIME_SPAN_SECOND;
9359       if (!g_cond_wait_until (&(rtspsrc)->open_end, &(rtspsrc)->pause_lock,
9360               end_time)) {
9361         GST_WARNING_OBJECT (rtspsrc,
9362             "time out: stream opend is not completed yet..");
9363       }
9364       g_mutex_unlock (&(rtspsrc)->pause_lock);
9365 #endif
9366       ret = GST_STATE_CHANGE_NO_PREROLL;
9367       break;
9368     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
9369       gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_PLAY, 0);
9370       ret = GST_STATE_CHANGE_SUCCESS;
9371       break;
9372     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
9373       /* send pause request and keep the idle task around */
9374       gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_PAUSE, CMD_LOOP);
9375       ret = GST_STATE_CHANGE_NO_PREROLL;
9376       break;
9377     case GST_STATE_CHANGE_PAUSED_TO_READY:
9378       gst_rtspsrc_loop_send_cmd_and_wait (rtspsrc, CMD_CLOSE, CMD_ALL,
9379           rtspsrc->teardown_timeout);
9380       ret = GST_STATE_CHANGE_SUCCESS;
9381       break;
9382     case GST_STATE_CHANGE_READY_TO_NULL:
9383       gst_rtspsrc_stop (rtspsrc);
9384       ret = GST_STATE_CHANGE_SUCCESS;
9385       break;
9386     default:
9387       /* Otherwise it's success, we don't want to return spurious
9388        * NO_PREROLL or ASYNC from internal elements as we care for
9389        * state changes ourselves here
9390        *
9391        * This is to catch PAUSED->PAUSED and PLAYING->PLAYING transitions.
9392        */
9393       if (GST_STATE_TRANSITION_NEXT (transition) == GST_STATE_PAUSED)
9394         ret = GST_STATE_CHANGE_NO_PREROLL;
9395       else
9396         ret = GST_STATE_CHANGE_SUCCESS;
9397       break;
9398   }
9399
9400 done:
9401   return ret;
9402
9403 start_failed:
9404   {
9405     GST_DEBUG_OBJECT (rtspsrc, "start failed");
9406     return GST_STATE_CHANGE_FAILURE;
9407   }
9408 }
9409
9410 static gboolean
9411 gst_rtspsrc_send_event (GstElement * element, GstEvent * event)
9412 {
9413   gboolean res;
9414   GstRTSPSrc *rtspsrc;
9415
9416   rtspsrc = GST_RTSPSRC (element);
9417
9418   if (GST_EVENT_IS_DOWNSTREAM (event)) {
9419     res = gst_rtspsrc_push_event (rtspsrc, event);
9420   } else {
9421     res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
9422   }
9423
9424   return res;
9425 }
9426
9427
9428 /*** GSTURIHANDLER INTERFACE *************************************************/
9429
9430 static GstURIType
9431 gst_rtspsrc_uri_get_type (GType type)
9432 {
9433   return GST_URI_SRC;
9434 }
9435
9436 static const gchar *const *
9437 gst_rtspsrc_uri_get_protocols (GType type)
9438 {
9439   static const gchar *protocols[] =
9440       { "rtsp", "rtspu", "rtspt", "rtsph", "rtsp-sdp",
9441     "rtsps", "rtspsu", "rtspst", "rtspsh", NULL
9442   };
9443
9444   return protocols;
9445 }
9446
9447 static gchar *
9448 gst_rtspsrc_uri_get_uri (GstURIHandler * handler)
9449 {
9450   GstRTSPSrc *src = GST_RTSPSRC (handler);
9451
9452   /* FIXME: make thread-safe */
9453   return g_strdup (src->conninfo.location);
9454 }
9455
9456 static gboolean
9457 gst_rtspsrc_uri_set_uri (GstURIHandler * handler, const gchar * uri,
9458     GError ** error)
9459 {
9460   GstRTSPSrc *src;
9461   GstRTSPResult res;
9462   GstSDPResult sres;
9463   GstRTSPUrl *newurl = NULL;
9464   GstSDPMessage *sdp = NULL;
9465
9466   src = GST_RTSPSRC (handler);
9467
9468   /* same URI, we're fine */
9469   if (src->conninfo.location && uri && !strcmp (uri, src->conninfo.location))
9470     goto was_ok;
9471
9472   if (g_str_has_prefix (uri, "rtsp-sdp://")) {
9473     sres = gst_sdp_message_new (&sdp);
9474     if (sres < 0)
9475       goto sdp_failed;
9476
9477     GST_DEBUG_OBJECT (src, "parsing SDP message");
9478     sres = gst_sdp_message_parse_uri (uri, sdp);
9479     if (sres < 0)
9480       goto invalid_sdp;
9481   } else {
9482     /* try to parse */
9483     GST_DEBUG_OBJECT (src, "parsing URI");
9484     if ((res = gst_rtsp_url_parse (uri, &newurl)) < 0)
9485       goto parse_error;
9486   }
9487
9488   /* if worked, free previous and store new url object along with the original
9489    * location. */
9490   GST_DEBUG_OBJECT (src, "configuring URI");
9491   g_free (src->conninfo.location);
9492   src->conninfo.location = g_strdup (uri);
9493   gst_rtsp_url_free (src->conninfo.url);
9494   src->conninfo.url = newurl;
9495   g_free (src->conninfo.url_str);
9496   if (newurl)
9497     src->conninfo.url_str = gst_rtsp_url_get_request_uri (src->conninfo.url);
9498   else
9499     src->conninfo.url_str = NULL;
9500
9501   if (src->sdp)
9502     gst_sdp_message_free (src->sdp);
9503   src->sdp = sdp;
9504   src->from_sdp = sdp != NULL;
9505
9506   GST_DEBUG_OBJECT (src, "set uri: %s", GST_STR_NULL (uri));
9507   GST_DEBUG_OBJECT (src, "request uri is: %s",
9508       GST_STR_NULL (src->conninfo.url_str));
9509
9510   return TRUE;
9511
9512   /* Special cases */
9513 was_ok:
9514   {
9515     GST_DEBUG_OBJECT (src, "URI was ok: '%s'", GST_STR_NULL (uri));
9516     return TRUE;
9517   }
9518 sdp_failed:
9519   {
9520     GST_ERROR_OBJECT (src, "Could not create new SDP (%d)", sres);
9521     g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
9522         "Could not create SDP");
9523     return FALSE;
9524   }
9525 invalid_sdp:
9526   {
9527     GST_ERROR_OBJECT (src, "Not a valid SDP (%d) '%s'", sres,
9528         GST_STR_NULL (uri));
9529     gst_sdp_message_free (sdp);
9530     g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
9531         "Invalid SDP");
9532     return FALSE;
9533   }
9534 parse_error:
9535   {
9536     GST_ERROR_OBJECT (src, "Not a valid RTSP url '%s' (%d)",
9537         GST_STR_NULL (uri), res);
9538     g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
9539         "Invalid RTSP URI");
9540     return FALSE;
9541   }
9542 }
9543
9544 static void
9545 gst_rtspsrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
9546 {
9547   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
9548
9549   iface->get_type = gst_rtspsrc_uri_get_type;
9550   iface->get_protocols = gst_rtspsrc_uri_get_protocols;
9551   iface->get_uri = gst_rtspsrc_uri_get_uri;
9552   iface->set_uri = gst_rtspsrc_uri_set_uri;
9553 }
9554
9555
9556 /* send GET_PARAMETER */
9557 static GstRTSPResult
9558 gst_rtspsrc_get_parameter (GstRTSPSrc * src, ParameterRequest * req)
9559 {
9560   GstRTSPMessage request = { 0 };
9561   GstRTSPMessage response = { 0 };
9562   GstRTSPResult res;
9563   GstRTSPStatusCode code = GST_RTSP_STS_OK;
9564   const gchar *control;
9565   gchar *recv_body = NULL;
9566   guint recv_body_len;
9567
9568   GST_DEBUG_OBJECT (src, "creating server get_parameter");
9569
9570   if ((res = gst_rtspsrc_ensure_open (src, FALSE)) < 0)
9571     goto open_failed;
9572
9573   control = get_aggregate_control (src);
9574   if (control == NULL)
9575     goto no_control;
9576
9577   if (!(src->methods & GST_RTSP_GET_PARAMETER))
9578     goto not_supported;
9579
9580   gst_rtspsrc_connection_flush (src, FALSE);
9581
9582   res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER,
9583       control);
9584   if (res < 0)
9585     goto create_request_failed;
9586
9587   res = gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_TYPE,
9588       req->content_type == NULL ? "text/parameters" : req->content_type);
9589   if (res < 0)
9590     goto add_content_hdr_failed;
9591
9592   if (req->body && req->body->len) {
9593     res =
9594         gst_rtsp_message_set_body (&request, (guint8 *) req->body->str,
9595         req->body->len);
9596     if (res < 0)
9597       goto set_body_failed;
9598   }
9599
9600   if ((res = gst_rtspsrc_send (src, &src->conninfo,
9601               &request, &response, &code, NULL)) < 0)
9602     goto send_error;
9603
9604   res = gst_rtsp_message_get_body (&response, (guint8 **) & recv_body,
9605       &recv_body_len);
9606   if (res < 0)
9607     goto get_body_failed;
9608
9609 done:
9610   {
9611     gst_promise_reply (req->promise,
9612         gst_structure_new ("get-parameter-reply",
9613             "rtsp-result", G_TYPE_INT, res,
9614             "rtsp-code", G_TYPE_INT, code,
9615             "rtsp-reason", G_TYPE_STRING, gst_rtsp_status_as_text (code),
9616             "body", G_TYPE_STRING, GST_STR_NULL (recv_body), NULL));
9617     free_param_data (req);
9618
9619
9620     gst_rtsp_message_unset (&request);
9621     gst_rtsp_message_unset (&response);
9622
9623     return res;
9624   }
9625
9626   /* ERRORS */
9627 open_failed:
9628   {
9629     GST_DEBUG_OBJECT (src, "failed to open stream");
9630     goto done;
9631   }
9632 no_control:
9633   {
9634     GST_DEBUG_OBJECT (src, "no control url to send GET_PARAMETER");
9635     res = GST_RTSP_ERROR;
9636     goto done;
9637   }
9638 not_supported:
9639   {
9640     GST_DEBUG_OBJECT (src, "GET_PARAMETER is not supported");
9641     res = GST_RTSP_ERROR;
9642     goto done;
9643   }
9644 create_request_failed:
9645   {
9646     GST_DEBUG_OBJECT (src, "could not create GET_PARAMETER request");
9647     goto done;
9648   }
9649 add_content_hdr_failed:
9650   {
9651     GST_DEBUG_OBJECT (src, "could not add content header");
9652     goto done;
9653   }
9654 set_body_failed:
9655   {
9656     GST_DEBUG_OBJECT (src, "could not set body");
9657     goto done;
9658   }
9659 send_error:
9660   {
9661     gchar *str = gst_rtsp_strresult (res);
9662
9663     GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
9664         ("Could not send get-parameter. (%s)", str));
9665     g_free (str);
9666     goto done;
9667   }
9668 get_body_failed:
9669   {
9670     GST_DEBUG_OBJECT (src, "could not get body");
9671     goto done;
9672   }
9673 }
9674
9675 /* send SET_PARAMETER */
9676 static GstRTSPResult
9677 gst_rtspsrc_set_parameter (GstRTSPSrc * src, ParameterRequest * req)
9678 {
9679   GstRTSPMessage request = { 0 };
9680   GstRTSPMessage response = { 0 };
9681   GstRTSPResult res = GST_RTSP_OK;
9682   GstRTSPStatusCode code = GST_RTSP_STS_OK;
9683   const gchar *control;
9684
9685   GST_DEBUG_OBJECT (src, "creating server set_parameter");
9686
9687   if ((res = gst_rtspsrc_ensure_open (src, FALSE)) < 0)
9688     goto open_failed;
9689
9690   control = get_aggregate_control (src);
9691   if (control == NULL)
9692     goto no_control;
9693
9694   if (!(src->methods & GST_RTSP_SET_PARAMETER))
9695     goto not_supported;
9696
9697   gst_rtspsrc_connection_flush (src, FALSE);
9698
9699   res =
9700       gst_rtsp_message_init_request (&request, GST_RTSP_SET_PARAMETER, control);
9701   if (res < 0)
9702     goto send_error;
9703
9704   res = gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_TYPE,
9705       req->content_type == NULL ? "text/parameters" : req->content_type);
9706   if (res < 0)
9707     goto add_content_hdr_failed;
9708
9709   if (req->body && req->body->len) {
9710     res =
9711         gst_rtsp_message_set_body (&request, (guint8 *) req->body->str,
9712         req->body->len);
9713
9714     if (res < 0)
9715       goto set_body_failed;
9716   }
9717
9718   if ((res = gst_rtspsrc_send (src, &src->conninfo,
9719               &request, &response, &code, NULL)) < 0)
9720     goto send_error;
9721
9722 done:
9723   {
9724     gst_promise_reply (req->promise, gst_structure_new ("set-parameter-reply",
9725             "rtsp-result", G_TYPE_INT, res,
9726             "rtsp-code", G_TYPE_INT, code,
9727             "rtsp-reason", G_TYPE_STRING, gst_rtsp_status_as_text (code),
9728             NULL));
9729     free_param_data (req);
9730
9731     gst_rtsp_message_unset (&request);
9732     gst_rtsp_message_unset (&response);
9733
9734     return res;
9735   }
9736
9737   /* ERRORS */
9738 open_failed:
9739   {
9740     GST_DEBUG_OBJECT (src, "failed to open stream");
9741     goto done;
9742   }
9743 no_control:
9744   {
9745     GST_DEBUG_OBJECT (src, "no control url to send SET_PARAMETER");
9746     res = GST_RTSP_ERROR;
9747     goto done;
9748   }
9749 not_supported:
9750   {
9751     GST_DEBUG_OBJECT (src, "SET_PARAMETER is not supported");
9752     res = GST_RTSP_ERROR;
9753     goto done;
9754   }
9755 add_content_hdr_failed:
9756   {
9757     GST_DEBUG_OBJECT (src, "could not add content header");
9758     goto done;
9759   }
9760 set_body_failed:
9761   {
9762     GST_DEBUG_OBJECT (src, "could not set body");
9763     goto done;
9764   }
9765 send_error:
9766   {
9767     gchar *str = gst_rtsp_strresult (res);
9768
9769     GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
9770         ("Could not send set-parameter. (%s)", str));
9771     g_free (str);
9772     goto done;
9773   }
9774 }
9775
9776 typedef struct _RTSPKeyValue
9777 {
9778   GstRTSPHeaderField field;
9779   gchar *value;
9780   gchar *custom_key;            /* custom header string (field is INVALID then) */
9781 } RTSPKeyValue;
9782
9783 static void
9784 key_value_foreach (GArray * array, GFunc func, gpointer user_data)
9785 {
9786   guint i;
9787
9788   g_return_if_fail (array != NULL);
9789
9790   for (i = 0; i < array->len; i++) {
9791     (*func) (&g_array_index (array, RTSPKeyValue, i), user_data);
9792   }
9793 }
9794
9795 static void
9796 dump_key_value (gpointer data, gpointer user_data G_GNUC_UNUSED)
9797 {
9798   RTSPKeyValue *key_value = (RTSPKeyValue *) data;
9799   GstRTSPSrc *src = GST_RTSPSRC (user_data);
9800   const gchar *key_string;
9801
9802   if (key_value->custom_key != NULL)
9803     key_string = key_value->custom_key;
9804   else
9805     key_string = gst_rtsp_header_as_text (key_value->field);
9806
9807   GST_LOG_OBJECT (src, "   key: '%s', value: '%s'", key_string,
9808       key_value->value);
9809 }
9810
9811 static void
9812 gst_rtspsrc_print_rtsp_message (GstRTSPSrc * src, const GstRTSPMessage * msg)
9813 {
9814   guint8 *data;
9815   guint size;
9816   GString *body_string = NULL;
9817
9818   g_return_if_fail (src != NULL);
9819   g_return_if_fail (msg != NULL);
9820
9821   if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_LOG)
9822     return;
9823
9824   GST_LOG_OBJECT (src, "--------------------------------------------");
9825   switch (msg->type) {
9826     case GST_RTSP_MESSAGE_REQUEST:
9827       GST_LOG_OBJECT (src, "RTSP request message %p", msg);
9828       GST_LOG_OBJECT (src, " request line:");
9829       GST_LOG_OBJECT (src, "   method: '%s'",
9830           gst_rtsp_method_as_text (msg->type_data.request.method));
9831       GST_LOG_OBJECT (src, "   uri:    '%s'", msg->type_data.request.uri);
9832       GST_LOG_OBJECT (src, "   version: '%s'",
9833           gst_rtsp_version_as_text (msg->type_data.request.version));
9834       GST_LOG_OBJECT (src, " headers:");
9835       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9836       GST_LOG_OBJECT (src, " body:");
9837       gst_rtsp_message_get_body (msg, &data, &size);
9838       if (size > 0) {
9839         body_string = g_string_new_len ((const gchar *) data, size);
9840         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9841         g_string_free (body_string, TRUE);
9842         body_string = NULL;
9843       }
9844       break;
9845     case GST_RTSP_MESSAGE_RESPONSE:
9846       GST_LOG_OBJECT (src, "RTSP response message %p", msg);
9847       GST_LOG_OBJECT (src, " status line:");
9848       GST_LOG_OBJECT (src, "   code:   '%d'", msg->type_data.response.code);
9849       GST_LOG_OBJECT (src, "   reason: '%s'", msg->type_data.response.reason);
9850       GST_LOG_OBJECT (src, "   version: '%s",
9851           gst_rtsp_version_as_text (msg->type_data.response.version));
9852       GST_LOG_OBJECT (src, " headers:");
9853       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9854       gst_rtsp_message_get_body (msg, &data, &size);
9855       GST_LOG_OBJECT (src, " body: length %d", size);
9856       if (size > 0) {
9857         body_string = g_string_new_len ((const gchar *) data, size);
9858         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9859         g_string_free (body_string, TRUE);
9860         body_string = NULL;
9861       }
9862       break;
9863     case GST_RTSP_MESSAGE_HTTP_REQUEST:
9864       GST_LOG_OBJECT (src, "HTTP request message %p", msg);
9865       GST_LOG_OBJECT (src, " request line:");
9866       GST_LOG_OBJECT (src, "   method:  '%s'",
9867           gst_rtsp_method_as_text (msg->type_data.request.method));
9868       GST_LOG_OBJECT (src, "   uri:     '%s'", msg->type_data.request.uri);
9869       GST_LOG_OBJECT (src, "   version: '%s'",
9870           gst_rtsp_version_as_text (msg->type_data.request.version));
9871       GST_LOG_OBJECT (src, " headers:");
9872       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9873       GST_LOG_OBJECT (src, " body:");
9874       gst_rtsp_message_get_body (msg, &data, &size);
9875       if (size > 0) {
9876         body_string = g_string_new_len ((const gchar *) data, size);
9877         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9878         g_string_free (body_string, TRUE);
9879         body_string = NULL;
9880       }
9881       break;
9882     case GST_RTSP_MESSAGE_HTTP_RESPONSE:
9883       GST_LOG_OBJECT (src, "HTTP response message %p", msg);
9884       GST_LOG_OBJECT (src, " status line:");
9885       GST_LOG_OBJECT (src, "   code:    '%d'", msg->type_data.response.code);
9886       GST_LOG_OBJECT (src, "   reason:  '%s'", msg->type_data.response.reason);
9887       GST_LOG_OBJECT (src, "   version: '%s'",
9888           gst_rtsp_version_as_text (msg->type_data.response.version));
9889       GST_LOG_OBJECT (src, " headers:");
9890       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9891       gst_rtsp_message_get_body (msg, &data, &size);
9892       GST_LOG_OBJECT (src, " body: length %d", size);
9893       if (size > 0) {
9894         body_string = g_string_new_len ((const gchar *) data, size);
9895         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9896         g_string_free (body_string, TRUE);
9897         body_string = NULL;
9898       }
9899       break;
9900     case GST_RTSP_MESSAGE_DATA:
9901       GST_LOG_OBJECT (src, "RTSP data message %p", msg);
9902       GST_LOG_OBJECT (src, " channel: '%d'", msg->type_data.data.channel);
9903       GST_LOG_OBJECT (src, " size:    '%d'", msg->body_size);
9904       gst_rtsp_message_get_body (msg, &data, &size);
9905       if (size > 0) {
9906         body_string = g_string_new_len ((const gchar *) data, size);
9907         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9908         g_string_free (body_string, TRUE);
9909         body_string = NULL;
9910       }
9911       break;
9912     default:
9913       GST_LOG_OBJECT (src, "unsupported message type %d", msg->type);
9914       break;
9915   }
9916   GST_LOG_OBJECT (src, "--------------------------------------------");
9917 }
9918
9919 static void
9920 gst_rtspsrc_print_sdp_media (GstRTSPSrc * src, GstSDPMedia * media)
9921 {
9922   GST_LOG_OBJECT (src, "   media:       '%s'", GST_STR_NULL (media->media));
9923   GST_LOG_OBJECT (src, "   port:        '%u'", media->port);
9924   GST_LOG_OBJECT (src, "   num_ports:   '%u'", media->num_ports);
9925   GST_LOG_OBJECT (src, "   proto:       '%s'", GST_STR_NULL (media->proto));
9926   if (media->fmts && media->fmts->len > 0) {
9927     guint i;
9928
9929     GST_LOG_OBJECT (src, "   formats:");
9930     for (i = 0; i < media->fmts->len; i++) {
9931       GST_LOG_OBJECT (src, "    format  '%s'", g_array_index (media->fmts,
9932               gchar *, i));
9933     }
9934   }
9935   GST_LOG_OBJECT (src, "   information: '%s'",
9936       GST_STR_NULL (media->information));
9937   if (media->connections && media->connections->len > 0) {
9938     guint i;
9939
9940     GST_LOG_OBJECT (src, "   connections:");
9941     for (i = 0; i < media->connections->len; i++) {
9942       GstSDPConnection *conn =
9943           &g_array_index (media->connections, GstSDPConnection, i);
9944
9945       GST_LOG_OBJECT (src, "    nettype:      '%s'",
9946           GST_STR_NULL (conn->nettype));
9947       GST_LOG_OBJECT (src, "    addrtype:     '%s'",
9948           GST_STR_NULL (conn->addrtype));
9949       GST_LOG_OBJECT (src, "    address:      '%s'",
9950           GST_STR_NULL (conn->address));
9951       GST_LOG_OBJECT (src, "    ttl:          '%u'", conn->ttl);
9952       GST_LOG_OBJECT (src, "    addr_number:  '%u'", conn->addr_number);
9953     }
9954   }
9955   if (media->bandwidths && media->bandwidths->len > 0) {
9956     guint i;
9957
9958     GST_LOG_OBJECT (src, "   bandwidths:");
9959     for (i = 0; i < media->bandwidths->len; i++) {
9960       GstSDPBandwidth *bw =
9961           &g_array_index (media->bandwidths, GstSDPBandwidth, i);
9962
9963       GST_LOG_OBJECT (src, "    type:         '%s'", GST_STR_NULL (bw->bwtype));
9964       GST_LOG_OBJECT (src, "    bandwidth:    '%u'", bw->bandwidth);
9965     }
9966   }
9967   GST_LOG_OBJECT (src, "   key:");
9968   GST_LOG_OBJECT (src, "    type:       '%s'", GST_STR_NULL (media->key.type));
9969   GST_LOG_OBJECT (src, "    data:       '%s'", GST_STR_NULL (media->key.data));
9970   if (media->attributes && media->attributes->len > 0) {
9971     guint i;
9972
9973     GST_LOG_OBJECT (src, "   attributes:");
9974     for (i = 0; i < media->attributes->len; i++) {
9975       GstSDPAttribute *attr =
9976           &g_array_index (media->attributes, GstSDPAttribute, i);
9977
9978       GST_LOG_OBJECT (src, "    attribute '%s' : '%s'", attr->key, attr->value);
9979     }
9980   }
9981 }
9982
9983 void
9984 gst_rtspsrc_print_sdp_message (GstRTSPSrc * src, const GstSDPMessage * msg)
9985 {
9986   g_return_if_fail (src != NULL);
9987   g_return_if_fail (msg != NULL);
9988
9989   if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_LOG)
9990     return;
9991
9992   GST_LOG_OBJECT (src, "--------------------------------------------");
9993   GST_LOG_OBJECT (src, "sdp packet %p:", msg);
9994   GST_LOG_OBJECT (src, " version:       '%s'", GST_STR_NULL (msg->version));
9995   GST_LOG_OBJECT (src, " origin:");
9996   GST_LOG_OBJECT (src, "  username:     '%s'",
9997       GST_STR_NULL (msg->origin.username));
9998   GST_LOG_OBJECT (src, "  sess_id:      '%s'",
9999       GST_STR_NULL (msg->origin.sess_id));
10000   GST_LOG_OBJECT (src, "  sess_version: '%s'",
10001       GST_STR_NULL (msg->origin.sess_version));
10002   GST_LOG_OBJECT (src, "  nettype:      '%s'",
10003       GST_STR_NULL (msg->origin.nettype));
10004   GST_LOG_OBJECT (src, "  addrtype:     '%s'",
10005       GST_STR_NULL (msg->origin.addrtype));
10006   GST_LOG_OBJECT (src, "  addr:         '%s'", GST_STR_NULL (msg->origin.addr));
10007   GST_LOG_OBJECT (src, " session_name:  '%s'",
10008       GST_STR_NULL (msg->session_name));
10009   GST_LOG_OBJECT (src, " information:   '%s'", GST_STR_NULL (msg->information));
10010   GST_LOG_OBJECT (src, " uri:           '%s'", GST_STR_NULL (msg->uri));
10011
10012   if (msg->emails && msg->emails->len > 0) {
10013     guint i;
10014
10015     GST_LOG_OBJECT (src, " emails:");
10016     for (i = 0; i < msg->emails->len; i++) {
10017       GST_LOG_OBJECT (src, "  email '%s'", g_array_index (msg->emails, gchar *,
10018               i));
10019     }
10020   }
10021   if (msg->phones && msg->phones->len > 0) {
10022     guint i;
10023
10024     GST_LOG_OBJECT (src, " phones:");
10025     for (i = 0; i < msg->phones->len; i++) {
10026       GST_LOG_OBJECT (src, "  phone '%s'", g_array_index (msg->phones, gchar *,
10027               i));
10028     }
10029   }
10030   GST_LOG_OBJECT (src, " connection:");
10031   GST_LOG_OBJECT (src, "  nettype:      '%s'",
10032       GST_STR_NULL (msg->connection.nettype));
10033   GST_LOG_OBJECT (src, "  addrtype:     '%s'",
10034       GST_STR_NULL (msg->connection.addrtype));
10035   GST_LOG_OBJECT (src, "  address:      '%s'",
10036       GST_STR_NULL (msg->connection.address));
10037   GST_LOG_OBJECT (src, "  ttl:          '%u'", msg->connection.ttl);
10038   GST_LOG_OBJECT (src, "  addr_number:  '%u'", msg->connection.addr_number);
10039   if (msg->bandwidths && msg->bandwidths->len > 0) {
10040     guint i;
10041
10042     GST_LOG_OBJECT (src, " bandwidths:");
10043     for (i = 0; i < msg->bandwidths->len; i++) {
10044       GstSDPBandwidth *bw =
10045           &g_array_index (msg->bandwidths, GstSDPBandwidth, i);
10046
10047       GST_LOG_OBJECT (src, "  type:         '%s'", GST_STR_NULL (bw->bwtype));
10048       GST_LOG_OBJECT (src, "  bandwidth:    '%u'", bw->bandwidth);
10049     }
10050   }
10051   GST_LOG_OBJECT (src, " key:");
10052   GST_LOG_OBJECT (src, "  type:         '%s'", GST_STR_NULL (msg->key.type));
10053   GST_LOG_OBJECT (src, "  data:         '%s'", GST_STR_NULL (msg->key.data));
10054   if (msg->attributes && msg->attributes->len > 0) {
10055     guint i;
10056
10057     GST_LOG_OBJECT (src, " attributes:");
10058     for (i = 0; i < msg->attributes->len; i++) {
10059       GstSDPAttribute *attr =
10060           &g_array_index (msg->attributes, GstSDPAttribute, i);
10061
10062       GST_LOG_OBJECT (src, "  attribute '%s' : '%s'", attr->key, attr->value);
10063     }
10064   }
10065   if (msg->medias && msg->medias->len > 0) {
10066     guint i;
10067
10068     GST_LOG_OBJECT (src, " medias:");
10069     for (i = 0; i < msg->medias->len; i++) {
10070       GST_LOG_OBJECT (src, "  media %u:", i);
10071       gst_rtspsrc_print_sdp_media (src, &g_array_index (msg->medias,
10072               GstSDPMedia, i));
10073     }
10074   }
10075   GST_LOG_OBJECT (src, "--------------------------------------------");
10076 }