390fb6f8eb38dba50f4d5b675f39163af9173040
[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
3976       /* we manage this element */
3977       gst_element_set_locked_state (src->manager, TRUE);
3978       gst_bin_add (GST_BIN_CAST (src), src->manager);
3979
3980       ret = gst_element_set_state (src->manager, GST_STATE_PAUSED);
3981       if (ret == GST_STATE_CHANGE_FAILURE)
3982         goto start_manager_failure;
3983
3984       g_object_set (src->manager, "latency", src->latency, NULL);
3985
3986       klass = G_OBJECT_GET_CLASS (G_OBJECT (src->manager));
3987
3988       if (g_object_class_find_property (klass, "ntp-sync")) {
3989         g_object_set (src->manager, "ntp-sync", src->ntp_sync, NULL);
3990       }
3991
3992       if (g_object_class_find_property (klass, "rfc7273-sync")) {
3993         g_object_set (src->manager, "rfc7273-sync", src->rfc7273_sync, NULL);
3994       }
3995
3996       if (src->use_pipeline_clock) {
3997         if (g_object_class_find_property (klass, "use-pipeline-clock")) {
3998           g_object_set (src->manager, "use-pipeline-clock", TRUE, NULL);
3999         }
4000       } else {
4001         if (g_object_class_find_property (klass, "ntp-time-source")) {
4002           g_object_set (src->manager, "ntp-time-source", src->ntp_time_source,
4003               NULL);
4004         }
4005       }
4006
4007       if (src->sdes && g_object_class_find_property (klass, "sdes")) {
4008         g_object_set (src->manager, "sdes", src->sdes, NULL);
4009       }
4010
4011       if (g_object_class_find_property (klass, "drop-on-latency")) {
4012         g_object_set (src->manager, "drop-on-latency", src->drop_on_latency,
4013             NULL);
4014       }
4015
4016       if (g_object_class_find_property (klass, "max-rtcp-rtp-time-diff")) {
4017         g_object_set (src->manager, "max-rtcp-rtp-time-diff",
4018             src->max_rtcp_rtp_time_diff, NULL);
4019       }
4020
4021       if (g_object_class_find_property (klass, "max-ts-offset-adjustment")) {
4022         g_object_set (src->manager, "max-ts-offset-adjustment",
4023             src->max_ts_offset_adjustment, NULL);
4024       }
4025
4026       if (g_object_class_find_property (klass, "max-ts-offset")) {
4027         gint64 max_ts_offset;
4028
4029         /* setting max-ts-offset in the manager has side effects so only do it
4030          * if the value differs */
4031         g_object_get (src->manager, "max-ts-offset", &max_ts_offset, NULL);
4032         if (max_ts_offset != src->max_ts_offset) {
4033           g_object_set (src->manager, "max-ts-offset", src->max_ts_offset,
4034               NULL);
4035         }
4036       }
4037
4038       /* buffer mode pauses are handled by adding offsets to buffer times,
4039        * but some depayloaders may have a hard time syncing output times
4040        * with such input times, e.g. container ones, most notably ASF */
4041       /* TODO alternatives are having an event that indicates these shifts,
4042        * or having rtsp extensions provide suggestion on buffer mode */
4043       /* valid duration implies not likely live pipeline,
4044        * so slaving in jitterbuffer does not make much sense
4045        * (and might mess things up due to bursts) */
4046       if (GST_CLOCK_TIME_IS_VALID (src->segment.duration) &&
4047           src->segment.duration && stream->container) {
4048         src->use_buffering = TRUE;
4049       } else {
4050         src->use_buffering = FALSE;
4051       }
4052
4053       set_manager_buffer_mode (src);
4054
4055       /* connect to signals */
4056       GST_DEBUG_OBJECT (src, "connect to signals on session manager, stream %p",
4057           stream);
4058       src->manager_sig_id =
4059           g_signal_connect (src->manager, "pad-added",
4060           (GCallback) new_manager_pad, src);
4061       src->manager_ptmap_id =
4062           g_signal_connect (src->manager, "request-pt-map",
4063           (GCallback) request_pt_map, src);
4064
4065       g_signal_connect (src->manager, "on-npt-stop", (GCallback) on_npt_stop,
4066           src);
4067
4068       g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_NEW_MANAGER], 0,
4069           src->manager);
4070
4071       if (src->do_retransmission)
4072         add_retransmission (src, transport);
4073     }
4074     g_signal_connect (src->manager, "request-rtp-decoder",
4075         (GCallback) request_rtp_decoder, stream);
4076     g_signal_connect (src->manager, "request-rtcp-decoder",
4077         (GCallback) request_rtp_decoder, stream);
4078     g_signal_connect (src->manager, "request-rtcp-encoder",
4079         (GCallback) request_rtcp_encoder, stream);
4080
4081     /* we stream directly to the manager, get some pads. Each RTSP stream goes
4082      * into a separate RTP session. */
4083     name = g_strdup_printf ("recv_rtp_sink_%u", stream->id);
4084     stream->channelpad[0] = gst_element_get_request_pad (src->manager, name);
4085     g_free (name);
4086     name = g_strdup_printf ("recv_rtcp_sink_%u", stream->id);
4087     stream->channelpad[1] = gst_element_get_request_pad (src->manager, name);
4088     g_free (name);
4089
4090     /* now configure the bandwidth in the manager */
4091     if (g_signal_lookup ("get-internal-session",
4092             G_OBJECT_TYPE (src->manager)) != 0) {
4093       GObject *rtpsession;
4094
4095       g_signal_emit_by_name (src->manager, "get-internal-session", stream->id,
4096           &rtpsession);
4097       if (rtpsession) {
4098         GstRTPProfile rtp_profile;
4099
4100         GST_INFO_OBJECT (src, "configure bandwidth in session %p", rtpsession);
4101
4102         stream->session = rtpsession;
4103
4104         if (stream->as_bandwidth != -1) {
4105           GST_INFO_OBJECT (src, "setting AS: %f",
4106               (gdouble) (stream->as_bandwidth * 1000));
4107           g_object_set (rtpsession, "bandwidth",
4108               (gdouble) (stream->as_bandwidth * 1000), NULL);
4109         }
4110         if (stream->rr_bandwidth != -1) {
4111           GST_INFO_OBJECT (src, "setting RR: %u", stream->rr_bandwidth);
4112           g_object_set (rtpsession, "rtcp-rr-bandwidth", stream->rr_bandwidth,
4113               NULL);
4114         }
4115         if (stream->rs_bandwidth != -1) {
4116           GST_INFO_OBJECT (src, "setting RS: %u", stream->rs_bandwidth);
4117           g_object_set (rtpsession, "rtcp-rs-bandwidth", stream->rs_bandwidth,
4118               NULL);
4119         }
4120
4121         switch (stream->profile) {
4122           case GST_RTSP_PROFILE_AVPF:
4123             rtp_profile = GST_RTP_PROFILE_AVPF;
4124             break;
4125           case GST_RTSP_PROFILE_SAVP:
4126             rtp_profile = GST_RTP_PROFILE_SAVP;
4127             break;
4128           case GST_RTSP_PROFILE_SAVPF:
4129             rtp_profile = GST_RTP_PROFILE_SAVPF;
4130             break;
4131           case GST_RTSP_PROFILE_AVP:
4132           default:
4133             rtp_profile = GST_RTP_PROFILE_AVP;
4134             break;
4135         }
4136
4137         g_object_set (rtpsession, "rtp-profile", rtp_profile, NULL);
4138
4139         g_object_set (rtpsession, "probation", src->probation, NULL);
4140
4141         g_object_set (rtpsession, "internal-ssrc", stream->send_ssrc, NULL);
4142
4143         g_signal_connect (rtpsession, "on-bye-ssrc", (GCallback) on_bye_ssrc,
4144             stream);
4145         g_signal_connect (rtpsession, "on-bye-timeout",
4146             (GCallback) on_timeout_common, stream);
4147         g_signal_connect (rtpsession, "on-timeout", (GCallback) on_timeout,
4148             stream);
4149         g_signal_connect (rtpsession, "on-ssrc-active",
4150             (GCallback) on_ssrc_active, stream);
4151       }
4152     }
4153   }
4154
4155 use_no_manager:
4156   return TRUE;
4157
4158   /* ERRORS */
4159 no_manager:
4160   {
4161     GST_DEBUG_OBJECT (src, "cannot get a session manager");
4162     return FALSE;
4163   }
4164 manager_failed:
4165   {
4166     GST_DEBUG_OBJECT (src, "no session manager element %s found", manager);
4167     return FALSE;
4168   }
4169 start_manager_failure:
4170   {
4171     GST_DEBUG_OBJECT (src, "could not start session manager");
4172     return FALSE;
4173   }
4174 }
4175
4176 /* free the UDP sources allocated when negotiating a transport.
4177  * This function is called when the server negotiated to a transport where the
4178  * UDP sources are not needed anymore, such as TCP or multicast. */
4179 static void
4180 gst_rtspsrc_stream_free_udp (GstRTSPStream * stream)
4181 {
4182   gint i;
4183
4184   for (i = 0; i < 2; i++) {
4185     if (stream->udpsrc[i]) {
4186       GST_DEBUG ("free UDP source %d for stream %p", i, stream);
4187       gst_element_set_state (stream->udpsrc[i], GST_STATE_NULL);
4188       gst_object_unref (stream->udpsrc[i]);
4189       stream->udpsrc[i] = NULL;
4190     }
4191   }
4192 }
4193
4194 /* for TCP, create pads to send and receive data to and from the manager and to
4195  * intercept various events and queries
4196  */
4197 static gboolean
4198 gst_rtspsrc_stream_configure_tcp (GstRTSPSrc * src, GstRTSPStream * stream,
4199     GstRTSPTransport * transport, GstPad ** outpad)
4200 {
4201   gchar *name;
4202   GstPadTemplate *template;
4203   GstPad *pad0, *pad1;
4204
4205   /* configure for interleaved delivery, nothing needs to be done
4206    * here, the loop function will call the chain functions of the
4207    * session manager. */
4208   stream->channel[0] = transport->interleaved.min;
4209   stream->channel[1] = transport->interleaved.max;
4210   GST_DEBUG_OBJECT (src, "stream %p on channels %d-%d", stream,
4211       stream->channel[0], stream->channel[1]);
4212
4213   /* we can remove the allocated UDP ports now */
4214   gst_rtspsrc_stream_free_udp (stream);
4215
4216   /* no session manager, send data to srcpad directly */
4217   if (!stream->channelpad[0]) {
4218     GST_DEBUG_OBJECT (src, "no manager, creating pad");
4219
4220     /* create a new pad we will use to stream to */
4221     name = g_strdup_printf ("stream_%u", stream->id);
4222     template = gst_static_pad_template_get (&rtptemplate);
4223     stream->channelpad[0] = gst_pad_new_from_template (template, name);
4224     gst_object_unref (template);
4225     g_free (name);
4226
4227     /* set caps and activate */
4228     gst_pad_use_fixed_caps (stream->channelpad[0]);
4229     gst_pad_set_active (stream->channelpad[0], TRUE);
4230
4231     *outpad = gst_object_ref (stream->channelpad[0]);
4232   } else {
4233     GST_DEBUG_OBJECT (src, "using manager source pad");
4234
4235     template = gst_static_pad_template_get (&anysrctemplate);
4236
4237     /* allocate pads for sending the channel data into the manager */
4238     pad0 = gst_pad_new_from_template (template, "internalsrc_0");
4239     gst_pad_link_full (pad0, stream->channelpad[0], GST_PAD_LINK_CHECK_NOTHING);
4240     gst_object_unref (stream->channelpad[0]);
4241     stream->channelpad[0] = pad0;
4242     gst_pad_set_event_function (pad0, gst_rtspsrc_handle_internal_src_event);
4243     gst_pad_set_query_function (pad0, gst_rtspsrc_handle_internal_src_query);
4244     gst_pad_set_element_private (pad0, src);
4245     gst_pad_set_active (pad0, TRUE);
4246
4247     if (stream->channelpad[1]) {
4248       /* if we have a sinkpad for the other channel, create a pad and link to the
4249        * manager. */
4250       pad1 = gst_pad_new_from_template (template, "internalsrc_1");
4251       gst_pad_set_event_function (pad1, gst_rtspsrc_handle_internal_src_event);
4252       gst_pad_link_full (pad1, stream->channelpad[1],
4253           GST_PAD_LINK_CHECK_NOTHING);
4254       gst_object_unref (stream->channelpad[1]);
4255       stream->channelpad[1] = pad1;
4256       gst_pad_set_active (pad1, TRUE);
4257     }
4258     gst_object_unref (template);
4259   }
4260   /* setup RTCP transport back to the server if we have to. */
4261   if (src->manager && src->do_rtcp) {
4262     GstPad *pad;
4263
4264     template = gst_static_pad_template_get (&anysinktemplate);
4265
4266     stream->rtcppad = gst_pad_new_from_template (template, "internalsink_0");
4267     gst_pad_set_chain_function (stream->rtcppad, gst_rtspsrc_sink_chain);
4268     gst_pad_set_element_private (stream->rtcppad, stream);
4269     gst_pad_set_active (stream->rtcppad, TRUE);
4270
4271     /* get session RTCP pad */
4272     name = g_strdup_printf ("send_rtcp_src_%u", stream->id);
4273     pad = gst_element_get_request_pad (src->manager, name);
4274     g_free (name);
4275
4276     /* and link */
4277     if (pad) {
4278       gst_pad_link_full (pad, stream->rtcppad, GST_PAD_LINK_CHECK_NOTHING);
4279       gst_object_unref (pad);
4280     }
4281
4282     gst_object_unref (template);
4283   }
4284   return TRUE;
4285 }
4286
4287 static void
4288 gst_rtspsrc_get_transport_info (GstRTSPSrc * src, GstRTSPStream * stream,
4289     GstRTSPTransport * transport, const gchar ** destination, gint * min,
4290     gint * max, guint * ttl)
4291 {
4292   if (transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
4293     if (destination) {
4294       if (!(*destination = transport->destination))
4295         *destination = stream->destination;
4296     }
4297     if (min && max) {
4298       /* transport first */
4299       *min = transport->port.min;
4300       *max = transport->port.max;
4301       if (*min == -1 && *max == -1) {
4302         /* then try from SDP */
4303         if (stream->port != 0) {
4304           *min = stream->port;
4305           *max = stream->port + 1;
4306         }
4307       }
4308     }
4309
4310     if (ttl) {
4311       if (!(*ttl = transport->ttl))
4312         *ttl = stream->ttl;
4313     }
4314   } else {
4315     if (destination) {
4316       /* first take the source, then the endpoint to figure out where to send
4317        * the RTCP. */
4318       if (!(*destination = transport->source)) {
4319         if (src->conninfo.connection)
4320           *destination = gst_rtsp_connection_get_ip (src->conninfo.connection);
4321         else if (stream->conninfo.connection)
4322           *destination =
4323               gst_rtsp_connection_get_ip (stream->conninfo.connection);
4324       }
4325     }
4326     if (min && max) {
4327       /* for unicast we only expect the ports here */
4328       *min = transport->server_port.min;
4329       *max = transport->server_port.max;
4330     }
4331   }
4332 }
4333
4334 /* For multicast create UDP sources and join the multicast group. */
4335 static gboolean
4336 gst_rtspsrc_stream_configure_mcast (GstRTSPSrc * src, GstRTSPStream * stream,
4337     GstRTSPTransport * transport, GstPad ** outpad)
4338 {
4339   gchar *uri;
4340   const gchar *destination;
4341   gint min, max;
4342
4343   GST_DEBUG_OBJECT (src, "creating UDP sources for multicast");
4344
4345   /* we can remove the allocated UDP ports now */
4346   gst_rtspsrc_stream_free_udp (stream);
4347
4348   gst_rtspsrc_get_transport_info (src, stream, transport, &destination, &min,
4349       &max, NULL);
4350
4351   /* we need a destination now */
4352   if (destination == NULL)
4353     goto no_destination;
4354
4355   /* we really need ports now or we won't be able to receive anything at all */
4356   if (min == -1 && max == -1)
4357     goto no_ports;
4358
4359   GST_DEBUG_OBJECT (src, "have destination '%s' and ports (%d)-(%d)",
4360       destination, min, max);
4361
4362   /* creating UDP source for RTP */
4363   if (min != -1) {
4364     uri = g_strdup_printf ("udp://%s:%d", destination, min);
4365     stream->udpsrc[0] =
4366         gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
4367     g_free (uri);
4368     if (stream->udpsrc[0] == NULL)
4369       goto no_element;
4370
4371     /* take ownership */
4372     gst_object_ref_sink (stream->udpsrc[0]);
4373
4374     if (src->udp_buffer_size != 0)
4375       g_object_set (G_OBJECT (stream->udpsrc[0]), "buffer-size",
4376           src->udp_buffer_size, NULL);
4377
4378     if (src->multi_iface != NULL)
4379       g_object_set (G_OBJECT (stream->udpsrc[0]), "multicast-iface",
4380           src->multi_iface, NULL);
4381
4382     /* change state */
4383     gst_element_set_locked_state (stream->udpsrc[0], TRUE);
4384     gst_element_set_state (stream->udpsrc[0], GST_STATE_READY);
4385   }
4386
4387   /* creating another UDP source for RTCP */
4388   if (max != -1) {
4389     GstCaps *caps;
4390
4391     uri = g_strdup_printf ("udp://%s:%d", destination, max);
4392     stream->udpsrc[1] =
4393         gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
4394     g_free (uri);
4395     if (stream->udpsrc[1] == NULL)
4396       goto no_element;
4397
4398     if (stream->profile == GST_RTSP_PROFILE_SAVP ||
4399         stream->profile == GST_RTSP_PROFILE_SAVPF)
4400       caps = gst_caps_new_empty_simple ("application/x-srtcp");
4401     else
4402       caps = gst_caps_new_empty_simple ("application/x-rtcp");
4403     g_object_set (stream->udpsrc[1], "caps", caps, NULL);
4404     gst_caps_unref (caps);
4405
4406     /* take ownership */
4407     gst_object_ref_sink (stream->udpsrc[1]);
4408
4409     if (src->multi_iface != NULL)
4410       g_object_set (G_OBJECT (stream->udpsrc[1]), "multicast-iface",
4411           src->multi_iface, NULL);
4412
4413     gst_element_set_state (stream->udpsrc[1], GST_STATE_READY);
4414   }
4415   return TRUE;
4416
4417   /* ERRORS */
4418 no_element:
4419   {
4420     GST_DEBUG_OBJECT (src, "no UDP source element found");
4421     return FALSE;
4422   }
4423 no_destination:
4424   {
4425     GST_DEBUG_OBJECT (src, "no destination found");
4426     return FALSE;
4427   }
4428 no_ports:
4429   {
4430     GST_DEBUG_OBJECT (src, "no ports found");
4431     return FALSE;
4432   }
4433 }
4434
4435 /* configure the remainder of the UDP ports */
4436 static gboolean
4437 gst_rtspsrc_stream_configure_udp (GstRTSPSrc * src, GstRTSPStream * stream,
4438     GstRTSPTransport * transport, GstPad ** outpad)
4439 {
4440   /* we manage the UDP elements now. For unicast, the UDP sources where
4441    * allocated in the stream when we suggested a transport. */
4442   if (stream->udpsrc[0]) {
4443     GstCaps *caps;
4444
4445     gst_element_set_locked_state (stream->udpsrc[0], TRUE);
4446     gst_bin_add (GST_BIN_CAST (src), stream->udpsrc[0]);
4447
4448     GST_DEBUG_OBJECT (src, "setting up UDP source");
4449
4450     /* configure a timeout on the UDP port. When the timeout message is
4451      * posted, we assume UDP transport is not possible. We reconnect using TCP
4452      * if we can. */
4453     g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout",
4454         src->udp_timeout * 1000, NULL);
4455
4456     if ((caps = stream_get_caps_for_pt (stream, stream->default_pt)))
4457       g_object_set (stream->udpsrc[0], "caps", caps, NULL);
4458
4459     /* get output pad of the UDP source. */
4460     *outpad = gst_element_get_static_pad (stream->udpsrc[0], "src");
4461
4462     /* save it so we can unblock */
4463     stream->blockedpad = *outpad;
4464
4465     /* configure pad block on the pad. As soon as there is dataflow on the
4466      * UDP source, we know that UDP is not blocked by a firewall and we can
4467      * configure all the streams to let the application autoplug decoders. */
4468     stream->blockid =
4469         gst_pad_add_probe (stream->blockedpad,
4470         GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER |
4471         GST_PAD_PROBE_TYPE_BUFFER_LIST, pad_blocked, src, NULL);
4472
4473     gst_pad_add_probe (stream->blockedpad,
4474         GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, udpsrc_probe_cb,
4475         &(stream->segment_seqnum[0]), NULL);
4476
4477     if (stream->channelpad[0]) {
4478       GST_DEBUG_OBJECT (src, "connecting UDP source 0 to manager");
4479       /* configure for UDP delivery, we need to connect the UDP pads to
4480        * the session plugin. */
4481       gst_pad_link_full (*outpad, stream->channelpad[0],
4482           GST_PAD_LINK_CHECK_NOTHING);
4483       gst_object_unref (*outpad);
4484       *outpad = NULL;
4485       /* we connected to pad-added signal to get pads from the manager */
4486     } else {
4487       GST_DEBUG_OBJECT (src, "using UDP src pad as output");
4488     }
4489   }
4490
4491   /* RTCP port */
4492   if (stream->udpsrc[1]) {
4493     GstCaps *caps;
4494
4495     gst_element_set_locked_state (stream->udpsrc[1], TRUE);
4496     gst_bin_add (GST_BIN_CAST (src), stream->udpsrc[1]);
4497
4498     if (stream->profile == GST_RTSP_PROFILE_SAVP ||
4499         stream->profile == GST_RTSP_PROFILE_SAVPF)
4500       caps = gst_caps_new_empty_simple ("application/x-srtcp");
4501     else
4502       caps = gst_caps_new_empty_simple ("application/x-rtcp");
4503     g_object_set (stream->udpsrc[1], "caps", caps, NULL);
4504     gst_caps_unref (caps);
4505
4506     if (stream->channelpad[1]) {
4507       GstPad *pad;
4508
4509       GST_DEBUG_OBJECT (src, "connecting UDP source 1 to manager");
4510
4511       pad = gst_element_get_static_pad (stream->udpsrc[1], "src");
4512       gst_pad_add_probe (pad,
4513           GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, udpsrc_probe_cb,
4514           &(stream->segment_seqnum[1]), NULL);
4515       gst_pad_link_full (pad, stream->channelpad[1],
4516           GST_PAD_LINK_CHECK_NOTHING);
4517       gst_object_unref (pad);
4518     } else {
4519       /* leave unlinked */
4520     }
4521   }
4522   return TRUE;
4523 }
4524
4525 /* configure the UDP sink back to the server for status reports */
4526 static gboolean
4527 gst_rtspsrc_stream_configure_udp_sinks (GstRTSPSrc * src,
4528     GstRTSPStream * stream, GstRTSPTransport * transport)
4529 {
4530   GstPad *pad;
4531   gint rtp_port, rtcp_port;
4532   gboolean do_rtp, do_rtcp;
4533   const gchar *destination;
4534   gchar *uri, *name;
4535   guint ttl = 0;
4536   GSocket *socket;
4537
4538   /* get transport info */
4539   gst_rtspsrc_get_transport_info (src, stream, transport, &destination,
4540       &rtp_port, &rtcp_port, &ttl);
4541
4542   /* see what we need to do */
4543   do_rtp = (rtp_port != -1);
4544   /* it's possible that the server does not want us to send RTCP in which case
4545    * the port is -1 */
4546   do_rtcp = (rtcp_port != -1 && src->manager != NULL && src->do_rtcp);
4547
4548   /* we need a destination when we have RTP or RTCP ports */
4549   if (destination == NULL && (do_rtp || do_rtcp))
4550     goto no_destination;
4551
4552   /* try to construct the fakesrc to the RTP port of the server to open up any
4553    * NAT firewalls or, if backchannel, construct an appsrc */
4554   if (do_rtp) {
4555     GST_DEBUG_OBJECT (src, "configure RTP UDP sink for %s:%d", destination,
4556         rtp_port);
4557
4558     uri = g_strdup_printf ("udp://%s:%d", destination, rtp_port);
4559     stream->udpsink[0] =
4560         gst_element_make_from_uri (GST_URI_SINK, uri, NULL, NULL);
4561     g_free (uri);
4562     if (stream->udpsink[0] == NULL)
4563       goto no_sink_element;
4564
4565     /* don't join multicast group, we will have the source socket do that */
4566     /* no sync or async state changes needed */
4567     g_object_set (G_OBJECT (stream->udpsink[0]), "auto-multicast", FALSE,
4568         "loop", FALSE, "sync", FALSE, "async", FALSE, NULL);
4569     if (ttl > 0)
4570       g_object_set (G_OBJECT (stream->udpsink[0]), "ttl", ttl, NULL);
4571
4572     if (stream->udpsrc[0]) {
4573       /* configure socket, we give it the same UDP socket as the udpsrc for RTP
4574        * so that NAT firewalls will open a hole for us */
4575       g_object_get (G_OBJECT (stream->udpsrc[0]), "used-socket", &socket, NULL);
4576       if (!socket)
4577         goto no_socket;
4578
4579       GST_DEBUG_OBJECT (src, "RTP UDP src has sock %p", socket);
4580       /* configure socket and make sure udpsink does not close it when shutting
4581        * down, it belongs to udpsrc after all. */
4582       g_object_set (G_OBJECT (stream->udpsink[0]), "socket", socket,
4583           "close-socket", FALSE, NULL);
4584       g_object_unref (socket);
4585     }
4586
4587     if (stream->is_backchannel) {
4588       /* appsrc is for the app to shovel data using push-backchannel-buffer */
4589       stream->rtpsrc = gst_element_factory_make ("appsrc", NULL);
4590       if (stream->rtpsrc == NULL)
4591         goto no_appsrc_element;
4592
4593       /* interal use only, don't emit signals */
4594       g_object_set (G_OBJECT (stream->rtpsrc), "emit-signals", TRUE,
4595           "is-live", TRUE, NULL);
4596     } else {
4597       /* the source for the dummy packets to open up NAT */
4598       stream->rtpsrc = gst_element_factory_make ("fakesrc", NULL);
4599       if (stream->rtpsrc == NULL)
4600         goto no_fakesrc_element;
4601
4602       /* random data in 5 buffers, a size of 200 bytes should be fine */
4603       g_object_set (G_OBJECT (stream->rtpsrc), "filltype", 3, "num-buffers", 5,
4604           "sizetype", 2, "sizemax", 200, "silent", TRUE, NULL);
4605     }
4606
4607     /* keep everything locked */
4608     gst_element_set_locked_state (stream->udpsink[0], TRUE);
4609     gst_element_set_locked_state (stream->rtpsrc, TRUE);
4610
4611     gst_object_ref (stream->udpsink[0]);
4612     gst_bin_add (GST_BIN_CAST (src), stream->udpsink[0]);
4613     gst_object_ref (stream->rtpsrc);
4614     gst_bin_add (GST_BIN_CAST (src), stream->rtpsrc);
4615
4616     gst_element_link_pads_full (stream->rtpsrc, "src", stream->udpsink[0],
4617         "sink", GST_PAD_LINK_CHECK_NOTHING);
4618   }
4619   if (do_rtcp) {
4620     GST_DEBUG_OBJECT (src, "configure RTCP UDP sink for %s:%d", destination,
4621         rtcp_port);
4622
4623     uri = g_strdup_printf ("udp://%s:%d", destination, rtcp_port);
4624     stream->udpsink[1] =
4625         gst_element_make_from_uri (GST_URI_SINK, uri, NULL, NULL);
4626     g_free (uri);
4627     if (stream->udpsink[1] == NULL)
4628       goto no_sink_element;
4629
4630     /* don't join multicast group, we will have the source socket do that */
4631     /* no sync or async state changes needed */
4632     g_object_set (G_OBJECT (stream->udpsink[1]), "auto-multicast", FALSE,
4633         "loop", FALSE, "sync", FALSE, "async", FALSE, NULL);
4634     if (ttl > 0)
4635       g_object_set (G_OBJECT (stream->udpsink[0]), "ttl", ttl, NULL);
4636
4637     if (stream->udpsrc[1]) {
4638       /* configure socket, we give it the same UDP socket as the udpsrc for RTCP
4639        * because some servers check the port number of where it sends RTCP to identify
4640        * the RTCP packets it receives */
4641       g_object_get (G_OBJECT (stream->udpsrc[1]), "used-socket", &socket, NULL);
4642       if (!socket)
4643         goto no_socket;
4644
4645       GST_DEBUG_OBJECT (src, "RTCP UDP src has sock %p", socket);
4646       /* configure socket and make sure udpsink does not close it when shutting
4647        * down, it belongs to udpsrc after all. */
4648       g_object_set (G_OBJECT (stream->udpsink[1]), "socket", socket,
4649           "close-socket", FALSE, NULL);
4650       g_object_unref (socket);
4651     }
4652
4653     /* we keep this playing always */
4654     gst_element_set_locked_state (stream->udpsink[1], TRUE);
4655     gst_element_set_state (stream->udpsink[1], GST_STATE_PLAYING);
4656
4657     gst_object_ref (stream->udpsink[1]);
4658     gst_bin_add (GST_BIN_CAST (src), stream->udpsink[1]);
4659
4660     stream->rtcppad = gst_element_get_static_pad (stream->udpsink[1], "sink");
4661
4662     /* get session RTCP pad */
4663     name = g_strdup_printf ("send_rtcp_src_%u", stream->id);
4664     pad = gst_element_get_request_pad (src->manager, name);
4665     g_free (name);
4666
4667     /* and link */
4668     if (pad) {
4669       gst_pad_link_full (pad, stream->rtcppad, GST_PAD_LINK_CHECK_NOTHING);
4670       gst_object_unref (pad);
4671     }
4672   }
4673
4674   return TRUE;
4675
4676   /* ERRORS */
4677 no_destination:
4678   {
4679     GST_ERROR_OBJECT (src, "no destination address specified");
4680     return FALSE;
4681   }
4682 no_sink_element:
4683   {
4684     GST_ERROR_OBJECT (src, "no UDP sink element found");
4685     return FALSE;
4686   }
4687 no_appsrc_element:
4688   {
4689     GST_ERROR_OBJECT (src, "no appsrc element found");
4690     return FALSE;
4691   }
4692 no_fakesrc_element:
4693   {
4694     GST_ERROR_OBJECT (src, "no fakesrc element found");
4695     return FALSE;
4696   }
4697 no_socket:
4698   {
4699     GST_ERROR_OBJECT (src, "failed to create socket");
4700     return FALSE;
4701   }
4702 }
4703
4704 /* sets up all elements needed for streaming over the specified transport.
4705  * Does not yet expose the element pads, this will be done when there is actuall
4706  * dataflow detected, which might never happen when UDP is blocked in a
4707  * firewall, for example.
4708  */
4709 static gboolean
4710 gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
4711     GstRTSPTransport * transport)
4712 {
4713   GstRTSPSrc *src;
4714   GstPad *outpad = NULL;
4715   GstPadTemplate *template;
4716   gchar *name;
4717   const gchar *media_type;
4718   guint i, len;
4719
4720   src = stream->parent;
4721
4722   GST_DEBUG_OBJECT (src, "configuring transport for stream %p", stream);
4723
4724   /* get the proper media type for this stream now */
4725   if (gst_rtsp_transport_get_media_type (transport, &media_type) < 0)
4726     goto unknown_transport;
4727   if (!media_type)
4728     goto unknown_transport;
4729
4730   /* configure the final media type */
4731   GST_DEBUG_OBJECT (src, "setting media type to %s", media_type);
4732
4733   len = stream->ptmap->len;
4734   for (i = 0; i < len; i++) {
4735     GstStructure *s;
4736     PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, i);
4737
4738     if (item->caps == NULL)
4739       continue;
4740
4741     s = gst_caps_get_structure (item->caps, 0);
4742     gst_structure_set_name (s, media_type);
4743     /* set ssrc if known */
4744     if (transport->ssrc)
4745       gst_structure_set (s, "ssrc", G_TYPE_UINT, transport->ssrc, NULL);
4746   }
4747
4748   /* try to get and configure a manager, channelpad[0-1] will be configured with
4749    * the pads for the manager, or NULL when no manager is needed. */
4750   if (!gst_rtspsrc_stream_configure_manager (src, stream, transport))
4751     goto no_manager;
4752
4753   switch (transport->lower_transport) {
4754     case GST_RTSP_LOWER_TRANS_TCP:
4755       if (!gst_rtspsrc_stream_configure_tcp (src, stream, transport, &outpad))
4756         goto transport_failed;
4757       break;
4758     case GST_RTSP_LOWER_TRANS_UDP_MCAST:
4759       if (!gst_rtspsrc_stream_configure_mcast (src, stream, transport, &outpad))
4760         goto transport_failed;
4761       /* fallthrough, the rest is the same for UDP and MCAST */
4762     case GST_RTSP_LOWER_TRANS_UDP:
4763       if (!gst_rtspsrc_stream_configure_udp (src, stream, transport, &outpad))
4764         goto transport_failed;
4765       /* configure udpsinks back to the server for RTCP messages, for the
4766        * dummy RTP messages to open NAT, and for the backchannel */
4767       if (!gst_rtspsrc_stream_configure_udp_sinks (src, stream, transport))
4768         goto transport_failed;
4769       break;
4770     default:
4771       goto unknown_transport;
4772   }
4773
4774   /* using backchannel and no manager, hence no srcpad for this stream */
4775   if (outpad && stream->is_backchannel) {
4776     add_backchannel_fakesink (src, stream, outpad);
4777     gst_object_unref (outpad);
4778   } else if (outpad) {
4779     GST_DEBUG_OBJECT (src, "creating ghostpad for stream %p", stream);
4780
4781     gst_pad_use_fixed_caps (outpad);
4782
4783     /* create ghostpad, don't add just yet, this will be done when we activate
4784      * the stream. */
4785     name = g_strdup_printf ("stream_%u", stream->id);
4786     template = gst_static_pad_template_get (&rtptemplate);
4787     stream->srcpad = gst_ghost_pad_new_from_template (name, outpad, template);
4788     gst_pad_set_event_function (stream->srcpad, gst_rtspsrc_handle_src_event);
4789     gst_pad_set_query_function (stream->srcpad, gst_rtspsrc_handle_src_query);
4790     gst_object_unref (template);
4791     g_free (name);
4792
4793     gst_object_unref (outpad);
4794   }
4795   /* mark pad as ok */
4796   stream->last_ret = GST_FLOW_OK;
4797
4798   return TRUE;
4799
4800   /* ERRORS */
4801 transport_failed:
4802   {
4803     GST_WARNING_OBJECT (src, "failed to configure transport");
4804     return FALSE;
4805   }
4806 unknown_transport:
4807   {
4808     GST_WARNING_OBJECT (src, "unknown transport");
4809     return FALSE;
4810   }
4811 no_manager:
4812   {
4813     GST_WARNING_OBJECT (src, "cannot get a session manager");
4814     return FALSE;
4815   }
4816 }
4817
4818 /* send a couple of dummy random packets on the receiver RTP port to the server,
4819  * this should make a firewall think we initiated the data transfer and
4820  * hopefully allow packets to go from the sender port to our RTP receiver port */
4821 static gboolean
4822 gst_rtspsrc_send_dummy_packets (GstRTSPSrc * src)
4823 {
4824   GList *walk;
4825
4826   if (src->nat_method != GST_RTSP_NAT_DUMMY)
4827     return TRUE;
4828
4829   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4830     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4831
4832     if (!stream->rtpsrc || !stream->udpsink[0])
4833       continue;
4834
4835     if (stream->is_backchannel)
4836       GST_DEBUG_OBJECT (src, "starting backchannel stream %p", stream);
4837     else
4838       GST_DEBUG_OBJECT (src, "sending dummy packet to stream %p", stream);
4839
4840     gst_element_set_state (stream->udpsink[0], GST_STATE_NULL);
4841     gst_element_set_state (stream->rtpsrc, GST_STATE_NULL);
4842     gst_element_set_state (stream->udpsink[0], GST_STATE_PLAYING);
4843     gst_element_set_state (stream->rtpsrc, GST_STATE_PLAYING);
4844   }
4845   return TRUE;
4846 }
4847
4848 /* Adds the source pads of all configured streams to the element.
4849  * This code is performed when we detected dataflow.
4850  *
4851  * We detect dataflow from either the _loop function or with pad probes on the
4852  * udp sources.
4853  */
4854 static gboolean
4855 gst_rtspsrc_activate_streams (GstRTSPSrc * src)
4856 {
4857   GList *walk;
4858
4859   GST_DEBUG_OBJECT (src, "activating streams");
4860
4861   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4862     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4863
4864     if (stream->udpsrc[0]) {
4865       /* remove timeout, we are streaming now and timeouts will be handled by
4866        * the session manager and jitter buffer */
4867       g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout", (guint64) 0, NULL);
4868     }
4869     if (stream->srcpad) {
4870       GST_DEBUG_OBJECT (src, "activating stream pad %p", stream);
4871       gst_pad_set_active (stream->srcpad, TRUE);
4872
4873       /* if we don't have a session manager, set the caps now. If we have a
4874        * session, we will get a notification of the pad and the caps. */
4875       if (!src->manager) {
4876         GstCaps *caps;
4877
4878         caps = stream_get_caps_for_pt (stream, stream->default_pt);
4879         GST_DEBUG_OBJECT (src, "setting pad caps for stream %p", stream);
4880         gst_pad_set_caps (stream->srcpad, caps);
4881       }
4882       /* add the pad */
4883       if (!stream->added) {
4884         GST_DEBUG_OBJECT (src, "adding stream pad %p", stream);
4885         if (stream->is_backchannel)
4886           add_backchannel_fakesink (src, stream, stream->srcpad);
4887         else
4888           gst_element_add_pad (GST_ELEMENT_CAST (src), stream->srcpad);
4889         stream->added = TRUE;
4890       }
4891     }
4892   }
4893
4894   /* unblock all pads */
4895   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4896     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4897
4898     if (stream->blockid) {
4899       GST_DEBUG_OBJECT (src, "unblocking stream pad %p", stream);
4900       gst_pad_remove_probe (stream->blockedpad, stream->blockid);
4901       stream->blockid = 0;
4902     }
4903   }
4904
4905   return TRUE;
4906 }
4907
4908 static void
4909 gst_rtspsrc_configure_caps (GstRTSPSrc * src, GstSegment * segment,
4910     gboolean reset_manager)
4911 {
4912   GList *walk;
4913   guint64 start, stop;
4914   gdouble play_speed, play_scale;
4915
4916   GST_DEBUG_OBJECT (src, "configuring stream caps");
4917
4918   start = segment->position;
4919   stop = segment->duration;
4920   play_speed = segment->rate;
4921   play_scale = segment->applied_rate;
4922
4923   for (walk = src->streams; walk; walk = g_list_next (walk)) {
4924     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
4925     guint j, len;
4926
4927     if (!stream->setup)
4928       continue;
4929
4930     len = stream->ptmap->len;
4931     for (j = 0; j < len; j++) {
4932       GstCaps *caps;
4933       PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, j);
4934
4935       if (item->caps == NULL)
4936         continue;
4937
4938       caps = gst_caps_make_writable (item->caps);
4939       /* update caps */
4940       if (stream->timebase != -1)
4941         gst_caps_set_simple (caps, "clock-base", G_TYPE_UINT,
4942             (guint) stream->timebase, NULL);
4943       if (stream->seqbase != -1)
4944         gst_caps_set_simple (caps, "seqnum-base", G_TYPE_UINT,
4945             (guint) stream->seqbase, NULL);
4946       gst_caps_set_simple (caps, "npt-start", G_TYPE_UINT64, start, NULL);
4947       if (stop != -1)
4948         gst_caps_set_simple (caps, "npt-stop", G_TYPE_UINT64, stop, NULL);
4949       gst_caps_set_simple (caps, "play-speed", G_TYPE_DOUBLE, play_speed, NULL);
4950       gst_caps_set_simple (caps, "play-scale", G_TYPE_DOUBLE, play_scale, NULL);
4951
4952       item->caps = caps;
4953       GST_DEBUG_OBJECT (src, "stream %p, pt %d, caps %" GST_PTR_FORMAT, stream,
4954           item->pt, caps);
4955
4956       if (item->pt == stream->default_pt) {
4957         if (stream->udpsrc[0])
4958           g_object_set (stream->udpsrc[0], "caps", caps, NULL);
4959         stream->need_caps = TRUE;
4960       }
4961     }
4962   }
4963   if (reset_manager && src->manager) {
4964     GST_DEBUG_OBJECT (src, "clear session");
4965     g_signal_emit_by_name (src->manager, "clear-pt-map", NULL);
4966   }
4967 }
4968
4969 static GstFlowReturn
4970 gst_rtspsrc_combine_flows (GstRTSPSrc * src, GstRTSPStream * stream,
4971     GstFlowReturn ret)
4972 {
4973   GList *streams;
4974
4975   /* store the value */
4976   stream->last_ret = ret;
4977
4978   /* if it's success we can return the value right away */
4979   if (ret == GST_FLOW_OK)
4980     goto done;
4981
4982   /* any other error that is not-linked can be returned right
4983    * away */
4984   if (ret != GST_FLOW_NOT_LINKED)
4985     goto done;
4986
4987   /* only return NOT_LINKED if all other pads returned NOT_LINKED */
4988   for (streams = src->streams; streams; streams = g_list_next (streams)) {
4989     GstRTSPStream *ostream = (GstRTSPStream *) streams->data;
4990
4991     ret = ostream->last_ret;
4992     /* some other return value (must be SUCCESS but we can return
4993      * other values as well) */
4994     if (ret != GST_FLOW_NOT_LINKED)
4995       goto done;
4996   }
4997   /* if we get here, all other pads were unlinked and we return
4998    * NOT_LINKED then */
4999 done:
5000   return ret;
5001 }
5002
5003 static gboolean
5004 gst_rtspsrc_stream_push_event (GstRTSPSrc * src, GstRTSPStream * stream,
5005     GstEvent * event)
5006 {
5007   gboolean res = TRUE;
5008
5009   /* only streams that have a connection to the outside world */
5010   if (!stream->setup)
5011     goto done;
5012
5013   if (stream->udpsrc[0]) {
5014     GstEvent *sent_event;
5015
5016     if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
5017       sent_event = gst_event_new_eos ();
5018       gst_event_set_seqnum (sent_event, stream->segment_seqnum[0]);
5019     } else {
5020       sent_event = gst_event_ref (event);
5021     }
5022
5023     res = gst_element_send_event (stream->udpsrc[0], sent_event);
5024   } else if (stream->channelpad[0]) {
5025     gst_event_ref (event);
5026     if (GST_PAD_IS_SRC (stream->channelpad[0]))
5027       res = gst_pad_push_event (stream->channelpad[0], event);
5028     else
5029       res = gst_pad_send_event (stream->channelpad[0], event);
5030   }
5031
5032   if (stream->udpsrc[1]) {
5033     GstEvent *sent_event;
5034
5035     if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
5036       sent_event = gst_event_new_eos ();
5037       if (stream->segment_seqnum[1] != GST_SEQNUM_INVALID) {
5038         gst_event_set_seqnum (sent_event, stream->segment_seqnum[1]);
5039       }
5040     } else {
5041       sent_event = gst_event_ref (event);
5042     }
5043
5044     res &= gst_element_send_event (stream->udpsrc[1], sent_event);
5045   } else if (stream->channelpad[1]) {
5046     gst_event_ref (event);
5047     if (GST_PAD_IS_SRC (stream->channelpad[1]))
5048       res &= gst_pad_push_event (stream->channelpad[1], event);
5049     else
5050       res &= gst_pad_send_event (stream->channelpad[1], event);
5051   }
5052
5053 done:
5054   gst_event_unref (event);
5055
5056   return res;
5057 }
5058
5059 static gboolean
5060 gst_rtspsrc_push_event (GstRTSPSrc * src, GstEvent * event)
5061 {
5062   GList *streams;
5063   gboolean res = TRUE;
5064
5065   for (streams = src->streams; streams; streams = g_list_next (streams)) {
5066     GstRTSPStream *ostream = (GstRTSPStream *) streams->data;
5067
5068     gst_event_ref (event);
5069     res &= gst_rtspsrc_stream_push_event (src, ostream, event);
5070   }
5071   gst_event_unref (event);
5072
5073   return res;
5074 }
5075
5076 static gboolean
5077 accept_certificate_cb (GTlsConnection * conn, GTlsCertificate * peer_cert,
5078     GTlsCertificateFlags errors, gpointer user_data)
5079 {
5080   GstRTSPSrc *src = user_data;
5081   gboolean accept = FALSE;
5082
5083   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_ACCEPT_CERTIFICATE], 0, conn,
5084       peer_cert, errors, &accept);
5085
5086   return accept;
5087 }
5088
5089 static GstRTSPResult
5090 gst_rtsp_conninfo_connect (GstRTSPSrc * src, GstRTSPConnInfo * info,
5091     gboolean async)
5092 {
5093   GstRTSPResult res;
5094   GstRTSPMessage response;
5095   gboolean retry = FALSE;
5096   memset (&response, 0, sizeof (response));
5097   gst_rtsp_message_init (&response);
5098   do {
5099     if (info->connection == NULL) {
5100       if (info->url == NULL) {
5101         GST_DEBUG_OBJECT (src, "parsing uri (%s)...", info->location);
5102         if ((res = gst_rtsp_url_parse (info->location, &info->url)) < 0)
5103           goto parse_error;
5104       }
5105       /* create connection */
5106       GST_DEBUG_OBJECT (src, "creating connection (%s)...", info->location);
5107       if ((res = gst_rtsp_connection_create (info->url, &info->connection)) < 0)
5108         goto could_not_create;
5109
5110       if (retry) {
5111         gst_rtspsrc_setup_auth (src, &response);
5112       }
5113
5114       g_free (info->url_str);
5115       info->url_str = gst_rtsp_url_get_request_uri (info->url);
5116
5117       GST_DEBUG_OBJECT (src, "sanitized uri %s", info->url_str);
5118
5119       if (info->url->transports & GST_RTSP_LOWER_TRANS_TLS) {
5120         if (!gst_rtsp_connection_set_tls_validation_flags (info->connection,
5121                 src->tls_validation_flags))
5122           GST_WARNING_OBJECT (src, "Unable to set TLS validation flags");
5123
5124         if (src->tls_database)
5125           gst_rtsp_connection_set_tls_database (info->connection,
5126               src->tls_database);
5127
5128         if (src->tls_interaction)
5129           gst_rtsp_connection_set_tls_interaction (info->connection,
5130               src->tls_interaction);
5131         gst_rtsp_connection_set_accept_certificate_func (info->connection,
5132             accept_certificate_cb, src, NULL);
5133       }
5134
5135       if (info->url->transports & GST_RTSP_LOWER_TRANS_HTTP)
5136         gst_rtsp_connection_set_tunneled (info->connection, TRUE);
5137
5138       if (src->proxy_host) {
5139         GST_DEBUG_OBJECT (src, "setting proxy %s:%d", src->proxy_host,
5140             src->proxy_port);
5141         gst_rtsp_connection_set_proxy (info->connection, src->proxy_host,
5142             src->proxy_port);
5143       }
5144     }
5145
5146     if (!info->connected) {
5147       /* connect */
5148       if (async)
5149         GST_ELEMENT_PROGRESS (src, CONTINUE, "connect",
5150             ("Connecting to %s", info->location));
5151       GST_DEBUG_OBJECT (src, "connecting (%s)...", info->location);
5152       res = gst_rtsp_connection_connect_with_response (info->connection,
5153           src->ptcp_timeout, &response);
5154
5155       if (response.type == GST_RTSP_MESSAGE_HTTP_RESPONSE &&
5156           response.type_data.response.code == GST_RTSP_STS_UNAUTHORIZED) {
5157         gst_rtsp_conninfo_close (src, info, TRUE);
5158         if (!retry)
5159           retry = TRUE;
5160         else
5161           retry = FALSE;        // we should not retry more than once
5162       } else {
5163         retry = FALSE;
5164       }
5165
5166       if (res == GST_RTSP_OK)
5167         info->connected = TRUE;
5168       else if (!retry)
5169         goto could_not_connect;
5170     }
5171   } while (!info->connected && retry);
5172
5173   gst_rtsp_message_unset (&response);
5174   return GST_RTSP_OK;
5175
5176   /* ERRORS */
5177 parse_error:
5178   {
5179     GST_ERROR_OBJECT (src, "No valid RTSP URL was provided");
5180     gst_rtsp_message_unset (&response);
5181     return res;
5182   }
5183 could_not_create:
5184   {
5185     gchar *str = gst_rtsp_strresult (res);
5186     GST_ERROR_OBJECT (src, "Could not create connection. (%s)", str);
5187     g_free (str);
5188     gst_rtsp_message_unset (&response);
5189     return res;
5190   }
5191 could_not_connect:
5192   {
5193     gchar *str = gst_rtsp_strresult (res);
5194     GST_ERROR_OBJECT (src, "Could not connect to server. (%s)", str);
5195     g_free (str);
5196     gst_rtsp_message_unset (&response);
5197     return res;
5198   }
5199 }
5200
5201 static GstRTSPResult
5202 gst_rtsp_conninfo_close (GstRTSPSrc * src, GstRTSPConnInfo * info,
5203     gboolean free)
5204 {
5205   GST_RTSP_STATE_LOCK (src);
5206   if (info->connected) {
5207     GST_DEBUG_OBJECT (src, "closing connection...");
5208     gst_rtsp_connection_close (info->connection);
5209     info->connected = FALSE;
5210   }
5211   if (free && info->connection) {
5212     /* free connection */
5213     GST_DEBUG_OBJECT (src, "freeing connection...");
5214     gst_rtsp_connection_free (info->connection);
5215     info->connection = NULL;
5216     info->flushing = FALSE;
5217   }
5218   GST_RTSP_STATE_UNLOCK (src);
5219   return GST_RTSP_OK;
5220 }
5221
5222 static GstRTSPResult
5223 gst_rtsp_conninfo_reconnect (GstRTSPSrc * src, GstRTSPConnInfo * info,
5224     gboolean async)
5225 {
5226   GstRTSPResult res;
5227
5228   GST_DEBUG_OBJECT (src, "reconnecting connection...");
5229   gst_rtsp_conninfo_close (src, info, FALSE);
5230   res = gst_rtsp_conninfo_connect (src, info, async);
5231
5232   return res;
5233 }
5234
5235 static void
5236 gst_rtspsrc_connection_flush (GstRTSPSrc * src, gboolean flush)
5237 {
5238   GList *walk;
5239
5240   GST_DEBUG_OBJECT (src, "set flushing %d", flush);
5241   GST_RTSP_STATE_LOCK (src);
5242   if (src->conninfo.connection && src->conninfo.flushing != flush) {
5243     GST_DEBUG_OBJECT (src, "connection flush");
5244     gst_rtsp_connection_flush (src->conninfo.connection, flush);
5245     src->conninfo.flushing = flush;
5246   }
5247   for (walk = src->streams; walk; walk = g_list_next (walk)) {
5248     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
5249     if (stream->conninfo.connection && stream->conninfo.flushing != flush) {
5250       GST_DEBUG_OBJECT (src, "stream %p flush", stream);
5251       gst_rtsp_connection_flush (stream->conninfo.connection, flush);
5252       stream->conninfo.flushing = flush;
5253     }
5254   }
5255   GST_RTSP_STATE_UNLOCK (src);
5256 }
5257
5258 static GstRTSPResult
5259 gst_rtspsrc_init_request (GstRTSPSrc * src, GstRTSPMessage * msg,
5260     GstRTSPMethod method, const gchar * uri)
5261 {
5262   GstRTSPResult res;
5263
5264   res = gst_rtsp_message_init_request (msg, method, uri);
5265   if (res < 0)
5266     return res;
5267
5268   /* set user-agent */
5269   if (src->user_agent)
5270     gst_rtsp_message_add_header (msg, GST_RTSP_HDR_USER_AGENT, src->user_agent);
5271
5272   return res;
5273 }
5274
5275 /* FIXME, handle server request, reply with OK, for now */
5276 static GstRTSPResult
5277 gst_rtspsrc_handle_request (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
5278     GstRTSPMessage * request)
5279 {
5280   GstRTSPMessage response = { 0 };
5281   GstRTSPResult res;
5282
5283   GST_DEBUG_OBJECT (src, "got server request message");
5284
5285   DEBUG_RTSP (src, request);
5286
5287   res = gst_rtsp_ext_list_receive_request (src->extensions, request);
5288
5289   if (res == GST_RTSP_ENOTIMPL) {
5290     /* default implementation, send OK */
5291     GST_DEBUG_OBJECT (src, "prepare OK reply");
5292     res =
5293         gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, "OK",
5294         request);
5295     if (res < 0)
5296       goto send_error;
5297
5298     /* let app parse and reply */
5299     g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_HANDLE_REQUEST],
5300         0, request, &response);
5301
5302     DEBUG_RTSP (src, &response);
5303
5304     res = gst_rtspsrc_connection_send (src, conninfo, &response, NULL);
5305     if (res < 0)
5306       goto send_error;
5307
5308     gst_rtsp_message_unset (&response);
5309   } else if (res == GST_RTSP_EEOF)
5310     return res;
5311
5312   return GST_RTSP_OK;
5313
5314   /* ERRORS */
5315 send_error:
5316   {
5317     gst_rtsp_message_unset (&response);
5318     return res;
5319   }
5320 }
5321
5322 /* send server keep-alive */
5323 static GstRTSPResult
5324 gst_rtspsrc_send_keep_alive (GstRTSPSrc * src)
5325 {
5326   GstRTSPMessage request = { 0 };
5327   GstRTSPResult res;
5328   GstRTSPMethod method;
5329   const gchar *control;
5330
5331   if (src->do_rtsp_keep_alive == FALSE) {
5332     GST_DEBUG_OBJECT (src, "do-rtsp-keep-alive is FALSE, not sending.");
5333     gst_rtsp_connection_reset_timeout (src->conninfo.connection);
5334     return GST_RTSP_OK;
5335   }
5336
5337   GST_DEBUG_OBJECT (src, "creating server keep-alive");
5338
5339   /* find a method to use for keep-alive */
5340   if (src->methods & GST_RTSP_GET_PARAMETER)
5341     method = GST_RTSP_GET_PARAMETER;
5342   else
5343     method = GST_RTSP_OPTIONS;
5344
5345   control = get_aggregate_control (src);
5346   if (control == NULL)
5347     goto no_control;
5348
5349   res = gst_rtspsrc_init_request (src, &request, method, control);
5350   if (res < 0)
5351     goto send_error;
5352
5353   request.type_data.request.version = src->version;
5354
5355   res = gst_rtspsrc_connection_send (src, &src->conninfo, &request, NULL);
5356   if (res < 0)
5357     goto send_error;
5358
5359   gst_rtsp_connection_reset_timeout (src->conninfo.connection);
5360   gst_rtsp_message_unset (&request);
5361
5362   return GST_RTSP_OK;
5363
5364   /* ERRORS */
5365 no_control:
5366   {
5367     GST_WARNING_OBJECT (src, "no control url to send keepalive");
5368     return GST_RTSP_OK;
5369   }
5370 send_error:
5371   {
5372     gchar *str = gst_rtsp_strresult (res);
5373
5374     gst_rtsp_message_unset (&request);
5375     GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
5376         ("Could not send keep-alive. (%s)", str));
5377     g_free (str);
5378     return res;
5379   }
5380 }
5381
5382 static GstFlowReturn
5383 gst_rtspsrc_handle_data (GstRTSPSrc * src, GstRTSPMessage * message)
5384 {
5385   GstFlowReturn ret = GST_FLOW_OK;
5386   gint channel;
5387   GstRTSPStream *stream;
5388   GstPad *outpad = NULL;
5389   guint8 *data;
5390   guint size;
5391   GstBuffer *buf;
5392   gboolean is_rtcp;
5393
5394   channel = message->type_data.data.channel;
5395
5396   stream = find_stream (src, &channel, (gpointer) find_stream_by_channel);
5397   if (!stream)
5398     goto unknown_stream;
5399
5400   if (channel == stream->channel[0]) {
5401     outpad = stream->channelpad[0];
5402     is_rtcp = FALSE;
5403   } else if (channel == stream->channel[1]) {
5404     outpad = stream->channelpad[1];
5405     is_rtcp = TRUE;
5406   } else {
5407     is_rtcp = FALSE;
5408   }
5409
5410   /* take a look at the body to figure out what we have */
5411   gst_rtsp_message_get_body (message, &data, &size);
5412   if (size < 2)
5413     goto invalid_length;
5414
5415   /* channels are not correct on some servers, do extra check */
5416   if (data[1] >= 200 && data[1] <= 204) {
5417     /* hmm RTCP message switch to the RTCP pad of the same stream. */
5418     outpad = stream->channelpad[1];
5419     is_rtcp = TRUE;
5420   }
5421
5422   /* we have no clue what this is, just ignore then. */
5423   if (outpad == NULL)
5424     goto unknown_stream;
5425
5426   /* take the message body for further processing */
5427   gst_rtsp_message_steal_body (message, &data, &size);
5428
5429   /* strip the trailing \0 */
5430   size -= 1;
5431
5432   buf = gst_buffer_new ();
5433   gst_buffer_append_memory (buf,
5434       gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
5435
5436   /* don't need message anymore */
5437   gst_rtsp_message_unset (message);
5438
5439   GST_DEBUG_OBJECT (src, "pushing data of size %d on channel %d", size,
5440       channel);
5441
5442   if (src->need_activate) {
5443     gchar *stream_id;
5444     GstEvent *event;
5445     GChecksum *cs;
5446     gchar *uri;
5447     GList *streams;
5448     guint group_id = gst_util_group_id_next ();
5449
5450     /* generate an SHA256 sum of the URI */
5451     cs = g_checksum_new (G_CHECKSUM_SHA256);
5452     uri = src->conninfo.location;
5453     g_checksum_update (cs, (const guchar *) uri, strlen (uri));
5454
5455     for (streams = src->streams; streams; streams = g_list_next (streams)) {
5456       GstRTSPStream *ostream = (GstRTSPStream *) streams->data;
5457       GstCaps *caps;
5458
5459       stream_id =
5460           g_strdup_printf ("%s/%d", g_checksum_get_string (cs), ostream->id);
5461       event = gst_event_new_stream_start (stream_id);
5462       gst_event_set_group_id (event, group_id);
5463
5464       g_free (stream_id);
5465       gst_rtspsrc_stream_push_event (src, ostream, event);
5466
5467       if ((caps = stream_get_caps_for_pt (ostream, ostream->default_pt))) {
5468         /* only streams that have a connection to the outside world */
5469         if (ostream->setup) {
5470           if (ostream->udpsrc[0]) {
5471             gst_element_send_event (ostream->udpsrc[0],
5472                 gst_event_new_caps (caps));
5473           } else if (ostream->channelpad[0]) {
5474             if (GST_PAD_IS_SRC (ostream->channelpad[0]))
5475               gst_pad_push_event (ostream->channelpad[0],
5476                   gst_event_new_caps (caps));
5477             else
5478               gst_pad_send_event (ostream->channelpad[0],
5479                   gst_event_new_caps (caps));
5480           }
5481           ostream->need_caps = FALSE;
5482
5483           if (ostream->profile == GST_RTSP_PROFILE_SAVP ||
5484               ostream->profile == GST_RTSP_PROFILE_SAVPF)
5485             caps = gst_caps_new_empty_simple ("application/x-srtcp");
5486           else
5487             caps = gst_caps_new_empty_simple ("application/x-rtcp");
5488
5489           if (ostream->udpsrc[1]) {
5490             gst_element_send_event (ostream->udpsrc[1],
5491                 gst_event_new_caps (caps));
5492           } else if (ostream->channelpad[1]) {
5493             if (GST_PAD_IS_SRC (ostream->channelpad[1]))
5494               gst_pad_push_event (ostream->channelpad[1],
5495                   gst_event_new_caps (caps));
5496             else
5497               gst_pad_send_event (ostream->channelpad[1],
5498                   gst_event_new_caps (caps));
5499           }
5500
5501           gst_caps_unref (caps);
5502         }
5503       }
5504     }
5505     g_checksum_free (cs);
5506
5507     gst_rtspsrc_activate_streams (src);
5508     src->need_activate = FALSE;
5509     src->need_segment = TRUE;
5510   }
5511
5512   if (src->base_time == -1) {
5513     /* Take current running_time. This timestamp will be put on
5514      * the first buffer of each stream because we are a live source and so we
5515      * timestamp with the running_time. When we are dealing with TCP, we also
5516      * only timestamp the first buffer (using the DISCONT flag) because a server
5517      * typically bursts data, for which we don't want to compensate by speeding
5518      * up the media. The other timestamps will be interpollated from this one
5519      * using the RTP timestamps. */
5520     GST_OBJECT_LOCK (src);
5521     if (GST_ELEMENT_CLOCK (src)) {
5522       GstClockTime now;
5523       GstClockTime base_time;
5524
5525       now = gst_clock_get_time (GST_ELEMENT_CLOCK (src));
5526       base_time = GST_ELEMENT_CAST (src)->base_time;
5527
5528       src->base_time = now - base_time;
5529
5530       GST_DEBUG_OBJECT (src, "first buffer at time %" GST_TIME_FORMAT ", base %"
5531           GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
5532     }
5533     GST_OBJECT_UNLOCK (src);
5534   }
5535
5536   /* If needed send a new segment, don't forget we are live and buffer are
5537    * timestamped with running time */
5538   if (src->need_segment) {
5539     GstSegment segment;
5540     src->need_segment = FALSE;
5541     gst_segment_init (&segment, GST_FORMAT_TIME);
5542     gst_rtspsrc_push_event (src, gst_event_new_segment (&segment));
5543   }
5544
5545   if (stream->need_caps) {
5546     GstCaps *caps;
5547
5548     if ((caps = stream_get_caps_for_pt (stream, stream->default_pt))) {
5549       /* only streams that have a connection to the outside world */
5550       if (stream->setup) {
5551         /* Only need to update the TCP caps here, UDP is already handled */
5552         if (stream->channelpad[0]) {
5553           if (GST_PAD_IS_SRC (stream->channelpad[0]))
5554             gst_pad_push_event (stream->channelpad[0],
5555                 gst_event_new_caps (caps));
5556           else
5557             gst_pad_send_event (stream->channelpad[0],
5558                 gst_event_new_caps (caps));
5559         }
5560         stream->need_caps = FALSE;
5561       }
5562     }
5563
5564     stream->need_caps = FALSE;
5565   }
5566
5567   if (stream->discont && !is_rtcp) {
5568     /* mark first RTP buffer as discont */
5569     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5570     stream->discont = FALSE;
5571     /* first buffer gets the timestamp, other buffers are not timestamped and
5572      * their presentation time will be interpollated from the rtp timestamps. */
5573     GST_DEBUG_OBJECT (src, "setting timestamp %" GST_TIME_FORMAT,
5574         GST_TIME_ARGS (src->base_time));
5575
5576     GST_BUFFER_TIMESTAMP (buf) = src->base_time;
5577   }
5578
5579   /* chain to the peer pad */
5580   if (GST_PAD_IS_SINK (outpad))
5581     ret = gst_pad_chain (outpad, buf);
5582   else
5583     ret = gst_pad_push (outpad, buf);
5584
5585   if (!is_rtcp) {
5586     /* combine all stream flows for the data transport */
5587     ret = gst_rtspsrc_combine_flows (src, stream, ret);
5588   }
5589   return ret;
5590
5591   /* ERRORS */
5592 unknown_stream:
5593   {
5594     GST_DEBUG_OBJECT (src, "unknown stream on channel %d, ignored", channel);
5595     gst_rtsp_message_unset (message);
5596     return GST_FLOW_OK;
5597   }
5598 invalid_length:
5599   {
5600     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5601         ("Short message received, ignoring."));
5602     gst_rtsp_message_unset (message);
5603     return GST_FLOW_OK;
5604   }
5605 }
5606
5607 static GstFlowReturn
5608 gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
5609 {
5610   GstRTSPMessage message = { 0 };
5611   GstRTSPResult res;
5612   GstFlowReturn ret = GST_FLOW_OK;
5613   GTimeVal tv_timeout;
5614
5615   while (TRUE) {
5616     /* get the next timeout interval */
5617     gst_rtsp_connection_next_timeout (src->conninfo.connection, &tv_timeout);
5618
5619     /* see if the timeout period expired */
5620     if ((tv_timeout.tv_sec | tv_timeout.tv_usec) == 0) {
5621       GST_DEBUG_OBJECT (src, "timout, sending keep-alive");
5622       /* send keep-alive, only act on interrupt, a warning will be posted for
5623        * other errors. */
5624       if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5625         goto interrupt;
5626       /* get new timeout */
5627       gst_rtsp_connection_next_timeout (src->conninfo.connection, &tv_timeout);
5628     }
5629
5630     GST_DEBUG_OBJECT (src, "doing receive with timeout %ld seconds, %ld usec",
5631         tv_timeout.tv_sec, tv_timeout.tv_usec);
5632
5633     /* protect the connection with the connection lock so that we can see when
5634      * we are finished doing server communication */
5635     res =
5636         gst_rtspsrc_connection_receive (src, &src->conninfo,
5637         &message, src->ptcp_timeout);
5638
5639     switch (res) {
5640       case GST_RTSP_OK:
5641         GST_DEBUG_OBJECT (src, "we received a server message");
5642         break;
5643       case GST_RTSP_EINTR:
5644         /* we got interrupted this means we need to stop */
5645         goto interrupt;
5646       case GST_RTSP_ETIMEOUT:
5647         /* no reply, send keep alive */
5648         GST_DEBUG_OBJECT (src, "timeout, sending keep-alive");
5649         if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5650           goto interrupt;
5651         continue;
5652       case GST_RTSP_EEOF:
5653         /* go EOS when the server closed the connection */
5654         goto server_eof;
5655       default:
5656         goto receive_error;
5657     }
5658
5659     switch (message.type) {
5660       case GST_RTSP_MESSAGE_REQUEST:
5661         /* server sends us a request message, handle it */
5662         res = gst_rtspsrc_handle_request (src, &src->conninfo, &message);
5663         if (res == GST_RTSP_EEOF)
5664           goto server_eof;
5665         else if (res < 0)
5666           goto handle_request_failed;
5667         break;
5668       case GST_RTSP_MESSAGE_RESPONSE:
5669         /* we ignore response messages */
5670         GST_DEBUG_OBJECT (src, "ignoring response message");
5671         DEBUG_RTSP (src, &message);
5672         break;
5673       case GST_RTSP_MESSAGE_DATA:
5674         GST_DEBUG_OBJECT (src, "got data message");
5675         ret = gst_rtspsrc_handle_data (src, &message);
5676         if (ret != GST_FLOW_OK)
5677           goto handle_data_failed;
5678         break;
5679       default:
5680         GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
5681             message.type);
5682         break;
5683     }
5684   }
5685   g_assert_not_reached ();
5686
5687   /* ERRORS */
5688 server_eof:
5689   {
5690     GST_DEBUG_OBJECT (src, "we got an eof from the server");
5691     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5692         ("The server closed the connection."));
5693     src->conninfo.connected = FALSE;
5694     gst_rtsp_message_unset (&message);
5695     return GST_FLOW_EOS;
5696   }
5697 interrupt:
5698   {
5699     gst_rtsp_message_unset (&message);
5700     GST_DEBUG_OBJECT (src, "got interrupted");
5701     return GST_FLOW_FLUSHING;
5702   }
5703 receive_error:
5704   {
5705     gchar *str = gst_rtsp_strresult (res);
5706
5707 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5708     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_SERVER,
5709         "Could not receive message.");
5710 #else
5711     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
5712         ("Could not receive message. (%s)", str));
5713 #endif
5714     g_free (str);
5715
5716     gst_rtsp_message_unset (&message);
5717     return GST_FLOW_ERROR;
5718   }
5719 handle_request_failed:
5720   {
5721     gchar *str = gst_rtsp_strresult (res);
5722
5723 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5724     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_SERVICE_UNAVAILABLE,
5725         "Could not handle server message.");
5726 #else
5727     GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
5728         ("Could not handle server message. (%s)", str));
5729 #endif
5730     g_free (str);
5731     gst_rtsp_message_unset (&message);
5732     return GST_FLOW_ERROR;
5733   }
5734 handle_data_failed:
5735   {
5736     GST_DEBUG_OBJECT (src, "could no handle data message");
5737     return ret;
5738   }
5739 }
5740
5741 static GstFlowReturn
5742 gst_rtspsrc_loop_udp (GstRTSPSrc * src)
5743 {
5744   GstRTSPResult res;
5745   GstRTSPMessage message = { 0 };
5746   gint retry = 0;
5747
5748   while (TRUE) {
5749     GTimeVal tv_timeout;
5750
5751     /* get the next timeout interval */
5752     gst_rtsp_connection_next_timeout (src->conninfo.connection, &tv_timeout);
5753
5754     GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds",
5755         (gint) tv_timeout.tv_sec);
5756
5757     gst_rtsp_message_unset (&message);
5758
5759     /* we should continue reading the TCP socket because the server might
5760      * send us requests. When the session timeout expires, we need to send a
5761      * keep-alive request to keep the session open. */
5762     res = gst_rtspsrc_connection_receive (src, &src->conninfo,
5763         &message, &tv_timeout);
5764
5765     switch (res) {
5766       case GST_RTSP_OK:
5767         GST_DEBUG_OBJECT (src, "we received a server message");
5768         break;
5769       case GST_RTSP_EINTR:
5770         /* we got interrupted, see what we have to do */
5771         goto interrupt;
5772       case GST_RTSP_ETIMEOUT:
5773         /* send keep-alive, ignore the result, a warning will be posted. */
5774         GST_DEBUG_OBJECT (src, "timeout, sending keep-alive");
5775         if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5776           goto interrupt;
5777         continue;
5778       case GST_RTSP_EEOF:
5779         /* server closed the connection. not very fatal for UDP, reconnect and
5780          * see what happens. */
5781         GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5782             ("The server closed the connection."));
5783         if (src->udp_reconnect) {
5784           if ((res =
5785                   gst_rtsp_conninfo_reconnect (src, &src->conninfo, FALSE)) < 0)
5786             goto connect_error;
5787         } else {
5788           goto server_eof;
5789         }
5790         continue;
5791       case GST_RTSP_ENET:
5792         GST_DEBUG_OBJECT (src, "An ethernet problem occured.");
5793       default:
5794         GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5795             ("Unhandled return value %d.", res));
5796         goto receive_error;
5797     }
5798
5799     switch (message.type) {
5800       case GST_RTSP_MESSAGE_REQUEST:
5801         /* server sends us a request message, handle it */
5802         res = gst_rtspsrc_handle_request (src, &src->conninfo, &message);
5803         if (res == GST_RTSP_EEOF)
5804           goto server_eof;
5805         else if (res < 0)
5806           goto handle_request_failed;
5807         break;
5808       case GST_RTSP_MESSAGE_RESPONSE:
5809         /* we ignore response and data messages */
5810         GST_DEBUG_OBJECT (src, "ignoring response message");
5811         DEBUG_RTSP (src, &message);
5812         if (message.type_data.response.code == GST_RTSP_STS_UNAUTHORIZED) {
5813           GST_DEBUG_OBJECT (src, "but is Unauthorized response ...");
5814           if (gst_rtspsrc_setup_auth (src, &message) && !(retry++)) {
5815             GST_DEBUG_OBJECT (src, "so retrying keep-alive");
5816             if ((res = gst_rtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
5817               goto interrupt;
5818           }
5819         } else {
5820           retry = 0;
5821         }
5822         break;
5823       case GST_RTSP_MESSAGE_DATA:
5824         /* we ignore response and data messages */
5825         GST_DEBUG_OBJECT (src, "ignoring data message");
5826         break;
5827       default:
5828         GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
5829             message.type);
5830         break;
5831     }
5832   }
5833   g_assert_not_reached ();
5834
5835   /* we get here when the connection got interrupted */
5836 interrupt:
5837   {
5838     gst_rtsp_message_unset (&message);
5839     GST_DEBUG_OBJECT (src, "got interrupted");
5840     return GST_FLOW_FLUSHING;
5841   }
5842 connect_error:
5843   {
5844     gchar *str = gst_rtsp_strresult (res);
5845     GstFlowReturn ret;
5846
5847     src->conninfo.connected = FALSE;
5848     if (res != GST_RTSP_EINTR) {
5849 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5850       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
5851           "Could not connect to server.");
5852 #else
5853       GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
5854           ("Could not connect to server. (%s)", str));
5855 #endif
5856       g_free (str);
5857       ret = GST_FLOW_ERROR;
5858     } else {
5859       ret = GST_FLOW_FLUSHING;
5860     }
5861     return ret;
5862   }
5863 receive_error:
5864   {
5865     gchar *str = gst_rtsp_strresult (res);
5866
5867 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5868     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_SERVER_DISCONNECTED,
5869         "Could not receive message.");
5870 #else
5871     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
5872         ("Could not receive message. (%s)", str));
5873 #endif
5874     g_free (str);
5875     return GST_FLOW_ERROR;
5876   }
5877 handle_request_failed:
5878   {
5879     gchar *str = gst_rtsp_strresult (res);
5880     GstFlowReturn ret;
5881
5882     gst_rtsp_message_unset (&message);
5883     if (res != GST_RTSP_EINTR) {
5884 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5885       gst_rtspsrc_post_error_message (src,
5886           GST_RTSPSRC_ERROR_SERVICE_UNAVAILABLE,
5887           "Could not handle server message.");
5888 #else
5889       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
5890           ("Could not handle server message. (%s)", str));
5891 #endif
5892       g_free (str);
5893       ret = GST_FLOW_ERROR;
5894     } else {
5895       ret = GST_FLOW_FLUSHING;
5896     }
5897     return ret;
5898   }
5899 server_eof:
5900   {
5901     GST_DEBUG_OBJECT (src, "we got an eof from the server");
5902     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5903         ("The server closed the connection."));
5904     src->conninfo.connected = FALSE;
5905     gst_rtsp_message_unset (&message);
5906     return GST_FLOW_EOS;
5907   }
5908 }
5909
5910 static GstRTSPResult
5911 gst_rtspsrc_reconnect (GstRTSPSrc * src, gboolean async)
5912 {
5913   GstRTSPResult res = GST_RTSP_OK;
5914   gboolean restart;
5915
5916   GST_DEBUG_OBJECT (src, "doing reconnect");
5917
5918   GST_OBJECT_LOCK (src);
5919   /* only restart when the pads were not yet activated, else we were
5920    * streaming over UDP */
5921   restart = src->need_activate;
5922   GST_OBJECT_UNLOCK (src);
5923
5924   /* no need to restart, we're done */
5925   if (!restart)
5926     goto done;
5927
5928   /* we can try only TCP now */
5929   src->cur_protocols = GST_RTSP_LOWER_TRANS_TCP;
5930
5931   /* close and cleanup our state */
5932   if ((res = gst_rtspsrc_close (src, async, FALSE)) < 0)
5933     goto done;
5934
5935   /* see if we have TCP left to try. Also don't try TCP when we were configured
5936    * with an SDP. */
5937   if (!(src->protocols & GST_RTSP_LOWER_TRANS_TCP) || src->from_sdp)
5938     goto no_protocols;
5939
5940   /* We post a warning message now to inform the user
5941    * that nothing happened. It's most likely a firewall thing. */
5942   GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
5943       ("Could not receive any UDP packets for %.4f seconds, maybe your "
5944           "firewall is blocking it. Retrying using a tcp connection.",
5945           gst_guint64_to_gdouble (src->udp_timeout) / 1000000.0));
5946
5947   /* open new connection using tcp */
5948   if (gst_rtspsrc_open (src, async) < 0)
5949     goto open_failed;
5950
5951   /* start playback */
5952   if (gst_rtspsrc_play (src, &src->segment, async, NULL) < 0)
5953     goto play_failed;
5954
5955 done:
5956   return res;
5957
5958   /* ERRORS */
5959 no_protocols:
5960   {
5961     src->cur_protocols = 0;
5962     /* no transport possible, post an error and stop */
5963 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
5964     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_TRANSPORT,
5965         "Could not receive any UDP packets for seconds, maybe your firewall is blocking it. No other protocols to try.");
5966 #else
5967     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
5968         ("Could not receive any UDP packets for %.4f seconds, maybe your "
5969             "firewall is blocking it. No other protocols to try.",
5970             gst_guint64_to_gdouble (src->udp_timeout) / 1000000.0));
5971 #endif
5972     return GST_RTSP_ERROR;
5973   }
5974 open_failed:
5975   {
5976     GST_DEBUG_OBJECT (src, "open failed");
5977     return GST_RTSP_OK;
5978   }
5979 play_failed:
5980   {
5981     GST_DEBUG_OBJECT (src, "play failed");
5982     return GST_RTSP_OK;
5983   }
5984 }
5985
5986 static void
5987 gst_rtspsrc_loop_start_cmd (GstRTSPSrc * src, gint cmd)
5988 {
5989   switch (cmd) {
5990     case CMD_OPEN:
5991       GST_ELEMENT_PROGRESS (src, START, "open", ("Opening Stream"));
5992       break;
5993     case CMD_PLAY:
5994       GST_ELEMENT_PROGRESS (src, START, "request", ("Sending PLAY request"));
5995       break;
5996     case CMD_PAUSE:
5997       GST_ELEMENT_PROGRESS (src, START, "request", ("Sending PAUSE request"));
5998       break;
5999     case CMD_GET_PARAMETER:
6000       GST_ELEMENT_PROGRESS (src, START, "request",
6001           ("Sending GET_PARAMETER request"));
6002       break;
6003     case CMD_SET_PARAMETER:
6004       GST_ELEMENT_PROGRESS (src, START, "request",
6005           ("Sending SET_PARAMETER request"));
6006       break;
6007     case CMD_CLOSE:
6008       GST_ELEMENT_PROGRESS (src, START, "close", ("Closing Stream"));
6009       break;
6010     default:
6011       break;
6012   }
6013 }
6014
6015 static void
6016 gst_rtspsrc_loop_complete_cmd (GstRTSPSrc * src, gint cmd)
6017 {
6018 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6019   GstMessage *s;
6020   GST_WARNING_OBJECT (src, "Got cmd %s", cmd_to_string (cmd));
6021 #endif
6022
6023   switch (cmd) {
6024     case CMD_OPEN:
6025 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6026       GST_DEBUG_OBJECT (src,
6027           "rtsp_duration %" GST_TIME_FORMAT
6028           ", rtsp_audio_codec %s , rtsp_video_codec %s , rtsp_video_frame_size %s",
6029           GST_TIME_ARGS (src->segment.duration), src->audio_codec,
6030           src->video_codec, src->video_frame_size);
6031
6032       /* post message */
6033       s = gst_message_new_element (GST_OBJECT_CAST (src),
6034           gst_structure_new ("rtspsrc_properties",
6035               "rtsp_duration", G_TYPE_UINT64, src->segment.duration,
6036               "rtsp_audio_codec", G_TYPE_STRING, src->audio_codec,
6037               "rtsp_video_codec", G_TYPE_STRING, src->video_codec,
6038               "rtsp_video_frame_size", G_TYPE_STRING, src->video_frame_size,
6039               NULL));
6040
6041       gst_element_post_message (GST_ELEMENT_CAST (src), s);
6042 #endif
6043       GST_ELEMENT_PROGRESS (src, COMPLETE, "open", ("Opened Stream"));
6044 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6045       /* rtspsrc PAUSE state should be here for parsing sdp before PAUSE state changed. */
6046       g_mutex_lock (&(src)->pause_lock);
6047       g_cond_signal (&(src)->open_end);
6048       g_mutex_unlock (&(src)->pause_lock);
6049 #endif
6050       break;
6051     case CMD_PLAY:
6052       GST_ELEMENT_PROGRESS (src, COMPLETE, "request", ("Sent PLAY request"));
6053       break;
6054     case CMD_PAUSE:
6055       GST_ELEMENT_PROGRESS (src, COMPLETE, "request", ("Sent PAUSE request"));
6056       break;
6057     case CMD_GET_PARAMETER:
6058       GST_ELEMENT_PROGRESS (src, COMPLETE, "request",
6059           ("Sent GET_PARAMETER request"));
6060       break;
6061     case CMD_SET_PARAMETER:
6062       GST_ELEMENT_PROGRESS (src, COMPLETE, "request",
6063           ("Sent SET_PARAMETER request"));
6064       break;
6065     case CMD_CLOSE:
6066       GST_ELEMENT_PROGRESS (src, COMPLETE, "close", ("Closed Stream"));
6067       break;
6068     default:
6069       break;
6070   }
6071 }
6072
6073 static void
6074 gst_rtspsrc_loop_cancel_cmd (GstRTSPSrc * src, gint cmd)
6075 {
6076   switch (cmd) {
6077     case CMD_OPEN:
6078       GST_ELEMENT_PROGRESS (src, CANCELED, "open", ("Open canceled"));
6079       break;
6080     case CMD_PLAY:
6081       GST_ELEMENT_PROGRESS (src, CANCELED, "request", ("PLAY canceled"));
6082       break;
6083     case CMD_PAUSE:
6084       GST_ELEMENT_PROGRESS (src, CANCELED, "request", ("PAUSE canceled"));
6085       break;
6086     case CMD_GET_PARAMETER:
6087       GST_ELEMENT_PROGRESS (src, CANCELED, "request",
6088           ("GET_PARAMETER canceled"));
6089       break;
6090     case CMD_SET_PARAMETER:
6091       GST_ELEMENT_PROGRESS (src, CANCELED, "request",
6092           ("SET_PARAMETER canceled"));
6093       break;
6094     case CMD_CLOSE:
6095       GST_ELEMENT_PROGRESS (src, CANCELED, "close", ("Close canceled"));
6096       break;
6097     default:
6098       break;
6099   }
6100 }
6101
6102 static void
6103 gst_rtspsrc_loop_error_cmd (GstRTSPSrc * src, gint cmd)
6104 {
6105   switch (cmd) {
6106     case CMD_OPEN:
6107       GST_ELEMENT_PROGRESS (src, ERROR, "open", ("Open failed"));
6108 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6109       /* Ending conditional wait for pause when open fails.*/
6110       g_mutex_lock (&(src)->pause_lock);
6111       g_cond_signal (&(src)->open_end);
6112       g_mutex_unlock (&(src)->pause_lock);
6113       GST_WARNING_OBJECT (src,
6114           "ending conditional wait for pause as open is failed.");
6115 #endif
6116       break;
6117     case CMD_PLAY:
6118       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("PLAY failed"));
6119       break;
6120     case CMD_PAUSE:
6121       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("PAUSE failed"));
6122       break;
6123     case CMD_GET_PARAMETER:
6124       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("GET_PARAMETER failed"));
6125       break;
6126     case CMD_SET_PARAMETER:
6127       GST_ELEMENT_PROGRESS (src, ERROR, "request", ("SET_PARAMETER failed"));
6128       break;
6129     case CMD_CLOSE:
6130       GST_ELEMENT_PROGRESS (src, ERROR, "close", ("Close failed"));
6131       break;
6132     default:
6133       break;
6134   }
6135 }
6136
6137 static void
6138 gst_rtspsrc_loop_end_cmd (GstRTSPSrc * src, gint cmd, GstRTSPResult ret)
6139 {
6140   if (ret == GST_RTSP_OK)
6141     gst_rtspsrc_loop_complete_cmd (src, cmd);
6142   else if (ret == GST_RTSP_EINTR)
6143     gst_rtspsrc_loop_cancel_cmd (src, cmd);
6144   else
6145     gst_rtspsrc_loop_error_cmd (src, cmd);
6146 }
6147
6148 static gboolean
6149 gst_rtspsrc_loop_send_cmd (GstRTSPSrc * src, gint cmd, gint mask)
6150 {
6151   gint old;
6152   gboolean flushed = FALSE;
6153
6154   /* start new request */
6155   gst_rtspsrc_loop_start_cmd (src, cmd);
6156
6157   GST_DEBUG_OBJECT (src, "sending cmd %s", cmd_to_string (cmd));
6158
6159   GST_OBJECT_LOCK (src);
6160   old = src->pending_cmd;
6161
6162   if (old == CMD_RECONNECT) {
6163     GST_DEBUG_OBJECT (src, "ignore, we were reconnecting");
6164     cmd = CMD_RECONNECT;
6165   } else if (old == CMD_CLOSE) {
6166     /* our CMD_CLOSE might have interrutped CMD_LOOP. gst_rtspsrc_loop
6167      * will send a CMD_WAIT which would cancel our pending CMD_CLOSE (if
6168      * still pending). We just avoid it here by making sure CMD_CLOSE is
6169      * still the pending command. */
6170     GST_DEBUG_OBJECT (src, "ignore, we were closing");
6171     cmd = CMD_CLOSE;
6172   } else if (old == CMD_SET_PARAMETER) {
6173     GST_DEBUG_OBJECT (src, "ignore, we have a pending %s", cmd_to_string (old));
6174     cmd = CMD_SET_PARAMETER;
6175   } else if (old == CMD_GET_PARAMETER) {
6176     GST_DEBUG_OBJECT (src, "ignore, we have a pending %s", cmd_to_string (old));
6177     cmd = CMD_GET_PARAMETER;
6178   } else if (old != CMD_WAIT) {
6179     src->pending_cmd = CMD_WAIT;
6180     GST_OBJECT_UNLOCK (src);
6181     /* cancel previous request */
6182     GST_DEBUG_OBJECT (src, "cancel previous request %s", cmd_to_string (old));
6183     gst_rtspsrc_loop_cancel_cmd (src, old);
6184     GST_OBJECT_LOCK (src);
6185   }
6186   src->pending_cmd = cmd;
6187   /* interrupt if allowed */
6188   if (src->busy_cmd & mask) {
6189     GST_DEBUG_OBJECT (src, "connection flush busy %s",
6190         cmd_to_string (src->busy_cmd));
6191     gst_rtspsrc_connection_flush (src, TRUE);
6192     flushed = TRUE;
6193   } else {
6194     GST_DEBUG_OBJECT (src, "not interrupting busy cmd %s",
6195         cmd_to_string (src->busy_cmd));
6196   }
6197   if (src->task)
6198     gst_task_start (src->task);
6199   GST_OBJECT_UNLOCK (src);
6200
6201   return flushed;
6202 }
6203
6204 static gboolean
6205 gst_rtspsrc_loop_send_cmd_and_wait (GstRTSPSrc * src, gint cmd, gint mask,
6206     GstClockTime timeout)
6207 {
6208   gboolean flushed = gst_rtspsrc_loop_send_cmd (src, cmd, mask);
6209
6210   if (timeout > 0) {
6211     gint64 end_time = g_get_monotonic_time () + (timeout / 1000);
6212     GST_OBJECT_LOCK (src);
6213     while (src->pending_cmd == cmd || src->busy_cmd == cmd) {
6214       if (!g_cond_wait_until (&src->cmd_cond, GST_OBJECT_GET_LOCK (src),
6215               end_time)) {
6216         GST_WARNING_OBJECT (src,
6217             "Timed out waiting for TEARDOWN to be processed.");
6218         break;                  /* timeout passed */
6219       }
6220     }
6221     GST_OBJECT_UNLOCK (src);
6222   }
6223   return flushed;
6224 }
6225
6226 static gboolean
6227 gst_rtspsrc_loop (GstRTSPSrc * src)
6228 {
6229   GstFlowReturn ret;
6230
6231   if (!src->conninfo.connection || !src->conninfo.connected)
6232     goto no_connection;
6233
6234   if (src->interleaved)
6235     ret = gst_rtspsrc_loop_interleaved (src);
6236   else
6237     ret = gst_rtspsrc_loop_udp (src);
6238
6239   if (ret != GST_FLOW_OK)
6240     goto pause;
6241
6242   return TRUE;
6243
6244   /* ERRORS */
6245 no_connection:
6246   {
6247     GST_WARNING_OBJECT (src, "we are not connected");
6248     ret = GST_FLOW_FLUSHING;
6249     goto pause;
6250   }
6251 pause:
6252   {
6253     const gchar *reason = gst_flow_get_name (ret);
6254
6255     GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
6256     src->running = FALSE;
6257     if (ret == GST_FLOW_EOS) {
6258       /* perform EOS logic */
6259       if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6260         gst_element_post_message (GST_ELEMENT_CAST (src),
6261             gst_message_new_segment_done (GST_OBJECT_CAST (src),
6262                 src->segment.format, src->segment.position));
6263         gst_rtspsrc_push_event (src,
6264             gst_event_new_segment_done (src->segment.format,
6265                 src->segment.position));
6266       } else {
6267         gst_rtspsrc_push_event (src, gst_event_new_eos ());
6268       }
6269     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6270       /* for fatal errors we post an error message, post the error before the
6271        * EOS so the app knows about the error first. */
6272       GST_ELEMENT_FLOW_ERROR (src, ret);
6273       gst_rtspsrc_push_event (src, gst_event_new_eos ());
6274     }
6275     gst_rtspsrc_loop_send_cmd (src, CMD_WAIT, CMD_LOOP);
6276     return FALSE;
6277   }
6278 }
6279
6280 #ifndef GST_DISABLE_GST_DEBUG
6281 static const gchar *
6282 gst_rtsp_auth_method_to_string (GstRTSPAuthMethod method)
6283 {
6284   gint index = 0;
6285
6286   while (method != 0) {
6287     index++;
6288     method >>= 1;
6289   }
6290   switch (index) {
6291     case 0:
6292       return "None";
6293     case 1:
6294       return "Basic";
6295     case 2:
6296       return "Digest";
6297   }
6298
6299   return "Unknown";
6300 }
6301 #endif
6302
6303 /* Parse a WWW-Authenticate Response header and determine the
6304  * available authentication methods
6305  *
6306  * This code should also cope with the fact that each WWW-Authenticate
6307  * header can contain multiple challenge methods + tokens
6308  *
6309  * At the moment, for Basic auth, we just do a minimal check and don't
6310  * even parse out the realm */
6311 static void
6312 gst_rtspsrc_parse_auth_hdr (GstRTSPMessage * response,
6313     GstRTSPAuthMethod * methods, GstRTSPConnection * conn, gboolean * stale)
6314 {
6315   GstRTSPAuthCredential **credentials, **credential;
6316
6317   g_return_if_fail (response != NULL);
6318   g_return_if_fail (methods != NULL);
6319   g_return_if_fail (stale != NULL);
6320
6321   credentials =
6322       gst_rtsp_message_parse_auth_credentials (response,
6323       GST_RTSP_HDR_WWW_AUTHENTICATE);
6324   if (!credentials)
6325     return;
6326
6327   credential = credentials;
6328   while (*credential) {
6329     if ((*credential)->scheme == GST_RTSP_AUTH_BASIC) {
6330       *methods |= GST_RTSP_AUTH_BASIC;
6331     } else if ((*credential)->scheme == GST_RTSP_AUTH_DIGEST) {
6332       GstRTSPAuthParam **param = (*credential)->params;
6333
6334       *methods |= GST_RTSP_AUTH_DIGEST;
6335
6336       gst_rtsp_connection_clear_auth_params (conn);
6337       *stale = FALSE;
6338
6339       while (*param) {
6340         if (strcmp ((*param)->name, "stale") == 0
6341             && g_ascii_strcasecmp ((*param)->value, "TRUE") == 0)
6342           *stale = TRUE;
6343         gst_rtsp_connection_set_auth_param (conn, (*param)->name,
6344             (*param)->value);
6345         param++;
6346       }
6347     }
6348
6349     credential++;
6350   }
6351
6352   gst_rtsp_auth_credentials_free (credentials);
6353 }
6354
6355 /**
6356  * gst_rtspsrc_setup_auth:
6357  * @src: the rtsp source
6358  *
6359  * Configure a username and password and auth method on the
6360  * connection object based on a response we received from the
6361  * peer.
6362  *
6363  * Currently, this requires that a username and password were supplied
6364  * in the uri. In the future, they may be requested on demand by sending
6365  * a message up the bus.
6366  *
6367  * Returns: TRUE if authentication information could be set up correctly.
6368  */
6369 static gboolean
6370 gst_rtspsrc_setup_auth (GstRTSPSrc * src, GstRTSPMessage * response)
6371 {
6372   gchar *user = NULL;
6373   gchar *pass = NULL;
6374   GstRTSPAuthMethod avail_methods = GST_RTSP_AUTH_NONE;
6375   GstRTSPAuthMethod method;
6376   GstRTSPResult auth_result;
6377   GstRTSPUrl *url;
6378   GstRTSPConnection *conn;
6379   gboolean stale = FALSE;
6380
6381   conn = src->conninfo.connection;
6382
6383   /* Identify the available auth methods and see if any are supported */
6384   gst_rtspsrc_parse_auth_hdr (response, &avail_methods, conn, &stale);
6385
6386   if (avail_methods == GST_RTSP_AUTH_NONE)
6387     goto no_auth_available;
6388
6389   /* For digest auth, if the response indicates that the session
6390    * data are stale, we just update them in the connection object and
6391    * return TRUE to retry the request */
6392   if (stale)
6393     src->tried_url_auth = FALSE;
6394
6395   url = gst_rtsp_connection_get_url (conn);
6396
6397   /* Do we have username and password available? */
6398   if (url != NULL && !src->tried_url_auth && url->user != NULL
6399       && url->passwd != NULL) {
6400     user = url->user;
6401     pass = url->passwd;
6402     src->tried_url_auth = TRUE;
6403     GST_DEBUG_OBJECT (src,
6404         "Attempting authentication using credentials from the URL");
6405   } else {
6406     user = src->user_id;
6407     pass = src->user_pw;
6408     GST_DEBUG_OBJECT (src,
6409         "Attempting authentication using credentials from the properties");
6410   }
6411
6412   /* FIXME: If the url didn't contain username and password or we tried them
6413    * already, request a username and passwd from the application via some kind
6414    * of credentials request message */
6415
6416   /* If we don't have a username and passwd at this point, bail out. */
6417   if (user == NULL || pass == NULL)
6418     goto no_user_pass;
6419
6420   /* Try to configure for each available authentication method, strongest to
6421    * weakest */
6422   for (method = GST_RTSP_AUTH_MAX; method != GST_RTSP_AUTH_NONE; method >>= 1) {
6423     /* Check if this method is available on the server */
6424     if ((method & avail_methods) == 0)
6425       continue;
6426
6427     /* Pass the credentials to the connection to try on the next request */
6428     auth_result = gst_rtsp_connection_set_auth (conn, method, user, pass);
6429     /* INVAL indicates an invalid username/passwd were supplied, so we'll just
6430      * ignore it and end up retrying later */
6431     if (auth_result == GST_RTSP_OK || auth_result == GST_RTSP_EINVAL) {
6432       GST_DEBUG_OBJECT (src, "Attempting %s authentication",
6433           gst_rtsp_auth_method_to_string (method));
6434       break;
6435     }
6436   }
6437
6438   if (method == GST_RTSP_AUTH_NONE)
6439     goto no_auth_available;
6440
6441   return TRUE;
6442
6443 no_auth_available:
6444   {
6445     /* Output an error indicating that we couldn't connect because there were
6446      * no supported authentication protocols */
6447 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6448     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_NOT_AUTHORIZED,
6449         "No supported authentication protocol was found");
6450 #else
6451     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
6452         ("No supported authentication protocol was found"));
6453 #endif
6454     return FALSE;
6455   }
6456 no_user_pass:
6457   {
6458     /* We don't fire an error message, we just return FALSE and let the
6459      * normal NOT_AUTHORIZED error be propagated */
6460     return FALSE;
6461   }
6462 }
6463
6464 static GstRTSPResult
6465 gst_rtsp_src_receive_response (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
6466     GstRTSPMessage * response, GstRTSPStatusCode * code)
6467 {
6468   GstRTSPStatusCode thecode;
6469   gchar *content_base = NULL;
6470   GstRTSPResult res = gst_rtspsrc_connection_receive (src, conninfo,
6471       response, src->ptcp_timeout);
6472
6473   if (res < 0)
6474     goto receive_error;
6475
6476   DEBUG_RTSP (src, response);
6477
6478   switch (response->type) {
6479     case GST_RTSP_MESSAGE_REQUEST:
6480       res = gst_rtspsrc_handle_request (src, conninfo, response);
6481       if (res == GST_RTSP_EEOF)
6482         goto server_eof;
6483       else if (res < 0)
6484         goto handle_request_failed;
6485
6486       /* Not a response, receive next message */
6487       return gst_rtsp_src_receive_response (src, conninfo, response, code);
6488     case GST_RTSP_MESSAGE_RESPONSE:
6489       /* ok, a response is good */
6490       GST_DEBUG_OBJECT (src, "received response message");
6491       break;
6492     case GST_RTSP_MESSAGE_DATA:
6493       /* get next response */
6494       GST_DEBUG_OBJECT (src, "handle data response message");
6495       gst_rtspsrc_handle_data (src, response);
6496
6497       /* Not a response, receive next message */
6498       return gst_rtsp_src_receive_response (src, conninfo, response, code);
6499     default:
6500       GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
6501           response->type);
6502
6503       /* Not a response, receive next message */
6504       return gst_rtsp_src_receive_response (src, conninfo, response, code);
6505   }
6506
6507   thecode = response->type_data.response.code;
6508
6509   GST_DEBUG_OBJECT (src, "got response message %d", thecode);
6510
6511   /* if the caller wanted the result code, we store it. */
6512   if (code)
6513     *code = thecode;
6514
6515   /* If the request didn't succeed, bail out before doing any more */
6516   if (thecode != GST_RTSP_STS_OK)
6517     return GST_RTSP_OK;
6518
6519   /* store new content base if any */
6520   gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_BASE,
6521       &content_base, 0);
6522   if (content_base) {
6523     g_free (src->content_base);
6524     src->content_base = g_strdup (content_base);
6525   }
6526
6527   return GST_RTSP_OK;
6528
6529   /* ERRORS */
6530 receive_error:
6531   {
6532     switch (res) {
6533       case GST_RTSP_EEOF:
6534         return GST_RTSP_EEOF;
6535       default:
6536       {
6537         gchar *str = gst_rtsp_strresult (res);
6538
6539         if (res != GST_RTSP_EINTR) {
6540 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6541           gst_rtspsrc_post_error_message (src,
6542               GST_RTSPSRC_ERROR_SERVER_DISCONNECTED,
6543               "Could not receive message.");
6544 #else
6545           GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
6546               ("Could not receive message. (%s)", str));
6547 #endif
6548         } else {
6549           GST_WARNING_OBJECT (src, "receive interrupted");
6550         }
6551         g_free (str);
6552         break;
6553       }
6554     }
6555     return res;
6556   }
6557 handle_request_failed:
6558   {
6559     /* ERROR was posted */
6560     gst_rtsp_message_unset (response);
6561     return res;
6562   }
6563 server_eof:
6564   {
6565     GST_DEBUG_OBJECT (src, "we got an eof from the server");
6566     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
6567         ("The server closed the connection."));
6568     gst_rtsp_message_unset (response);
6569     return res;
6570   }
6571 }
6572
6573
6574 static GstRTSPResult
6575 gst_rtspsrc_try_send (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
6576     GstRTSPMessage * request, GstRTSPMessage * response,
6577     GstRTSPStatusCode * code)
6578 {
6579   GstRTSPResult res;
6580   gint try = 0;
6581   gboolean allow_send = TRUE;
6582
6583 again:
6584   if (!src->short_header)
6585     gst_rtsp_ext_list_before_send (src->extensions, request);
6586
6587   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_BEFORE_SEND], 0,
6588       request, &allow_send);
6589   if (!allow_send) {
6590     GST_DEBUG_OBJECT (src, "skipping message, disabled by signal");
6591     return GST_RTSP_OK;
6592   }
6593
6594   GST_DEBUG_OBJECT (src, "sending message");
6595
6596   DEBUG_RTSP (src, request);
6597
6598   res = gst_rtspsrc_connection_send (src, conninfo, request, src->ptcp_timeout);
6599   if (res < 0)
6600     goto send_error;
6601
6602   gst_rtsp_connection_reset_timeout (conninfo->connection);
6603   if (!response)
6604     return res;
6605
6606   res = gst_rtsp_src_receive_response (src, conninfo, response, code);
6607   if (res == GST_RTSP_EEOF) {
6608     GST_WARNING_OBJECT (src, "server closed connection");
6609     /* only try once after reconnect, then fallthrough and error out */
6610     if ((try == 0) && !src->interleaved && src->udp_reconnect) {
6611       try++;
6612       /* if reconnect succeeds, try again */
6613       if ((res = gst_rtsp_conninfo_reconnect (src, &src->conninfo, FALSE)) == 0)
6614         goto again;
6615     }
6616   }
6617   gst_rtsp_ext_list_after_send (src->extensions, request, response);
6618
6619   return res;
6620
6621 send_error:
6622   {
6623     gchar *str = gst_rtsp_strresult (res);
6624
6625     if (res != GST_RTSP_EINTR) {
6626 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6627       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
6628           "Could not send message.");
6629 #else
6630       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
6631           ("Could not send message. (%s)", str));
6632 #endif
6633     } else {
6634       GST_WARNING_OBJECT (src, "send interrupted");
6635     }
6636     g_free (str);
6637     return res;
6638   }
6639 }
6640
6641 /**
6642  * gst_rtspsrc_send:
6643  * @src: the rtsp source
6644  * @conninfo: the connection information to send on
6645  * @request: must point to a valid request
6646  * @response: must point to an empty #GstRTSPMessage
6647  * @code: an optional code result
6648  * @versions: List of versions to try, setting it back onto the @request message
6649  *            if not set, `src->version` will be used as RTSP version.
6650  *
6651  * send @request and retrieve the response in @response. optionally @code can be
6652  * non-NULL in which case it will contain the status code of the response.
6653  *
6654  * If This function returns #GST_RTSP_OK, @response will contain a valid response
6655  * message that should be cleaned with gst_rtsp_message_unset() after usage.
6656  *
6657  * If @code is NULL, this function will return #GST_RTSP_ERROR (with an invalid
6658  * @response message) if the response code was not 200 (OK).
6659  *
6660  * If the attempt results in an authentication failure, then this will attempt
6661  * to retrieve authentication credentials via gst_rtspsrc_setup_auth and retry
6662  * the request.
6663  *
6664  * Returns: #GST_RTSP_OK if the processing was successful.
6665  */
6666 static GstRTSPResult
6667 gst_rtspsrc_send (GstRTSPSrc * src, GstRTSPConnInfo * conninfo,
6668     GstRTSPMessage * request, GstRTSPMessage * response,
6669     GstRTSPStatusCode * code, GstRTSPVersion * versions)
6670 {
6671   GstRTSPStatusCode int_code = GST_RTSP_STS_OK;
6672   GstRTSPResult res = GST_RTSP_ERROR;
6673   gint count;
6674   gboolean retry;
6675   GstRTSPMethod method = GST_RTSP_INVALID;
6676   gint version_retry = 0;
6677
6678   count = 0;
6679   do {
6680     retry = FALSE;
6681
6682     /* make sure we don't loop forever */
6683     if (count++ > 8)
6684       break;
6685
6686     /* save method so we can disable it when the server complains */
6687     method = request->type_data.request.method;
6688
6689     if (!versions)
6690       request->type_data.request.version = src->version;
6691
6692     if ((res =
6693             gst_rtspsrc_try_send (src, conninfo, request, response,
6694                 &int_code)) < 0)
6695       goto error;
6696
6697     switch (int_code) {
6698       case GST_RTSP_STS_UNAUTHORIZED:
6699       case GST_RTSP_STS_NOT_FOUND:
6700         if (gst_rtspsrc_setup_auth (src, response)) {
6701           /* Try the request/response again after configuring the auth info
6702            * and loop again */
6703           retry = TRUE;
6704         }
6705         break;
6706       case GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED:
6707         GST_INFO_OBJECT (src, "Version %s not supported by the server",
6708             versions ? gst_rtsp_version_as_text (versions[version_retry]) :
6709             "unknown");
6710         if (versions && versions[version_retry] != GST_RTSP_VERSION_INVALID) {
6711           GST_INFO_OBJECT (src, "Unsupported version %s => trying %s",
6712               gst_rtsp_version_as_text (request->type_data.request.version),
6713               gst_rtsp_version_as_text (versions[version_retry]));
6714           request->type_data.request.version = versions[version_retry];
6715           retry = TRUE;
6716           version_retry++;
6717           break;
6718         }
6719         /* falltrough */
6720       default:
6721         break;
6722     }
6723   } while (retry == TRUE);
6724
6725   /* If the user requested the code, let them handle errors, otherwise
6726    * post an error below */
6727   if (code != NULL)
6728     *code = int_code;
6729   else if (int_code != GST_RTSP_STS_OK)
6730     goto error_response;
6731
6732   return res;
6733
6734   /* ERRORS */
6735 error:
6736   {
6737     GST_DEBUG_OBJECT (src, "got error %d", res);
6738     return res;
6739   }
6740 error_response:
6741   {
6742     res = GST_RTSP_ERROR;
6743
6744     switch (response->type_data.response.code) {
6745       case GST_RTSP_STS_NOT_FOUND:
6746 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6747         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
6748             "STS NOT FOUND");
6749 #else
6750         RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, NOT_FOUND,
6751             "Not found");
6752 #endif
6753         break;
6754       case GST_RTSP_STS_UNAUTHORIZED:
6755 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6756         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_NOT_AUTHORIZED,
6757             "STS NOT AUTHORIZED");
6758 #else
6759         RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, NOT_AUTHORIZED,
6760             "Unauthorized");
6761 #endif
6762         break;
6763       case GST_RTSP_STS_MOVED_PERMANENTLY:
6764       case GST_RTSP_STS_MOVE_TEMPORARILY:
6765       {
6766         gchar *new_location;
6767         GstRTSPLowerTrans transports;
6768
6769         GST_DEBUG_OBJECT (src, "got redirection");
6770         /* if we don't have a Location Header, we must error */
6771         if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_LOCATION,
6772                 &new_location, 0) < 0)
6773           break;
6774
6775         /* When we receive a redirect result, we go back to the INIT state after
6776          * parsing the new URI. The caller should do the needed steps to issue
6777          * a new setup when it detects this state change. */
6778         GST_DEBUG_OBJECT (src, "redirection to %s", new_location);
6779
6780         /* save current transports */
6781         if (src->conninfo.url)
6782           transports = src->conninfo.url->transports;
6783         else
6784           transports = GST_RTSP_LOWER_TRANS_UNKNOWN;
6785
6786         gst_rtspsrc_uri_set_uri (GST_URI_HANDLER (src), new_location, NULL);
6787
6788         /* set old transports */
6789         if (src->conninfo.url && transports != GST_RTSP_LOWER_TRANS_UNKNOWN)
6790           src->conninfo.url->transports = transports;
6791
6792         src->need_redirect = TRUE;
6793         res = GST_RTSP_OK;
6794         break;
6795       }
6796       case GST_RTSP_STS_NOT_ACCEPTABLE:
6797       case GST_RTSP_STS_NOT_IMPLEMENTED:
6798       case GST_RTSP_STS_METHOD_NOT_ALLOWED:
6799         GST_WARNING_OBJECT (src, "got NOT IMPLEMENTED, disable method %s",
6800             gst_rtsp_method_as_text (method));
6801         src->methods &= ~method;
6802         res = GST_RTSP_OK;
6803         break;
6804       default:
6805 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6806         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_UNEXPECTED_MSG,
6807             "Got error response from Server");
6808 #else
6809         RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, READ,
6810             "Unhandled error");
6811 #endif
6812         break;
6813     }
6814     /* if we return ERROR we should unset the response ourselves */
6815     if (res == GST_RTSP_ERROR)
6816       gst_rtsp_message_unset (response);
6817
6818     return res;
6819   }
6820 }
6821
6822 static GstRTSPResult
6823 gst_rtspsrc_send_cb (GstRTSPExtension * ext, GstRTSPMessage * request,
6824     GstRTSPMessage * response, GstRTSPSrc * src)
6825 {
6826   return gst_rtspsrc_send (src, &src->conninfo, request, response, NULL, NULL);
6827 }
6828
6829
6830 /* parse the response and collect all the supported methods. We need this
6831  * information so that we don't try to send an unsupported request to the
6832  * server.
6833  */
6834 static gboolean
6835 gst_rtspsrc_parse_methods (GstRTSPSrc * src, GstRTSPMessage * response)
6836 {
6837   GstRTSPHeaderField field;
6838   gchar *respoptions;
6839   gint indx = 0;
6840
6841   /* reset supported methods */
6842   src->methods = 0;
6843
6844   /* Try Allow Header first */
6845   field = GST_RTSP_HDR_ALLOW;
6846   while (TRUE) {
6847     respoptions = NULL;
6848     gst_rtsp_message_get_header (response, field, &respoptions, indx);
6849     if (!respoptions)
6850       break;
6851
6852     src->methods |= gst_rtsp_options_from_text (respoptions);
6853
6854     indx++;
6855   }
6856
6857   indx = 0;
6858   field = GST_RTSP_HDR_PUBLIC;
6859   while (TRUE) {
6860     respoptions = NULL;
6861     gst_rtsp_message_get_header (response, field, &respoptions, indx);
6862     if (!respoptions)
6863       break;
6864
6865     src->methods |= gst_rtsp_options_from_text (respoptions);
6866
6867     indx++;
6868   }
6869
6870   if (src->methods == 0) {
6871     /* neither Allow nor Public are required, assume the server supports
6872      * at least DESCRIBE, SETUP, we always assume it supports PLAY as
6873      * well. */
6874     GST_DEBUG_OBJECT (src, "could not get OPTIONS");
6875     src->methods = GST_RTSP_DESCRIBE | GST_RTSP_SETUP;
6876   }
6877   /* always assume PLAY, FIXME, extensions should be able to override
6878    * this */
6879   src->methods |= GST_RTSP_PLAY;
6880   /* also assume it will support Range */
6881   src->seekable = G_MAXFLOAT;
6882
6883   /* we need describe and setup */
6884   if (!(src->methods & GST_RTSP_DESCRIBE))
6885     goto no_describe;
6886   if (!(src->methods & GST_RTSP_SETUP))
6887     goto no_setup;
6888
6889   return TRUE;
6890
6891   /* ERRORS */
6892 no_describe:
6893   {
6894 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6895     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_METHOD_NOT_ALLOWED,
6896         "Server does not support DESCRIBE.");
6897 #else
6898     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
6899         ("Server does not support DESCRIBE."));
6900 #endif
6901     return FALSE;
6902   }
6903 no_setup:
6904   {
6905 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
6906     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_METHOD_NOT_ALLOWED,
6907         "Server does not support SETUP.");
6908 #else
6909     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
6910         ("Server does not support SETUP."));
6911 #endif
6912     return FALSE;
6913   }
6914 }
6915
6916 /* masks to be kept in sync with the hardcoded protocol order of preference
6917  * in code below */
6918 static const guint protocol_masks[] = {
6919   GST_RTSP_LOWER_TRANS_UDP,
6920   GST_RTSP_LOWER_TRANS_UDP_MCAST,
6921   GST_RTSP_LOWER_TRANS_TCP,
6922   0
6923 };
6924
6925 static GstRTSPResult
6926 gst_rtspsrc_create_transports_string (GstRTSPSrc * src,
6927     GstRTSPLowerTrans protocols, GstRTSPProfile profile, gchar ** transports)
6928 {
6929   GstRTSPResult res;
6930   GString *result;
6931   gboolean add_udp_str;
6932
6933   *transports = NULL;
6934
6935   res =
6936       gst_rtsp_ext_list_get_transports (src->extensions, protocols, transports);
6937
6938   if (res < 0)
6939     goto failed;
6940
6941   GST_DEBUG_OBJECT (src, "got transports %s", GST_STR_NULL (*transports));
6942
6943   /* extension listed transports, use those */
6944   if (*transports != NULL)
6945     return GST_RTSP_OK;
6946
6947   /* it's the default */
6948   add_udp_str = FALSE;
6949
6950   /* the default RTSP transports */
6951   result = g_string_new ("RTP");
6952
6953   switch (profile) {
6954     case GST_RTSP_PROFILE_AVP:
6955       g_string_append (result, "/AVP");
6956       break;
6957     case GST_RTSP_PROFILE_SAVP:
6958       g_string_append (result, "/SAVP");
6959       break;
6960     case GST_RTSP_PROFILE_AVPF:
6961       g_string_append (result, "/AVPF");
6962       break;
6963     case GST_RTSP_PROFILE_SAVPF:
6964       g_string_append (result, "/SAVPF");
6965       break;
6966     default:
6967       break;
6968   }
6969
6970   if (protocols & GST_RTSP_LOWER_TRANS_UDP) {
6971     GST_DEBUG_OBJECT (src, "adding UDP unicast");
6972     if (add_udp_str)
6973       g_string_append (result, "/UDP");
6974     g_string_append (result, ";unicast;client_port=%%u1-%%u2");
6975   } else if (protocols & GST_RTSP_LOWER_TRANS_UDP_MCAST) {
6976     GST_DEBUG_OBJECT (src, "adding UDP multicast");
6977     /* we don't have to allocate any UDP ports yet, if the selected transport
6978      * turns out to be multicast we can create them and join the multicast
6979      * group indicated in the transport reply */
6980     if (add_udp_str)
6981       g_string_append (result, "/UDP");
6982     g_string_append (result, ";multicast");
6983     if (src->next_port_num != 0) {
6984       if (src->client_port_range.max > 0 &&
6985           src->next_port_num >= src->client_port_range.max)
6986         goto no_ports;
6987
6988       g_string_append_printf (result, ";client_port=%d-%d",
6989           src->next_port_num, src->next_port_num + 1);
6990     }
6991   } else if (protocols & GST_RTSP_LOWER_TRANS_TCP) {
6992     GST_DEBUG_OBJECT (src, "adding TCP");
6993
6994     g_string_append (result, "/TCP;unicast;interleaved=%%i1-%%i2");
6995   }
6996   *transports = g_string_free (result, FALSE);
6997
6998   GST_DEBUG_OBJECT (src, "prepared transports %s", GST_STR_NULL (*transports));
6999
7000   return GST_RTSP_OK;
7001
7002   /* ERRORS */
7003 failed:
7004   {
7005     GST_ERROR ("extension gave error %d", res);
7006     return res;
7007   }
7008 no_ports:
7009   {
7010     GST_ERROR ("no more ports available");
7011     return GST_RTSP_ERROR;
7012   }
7013 }
7014
7015 static GstRTSPResult
7016 gst_rtspsrc_prepare_transports (GstRTSPStream * stream, gchar ** transports,
7017     gint orig_rtpport, gint orig_rtcpport)
7018 {
7019   GstRTSPSrc *src;
7020   gint nr_udp, nr_int;
7021   gchar *next, *p;
7022   gint rtpport = 0, rtcpport = 0;
7023   GString *str;
7024
7025   src = stream->parent;
7026
7027   /* find number of placeholders first */
7028   if (strstr (*transports, "%%i2"))
7029     nr_int = 2;
7030   else if (strstr (*transports, "%%i1"))
7031     nr_int = 1;
7032   else
7033     nr_int = 0;
7034
7035   if (strstr (*transports, "%%u2"))
7036     nr_udp = 2;
7037   else if (strstr (*transports, "%%u1"))
7038     nr_udp = 1;
7039   else
7040     nr_udp = 0;
7041
7042   if (nr_udp == 0 && nr_int == 0)
7043     goto done;
7044
7045   if (nr_udp > 0) {
7046     if (!orig_rtpport || !orig_rtcpport) {
7047       if (!gst_rtspsrc_alloc_udp_ports (stream, &rtpport, &rtcpport))
7048         goto failed;
7049     } else {
7050       rtpport = orig_rtpport;
7051       rtcpport = orig_rtcpport;
7052     }
7053   }
7054
7055   str = g_string_new ("");
7056   p = *transports;
7057   while ((next = strstr (p, "%%"))) {
7058     g_string_append_len (str, p, next - p);
7059     if (next[2] == 'u') {
7060       if (next[3] == '1')
7061         g_string_append_printf (str, "%d", rtpport);
7062       else if (next[3] == '2')
7063         g_string_append_printf (str, "%d", rtcpport);
7064     }
7065     if (next[2] == 'i') {
7066       if (next[3] == '1')
7067         g_string_append_printf (str, "%d", src->free_channel);
7068       else if (next[3] == '2')
7069         g_string_append_printf (str, "%d", src->free_channel + 1);
7070
7071     }
7072
7073     p = next + 4;
7074   }
7075   if (src->version >= GST_RTSP_VERSION_2_0)
7076     src->free_channel += 2;
7077
7078   /* append final part */
7079   g_string_append (str, p);
7080
7081   g_free (*transports);
7082   *transports = g_string_free (str, FALSE);
7083
7084 done:
7085   return GST_RTSP_OK;
7086
7087   /* ERRORS */
7088 failed:
7089   {
7090     GST_ERROR ("failed to allocate udp ports");
7091     return GST_RTSP_ERROR;
7092   }
7093 }
7094
7095 static GstCaps *
7096 signal_get_srtcp_params (GstRTSPSrc * src, GstRTSPStream * stream)
7097 {
7098   GstCaps *caps = NULL;
7099
7100   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_REQUEST_RTCP_KEY], 0,
7101       stream->id, &caps);
7102
7103   if (caps != NULL)
7104     GST_DEBUG_OBJECT (src, "SRTP parameters received");
7105
7106   return caps;
7107 }
7108
7109 static GstCaps *
7110 default_srtcp_params (void)
7111 {
7112   guint i;
7113   GstCaps *caps;
7114   GstBuffer *buf;
7115   guint8 *key_data;
7116 #define KEY_SIZE 30
7117   guint data_size = GST_ROUND_UP_4 (KEY_SIZE);
7118
7119   /* create a random key */
7120   key_data = g_malloc (data_size);
7121   for (i = 0; i < data_size; i += 4)
7122     GST_WRITE_UINT32_BE (key_data + i, g_random_int ());
7123
7124   buf = gst_buffer_new_wrapped (key_data, KEY_SIZE);
7125
7126   caps = gst_caps_new_simple ("application/x-srtcp",
7127       "srtp-key", GST_TYPE_BUFFER, buf,
7128       "srtp-cipher", G_TYPE_STRING, "aes-128-icm",
7129       "srtp-auth", G_TYPE_STRING, "hmac-sha1-80",
7130       "srtcp-cipher", G_TYPE_STRING, "aes-128-icm",
7131       "srtcp-auth", G_TYPE_STRING, "hmac-sha1-80", NULL);
7132
7133   gst_buffer_unref (buf);
7134
7135   return caps;
7136 }
7137
7138 static gchar *
7139 gst_rtspsrc_stream_make_keymgmt (GstRTSPSrc * src, GstRTSPStream * stream)
7140 {
7141   gchar *base64, *result = NULL;
7142   GstMIKEYMessage *mikey_msg;
7143
7144   stream->srtcpparams = signal_get_srtcp_params (src, stream);
7145   if (stream->srtcpparams == NULL)
7146     stream->srtcpparams = default_srtcp_params ();
7147
7148   mikey_msg = gst_mikey_message_new_from_caps (stream->srtcpparams);
7149   if (mikey_msg) {
7150     /* add policy '0' for our SSRC */
7151     gst_mikey_message_add_cs_srtp (mikey_msg, 0, stream->send_ssrc, 0);
7152
7153     base64 = gst_mikey_message_base64_encode (mikey_msg);
7154     gst_mikey_message_unref (mikey_msg);
7155
7156     if (base64) {
7157       result = gst_sdp_make_keymgmt (stream->conninfo.location, base64);
7158       g_free (base64);
7159     }
7160   }
7161
7162   return result;
7163 }
7164
7165 static GstRTSPResult
7166 gst_rtsp_src_setup_stream_from_response (GstRTSPSrc * src,
7167     GstRTSPStream * stream, GstRTSPMessage * response,
7168     GstRTSPLowerTrans * protocols, gint retry, gint * rtpport, gint * rtcpport)
7169 {
7170   gchar *resptrans = NULL;
7171   GstRTSPTransport transport = { 0 };
7172
7173   gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT, &resptrans, 0);
7174   if (!resptrans) {
7175     gst_rtspsrc_stream_free_udp (stream);
7176     goto no_transport;
7177   }
7178
7179   /* parse transport, go to next stream on parse error */
7180   if (gst_rtsp_transport_parse (resptrans, &transport) != GST_RTSP_OK) {
7181     GST_WARNING_OBJECT (src, "failed to parse transport %s", resptrans);
7182     return GST_RTSP_ELAST;
7183   }
7184
7185   /* update allowed transports for other streams. once the transport of
7186    * one stream has been determined, we make sure that all other streams
7187    * are configured in the same way */
7188   switch (transport.lower_transport) {
7189     case GST_RTSP_LOWER_TRANS_TCP:
7190       GST_DEBUG_OBJECT (src, "stream %p as TCP interleaved", stream);
7191       if (protocols)
7192         *protocols = GST_RTSP_LOWER_TRANS_TCP;
7193       src->interleaved = TRUE;
7194       if (src->version < GST_RTSP_VERSION_2_0) {
7195         /* update free channels */
7196         src->free_channel = MAX (transport.interleaved.min, src->free_channel);
7197         src->free_channel = MAX (transport.interleaved.max, src->free_channel);
7198         src->free_channel++;
7199       }
7200       break;
7201     case GST_RTSP_LOWER_TRANS_UDP_MCAST:
7202       /* only allow multicast for other streams */
7203       GST_DEBUG_OBJECT (src, "stream %p as UDP multicast", stream);
7204       if (protocols)
7205         *protocols = GST_RTSP_LOWER_TRANS_UDP_MCAST;
7206       /* if the server selected our ports, increment our counters so that
7207        * we select a new port later */
7208       if (src->next_port_num == transport.port.min &&
7209           src->next_port_num + 1 == transport.port.max) {
7210         src->next_port_num += 2;
7211       }
7212       break;
7213     case GST_RTSP_LOWER_TRANS_UDP:
7214       /* only allow unicast for other streams */
7215       GST_DEBUG_OBJECT (src, "stream %p as UDP unicast", stream);
7216       if (protocols)
7217         *protocols = GST_RTSP_LOWER_TRANS_UDP;
7218       break;
7219     default:
7220       GST_DEBUG_OBJECT (src, "stream %p unknown transport %d", stream,
7221           transport.lower_transport);
7222       break;
7223   }
7224
7225   if (!src->interleaved || !retry) {
7226     /* now configure the stream with the selected transport */
7227     if (!gst_rtspsrc_stream_configure_transport (stream, &transport)) {
7228       GST_DEBUG_OBJECT (src,
7229           "could not configure stream %p transport, skipping stream", stream);
7230       goto done;
7231     } else if (stream->udpsrc[0] && stream->udpsrc[1] && rtpport && rtcpport) {
7232       /* retain the first allocated UDP port pair */
7233       g_object_get (G_OBJECT (stream->udpsrc[0]), "port", rtpport, NULL);
7234       g_object_get (G_OBJECT (stream->udpsrc[1]), "port", rtcpport, NULL);
7235     }
7236   }
7237   /* we need to activate at least one stream when we detect activity */
7238   src->need_activate = TRUE;
7239
7240   /* stream is setup now */
7241   stream->setup = TRUE;
7242   stream->waiting_setup_response = FALSE;
7243
7244   if (src->version >= GST_RTSP_VERSION_2_0) {
7245     gchar *prop, *media_properties;
7246     gchar **props;
7247     gint i;
7248
7249     if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_MEDIA_PROPERTIES,
7250             &media_properties, 0) != GST_RTSP_OK) {
7251       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
7252           ("Error: No MEDIA_PROPERTY header in a SETUP request in RTSP 2.0"
7253               " - this header is mandatory."));
7254
7255       gst_rtsp_message_unset (response);
7256       return GST_RTSP_ERROR;
7257     }
7258
7259     props = g_strsplit (media_properties, ",", -2);
7260     for (i = 0; props[i]; i++) {
7261       prop = props[i];
7262
7263       while (*prop == ' ')
7264         prop++;
7265
7266       if (strstr (prop, "Random-Access")) {
7267         gchar **random_seekable_val = g_strsplit (prop, "=", 2);
7268
7269         if (!random_seekable_val[1])
7270           src->seekable = G_MAXFLOAT;
7271         else
7272           src->seekable = g_ascii_strtod (random_seekable_val[1], NULL);
7273
7274         g_strfreev (random_seekable_val);
7275       } else if (!g_strcmp0 (prop, "No-Seeking")) {
7276         src->seekable = -1.0;
7277       } else if (!g_strcmp0 (prop, "Beginning-Only")) {
7278         src->seekable = 0.0;
7279       }
7280     }
7281
7282     g_strfreev (props);
7283   }
7284
7285 done:
7286   /* clean up our transport struct */
7287   gst_rtsp_transport_init (&transport);
7288   /* clean up used RTSP messages */
7289   gst_rtsp_message_unset (response);
7290
7291   return GST_RTSP_OK;
7292
7293 no_transport:
7294   {
7295     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
7296         ("Server did not select transport."));
7297
7298     gst_rtsp_message_unset (response);
7299     return GST_RTSP_ERROR;
7300   }
7301 }
7302
7303 static GstRTSPResult
7304 gst_rtspsrc_setup_streams_end (GstRTSPSrc * src, gboolean async)
7305 {
7306   GList *tmp;
7307   GstRTSPConnInfo *conninfo;
7308
7309   g_assert (src->version >= GST_RTSP_VERSION_2_0);
7310
7311   conninfo = &src->conninfo;
7312   for (tmp = src->streams; tmp; tmp = tmp->next) {
7313     GstRTSPStream *stream = (GstRTSPStream *) tmp->data;
7314     GstRTSPMessage response = { 0, };
7315
7316     if (!stream->waiting_setup_response)
7317       continue;
7318
7319     if (!src->conninfo.connection)
7320       conninfo = &((GstRTSPStream *) tmp->data)->conninfo;
7321
7322     gst_rtsp_src_receive_response (src, conninfo, &response, NULL);
7323
7324     gst_rtsp_src_setup_stream_from_response (src, stream,
7325         &response, NULL, 0, NULL, NULL);
7326   }
7327
7328   return GST_RTSP_OK;
7329 }
7330
7331 /* Perform the SETUP request for all the streams.
7332  *
7333  * We ask the server for a specific transport, which initially includes all the
7334  * ones we can support (UDP/TCP/MULTICAST). For the UDP transport we allocate
7335  * two local UDP ports that we send to the server.
7336  *
7337  * Once the server replied with a transport, we configure the other streams
7338  * with the same transport.
7339  *
7340  * In case setup request are not pipelined, this function will also configure the
7341  * stream for the selected transport, * which basically means creating the pipeline.
7342  * Otherwise, the first stream is setup right away from the reply and a
7343  * CMD_FINALIZE_SETUP command is set for the stream pipelines to happen on the
7344  * remaining streams from the RTSP thread.
7345  */
7346 static GstRTSPResult
7347 gst_rtspsrc_setup_streams_start (GstRTSPSrc * src, gboolean async)
7348 {
7349   GList *walk;
7350   GstRTSPResult res = GST_RTSP_ERROR;
7351   GstRTSPMessage request = { 0 };
7352   GstRTSPMessage response = { 0 };
7353   GstRTSPStream *stream = NULL;
7354   GstRTSPLowerTrans protocols;
7355   GstRTSPStatusCode code;
7356   gboolean unsupported_real = FALSE;
7357   gint rtpport, rtcpport;
7358   GstRTSPUrl *url;
7359   gchar *hval;
7360   gchar *pipelined_request_id = NULL;
7361
7362   if (src->conninfo.connection) {
7363     url = gst_rtsp_connection_get_url (src->conninfo.connection);
7364     /* we initially allow all configured lower transports. based on the URL
7365      * transports and the replies from the server we narrow them down. */
7366     protocols = url->transports & src->cur_protocols;
7367   } else {
7368     url = NULL;
7369     protocols = src->cur_protocols;
7370   }
7371
7372   if (protocols == 0)
7373     goto no_protocols;
7374
7375   /* reset some state */
7376   src->free_channel = 0;
7377   src->interleaved = FALSE;
7378   src->need_activate = FALSE;
7379   /* keep track of next port number, 0 is random */
7380   src->next_port_num = src->client_port_range.min;
7381   rtpport = rtcpport = 0;
7382
7383   if (G_UNLIKELY (src->streams == NULL))
7384     goto no_streams;
7385
7386   for (walk = src->streams; walk; walk = g_list_next (walk)) {
7387     GstRTSPConnInfo *conninfo;
7388     gchar *transports;
7389     gint retry = 0;
7390     guint mask = 0;
7391     gboolean selected;
7392     GstCaps *caps;
7393
7394     stream = (GstRTSPStream *) walk->data;
7395
7396     caps = stream_get_caps_for_pt (stream, stream->default_pt);
7397     if (caps == NULL) {
7398       GST_WARNING_OBJECT (src, "skipping stream %p, no caps", stream);
7399       continue;
7400     }
7401
7402     if (stream->skipped) {
7403       GST_DEBUG_OBJECT (src, "skipping stream %p", stream);
7404       continue;
7405     }
7406
7407     /* see if we need to configure this stream */
7408     if (!gst_rtsp_ext_list_configure_stream (src->extensions, caps)) {
7409       GST_DEBUG_OBJECT (src, "skipping stream %p, disabled by extension",
7410           stream);
7411       continue;
7412     }
7413
7414     g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_SELECT_STREAM], 0,
7415         stream->id, caps, &selected);
7416     if (!selected) {
7417       GST_DEBUG_OBJECT (src, "skipping stream %p, disabled by signal", stream);
7418       continue;
7419     }
7420
7421     /* merge/overwrite global caps */
7422     if (caps) {
7423       guint j, num;
7424       GstStructure *s;
7425
7426       s = gst_caps_get_structure (caps, 0);
7427
7428       num = gst_structure_n_fields (src->props);
7429       for (j = 0; j < num; j++) {
7430         const gchar *name;
7431         const GValue *val;
7432
7433         name = gst_structure_nth_field_name (src->props, j);
7434         val = gst_structure_get_value (src->props, name);
7435         gst_structure_set_value (s, name, val);
7436
7437         GST_DEBUG_OBJECT (src, "copied %s", name);
7438       }
7439     }
7440
7441     /* skip setup if we have no URL for it */
7442     if (stream->conninfo.location == NULL) {
7443       GST_WARNING_OBJECT (src, "skipping stream %p, no setup", stream);
7444       continue;
7445     }
7446
7447     if (src->conninfo.connection == NULL) {
7448       if (!gst_rtsp_conninfo_connect (src, &stream->conninfo, async)) {
7449         GST_WARNING_OBJECT (src, "skipping stream %p, failed to connect",
7450             stream);
7451         continue;
7452       }
7453       conninfo = &stream->conninfo;
7454     } else {
7455       conninfo = &src->conninfo;
7456     }
7457     GST_DEBUG_OBJECT (src, "doing setup of stream %p with %s", stream,
7458         stream->conninfo.location);
7459
7460     /* if we have a multicast connection, only suggest multicast from now on */
7461     if (stream->is_multicast)
7462       protocols &= GST_RTSP_LOWER_TRANS_UDP_MCAST;
7463
7464   next_protocol:
7465     /* first selectable protocol */
7466     while (protocol_masks[mask] && !(protocols & protocol_masks[mask]))
7467       mask++;
7468     if (!protocol_masks[mask])
7469       goto no_protocols;
7470
7471   retry:
7472     GST_DEBUG_OBJECT (src, "protocols = 0x%x, protocol mask = 0x%x", protocols,
7473         protocol_masks[mask]);
7474     /* create a string with first transport in line */
7475     transports = NULL;
7476     res = gst_rtspsrc_create_transports_string (src,
7477         protocols & protocol_masks[mask], stream->profile, &transports);
7478     if (res < 0 || transports == NULL)
7479       goto setup_transport_failed;
7480
7481     if (strlen (transports) == 0) {
7482       g_free (transports);
7483       GST_DEBUG_OBJECT (src, "no transports found");
7484       mask++;
7485       goto next_protocol;
7486     }
7487
7488     GST_DEBUG_OBJECT (src, "replace ports in %s", GST_STR_NULL (transports));
7489
7490     /* replace placeholders with real values, this function will optionally
7491      * allocate UDP ports and other info needed to execute the setup request */
7492     res = gst_rtspsrc_prepare_transports (stream, &transports,
7493         retry > 0 ? rtpport : 0, retry > 0 ? rtcpport : 0);
7494     if (res < 0) {
7495       g_free (transports);
7496       goto setup_transport_failed;
7497     }
7498
7499     GST_DEBUG_OBJECT (src, "transport is now %s", GST_STR_NULL (transports));
7500     /* create SETUP request */
7501     res =
7502         gst_rtspsrc_init_request (src, &request, GST_RTSP_SETUP,
7503         stream->conninfo.location);
7504     if (res < 0) {
7505       g_free (transports);
7506       goto create_request_failed;
7507     }
7508
7509     if (src->version >= GST_RTSP_VERSION_2_0) {
7510       if (!pipelined_request_id)
7511         pipelined_request_id = g_strdup_printf ("%d",
7512             g_random_int_range (0, G_MAXINT32));
7513
7514       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_PIPELINED_REQUESTS,
7515           pipelined_request_id);
7516       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_ACCEPT_RANGES,
7517           "npt, clock, smpte, clock");
7518     }
7519
7520     /* select transport */
7521     gst_rtsp_message_take_header (&request, GST_RTSP_HDR_TRANSPORT, transports);
7522
7523     if (stream->is_backchannel && src->backchannel == BACKCHANNEL_ONVIF)
7524       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
7525           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
7526
7527     /* set up keys */
7528     if (stream->profile == GST_RTSP_PROFILE_SAVP ||
7529         stream->profile == GST_RTSP_PROFILE_SAVPF) {
7530       hval = gst_rtspsrc_stream_make_keymgmt (src, stream);
7531       gst_rtsp_message_take_header (&request, GST_RTSP_HDR_KEYMGMT, hval);
7532     }
7533
7534     /* if the user wants a non default RTP packet size we add the blocksize
7535      * parameter */
7536     if (src->rtp_blocksize > 0) {
7537       hval = g_strdup_printf ("%d", src->rtp_blocksize);
7538       gst_rtsp_message_take_header (&request, GST_RTSP_HDR_BLOCKSIZE, hval);
7539     }
7540
7541     if (async)
7542       GST_ELEMENT_PROGRESS (src, CONTINUE, "request", ("SETUP stream %d",
7543               stream->id));
7544
7545     /* handle the code ourselves */
7546     res =
7547         gst_rtspsrc_send (src, conninfo, &request,
7548         pipelined_request_id ? NULL : &response, &code, NULL);
7549     if (res < 0)
7550       goto send_error;
7551
7552     switch (code) {
7553       case GST_RTSP_STS_OK:
7554         break;
7555       case GST_RTSP_STS_UNSUPPORTED_TRANSPORT:
7556         gst_rtsp_message_unset (&request);
7557         gst_rtsp_message_unset (&response);
7558         /* cleanup of leftover transport */
7559         gst_rtspsrc_stream_free_udp (stream);
7560         /* MS WMServer RTSP MUST use same UDP pair in all SETUP requests;
7561          * we might be in this case */
7562         if (stream->container && rtpport && rtcpport && !retry) {
7563           GST_DEBUG_OBJECT (src, "retrying with original port pair %u-%u",
7564               rtpport, rtcpport);
7565           retry++;
7566           goto retry;
7567         }
7568         /* this transport did not go down well, but we may have others to try
7569          * that we did not send yet, try those and only give up then
7570          * but not without checking for lost cause/extension so we can
7571          * post a nicer/more useful error message later */
7572         if (!unsupported_real)
7573           unsupported_real = stream->is_real;
7574         /* select next available protocol, give up on this stream if none */
7575         mask++;
7576         while (protocol_masks[mask] && !(protocols & protocol_masks[mask]))
7577           mask++;
7578         if (!protocol_masks[mask] || unsupported_real)
7579           continue;
7580         else
7581           goto retry;
7582       default:
7583         /* cleanup of leftover transport and move to the next stream */
7584         gst_rtspsrc_stream_free_udp (stream);
7585         goto response_error;
7586     }
7587
7588
7589     if (!pipelined_request_id) {
7590       /* parse response transport */
7591       res = gst_rtsp_src_setup_stream_from_response (src, stream,
7592           &response, &protocols, retry, &rtpport, &rtcpport);
7593       switch (res) {
7594         case GST_RTSP_ERROR:
7595           goto cleanup_error;
7596         case GST_RTSP_ELAST:
7597           goto retry;
7598         default:
7599           break;
7600       }
7601     } else {
7602       stream->waiting_setup_response = TRUE;
7603       /* we need to activate at least one stream when we detect activity */
7604       src->need_activate = TRUE;
7605     }
7606
7607     {
7608       GList *skip = walk;
7609
7610       while (TRUE) {
7611         GstRTSPStream *sskip;
7612
7613         skip = g_list_next (skip);
7614         if (skip == NULL)
7615           break;
7616
7617         sskip = (GstRTSPStream *) skip->data;
7618
7619         /* skip all streams with the same control url */
7620         if (g_str_equal (stream->conninfo.location, sskip->conninfo.location)) {
7621           GST_DEBUG_OBJECT (src, "found stream %p with same control %s",
7622               sskip, sskip->conninfo.location);
7623           sskip->skipped = TRUE;
7624         }
7625       }
7626     }
7627     gst_rtsp_message_unset (&request);
7628   }
7629
7630   if (pipelined_request_id) {
7631     gst_rtspsrc_setup_streams_end (src, TRUE);
7632   }
7633
7634   /* store the transport protocol that was configured */
7635   src->cur_protocols = protocols;
7636
7637   gst_rtsp_ext_list_stream_select (src->extensions, url);
7638
7639   if (pipelined_request_id)
7640     g_free (pipelined_request_id);
7641
7642   /* if there is nothing to activate, error out */
7643   if (!src->need_activate)
7644     goto nothing_to_activate;
7645
7646   return res;
7647
7648   /* ERRORS */
7649 no_protocols:
7650   {
7651 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7652     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_INVALID_PROTOCOL,
7653         "Could not connect to server, no protocols left");
7654 #else
7655     /* no transport possible, post an error and stop */
7656     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
7657         ("Could not connect to server, no protocols left"));
7658 #endif
7659     return GST_RTSP_ERROR;
7660   }
7661 no_streams:
7662   {
7663 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7664     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONTENT_NOT_FOUND,
7665         "SDP contains no streams");
7666 #else
7667     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
7668         ("SDP contains no streams"));
7669 #endif
7670     return GST_RTSP_ERROR;
7671   }
7672 create_request_failed:
7673   {
7674     gchar *str = gst_rtsp_strresult (res);
7675
7676 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7677     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
7678         "Could not create request.");
7679 #else
7680     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
7681         ("Could not create request. (%s)", str));
7682 #endif
7683     g_free (str);
7684     goto cleanup_error;
7685   }
7686 setup_transport_failed:
7687   {
7688 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7689     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
7690         "Could not setup transport.");
7691 #else
7692     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
7693         ("Could not setup transport."));
7694 #endif
7695     res = GST_RTSP_ERROR;
7696     goto cleanup_error;
7697   }
7698 response_error:
7699   {
7700 #ifndef TIZEN_FEATURE_RTSP_MODIFICATION
7701     const gchar *str = gst_rtsp_status_as_text (code);
7702 #endif
7703
7704 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7705     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_UNEXPECTED_MSG,
7706         "Error from Server .");
7707 #else
7708     GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
7709         ("Error (%d): %s", code, GST_STR_NULL (str)));
7710 #endif
7711     res = GST_RTSP_ERROR;
7712     goto cleanup_error;
7713   }
7714 send_error:
7715   {
7716     gchar *str = gst_rtsp_strresult (res);
7717
7718     if (res != GST_RTSP_EINTR) {
7719 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7720       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
7721           "Could not send message.");
7722 #else
7723       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
7724           ("Could not send message. (%s)", str));
7725 #endif
7726     } else {
7727       GST_WARNING_OBJECT (src, "send interrupted");
7728     }
7729     g_free (str);
7730     goto cleanup_error;
7731   }
7732 nothing_to_activate:
7733   {
7734     /* none of the available error codes is really right .. */
7735     if (unsupported_real) {
7736 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7737       gst_rtspsrc_post_error_message (src,
7738           GST_RTSPSRC_ERROR_UNSUPPORTED_MEDIA_TYPE,
7739           "No supported stream was found. You might need to install a GStreamer RTSP extension plugin for Real media streams.");
7740 #else
7741       GST_ELEMENT_ERROR (src, STREAM, CODEC_NOT_FOUND,
7742           (_("No supported stream was found. You might need to install a "
7743                   "GStreamer RTSP extension plugin for Real media streams.")),
7744           (NULL));
7745 #endif
7746     } else {
7747 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7748       gst_rtspsrc_post_error_message (src,
7749           GST_RTSPSRC_ERROR_UNSUPPORTED_MEDIA_TYPE,
7750           "No supported stream was found. You might need to allow more transport protocols or may otherwise be missing the right GStreamer RTSP extension plugin.");
7751 #else
7752       GST_ELEMENT_ERROR (src, STREAM, CODEC_NOT_FOUND,
7753           (_("No supported stream was found. You might need to allow "
7754                   "more transport protocols or may otherwise be missing "
7755                   "the right GStreamer RTSP extension plugin.")), (NULL));
7756 #endif
7757     }
7758     return GST_RTSP_ERROR;
7759   }
7760 cleanup_error:
7761   {
7762     if (pipelined_request_id)
7763       g_free (pipelined_request_id);
7764     gst_rtsp_message_unset (&request);
7765     gst_rtsp_message_unset (&response);
7766     return res;
7767   }
7768 }
7769
7770 static gboolean
7771 gst_rtspsrc_parse_range (GstRTSPSrc * src, const gchar * range,
7772     GstSegment * segment)
7773 {
7774   gint64 seconds;
7775   GstRTSPTimeRange *therange;
7776
7777   if (src->range)
7778     gst_rtsp_range_free (src->range);
7779
7780   if (gst_rtsp_range_parse (range, &therange) == GST_RTSP_OK) {
7781     GST_DEBUG_OBJECT (src, "parsed range %s", range);
7782     src->range = therange;
7783   } else {
7784     GST_DEBUG_OBJECT (src, "failed to parse range %s", range);
7785     src->range = NULL;
7786     gst_segment_init (segment, GST_FORMAT_TIME);
7787     return FALSE;
7788   }
7789
7790   GST_DEBUG_OBJECT (src, "range: type %d, min %f - type %d,  max %f ",
7791       therange->min.type, therange->min.seconds, therange->max.type,
7792       therange->max.seconds);
7793
7794   if (therange->min.type == GST_RTSP_TIME_NOW)
7795     seconds = 0;
7796   else if (therange->min.type == GST_RTSP_TIME_END)
7797     seconds = 0;
7798   else
7799     seconds = therange->min.seconds * GST_SECOND;
7800
7801   GST_DEBUG_OBJECT (src, "range: min %" GST_TIME_FORMAT,
7802       GST_TIME_ARGS (seconds));
7803
7804   /* we need to start playback without clipping from the position reported by
7805    * the server */
7806   segment->start = seconds;
7807 #ifndef TIZEN_FEATURE_RTSP_MODIFICATION
7808 /*
7809 The range-min points to the start of the segment , not the current position.
7810 After getting the current position from MSL during normal pause/resume or during seek , we should not
7811 update the segment->position again with the rtp header npt timestamp.
7812 */
7813   segment->position = seconds;
7814 #endif
7815
7816   if (therange->max.type == GST_RTSP_TIME_NOW)
7817 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7818     seconds = 0;
7819 #else
7820     seconds = -1;
7821 #endif
7822   else if (therange->max.type == GST_RTSP_TIME_END)
7823     seconds = -1;
7824   else
7825     seconds = therange->max.seconds * GST_SECOND;
7826
7827   GST_DEBUG_OBJECT (src, "range: max %" GST_TIME_FORMAT,
7828       GST_TIME_ARGS (seconds));
7829
7830   /* live (WMS) server might send overflowed large max as its idea of infinity,
7831    * compensate to prevent problems later on */
7832   if (seconds != -1 && seconds < 0) {
7833     seconds = -1;
7834     GST_DEBUG_OBJECT (src, "insane range, set to NONE");
7835   }
7836
7837   /* live (WMS) might send min == max, which is not worth recording */
7838   if (segment->duration == -1 && seconds == segment->start)
7839     seconds = -1;
7840
7841   /* don't change duration with unknown value, we might have a valid value
7842    * there that we want to keep. */
7843   if (seconds != -1)
7844     segment->duration = seconds;
7845
7846   return TRUE;
7847 }
7848
7849 /* Parse clock profived by the server with following syntax:
7850  *
7851  * "GstNetTimeProvider <wrapped-clock> <server-IP:port> <clock-time>"
7852  */
7853 static gboolean
7854 gst_rtspsrc_parse_gst_clock (GstRTSPSrc * src, const gchar * gstclock)
7855 {
7856   gboolean res = FALSE;
7857
7858   if (g_str_has_prefix (gstclock, "GstNetTimeProvider ")) {
7859     gchar **fields = NULL, **parts = NULL;
7860     gchar *remote_ip, *str;
7861     gint port;
7862     GstClockTime base_time;
7863     GstClock *netclock;
7864
7865     fields = g_strsplit (gstclock, " ", 0);
7866
7867     /* wrapped clock, not very interesting for now */
7868     if (fields[1] == NULL)
7869       goto cleanup;
7870
7871     /* remote IP address and port */
7872     if ((str = fields[2]) == NULL)
7873       goto cleanup;
7874
7875     parts = g_strsplit (str, ":", 0);
7876
7877     if ((remote_ip = parts[0]) == NULL)
7878       goto cleanup;
7879
7880     if ((str = parts[1]) == NULL)
7881       goto cleanup;
7882
7883     port = atoi (str);
7884     if (port == 0)
7885       goto cleanup;
7886
7887     /* base-time */
7888     if ((str = fields[3]) == NULL)
7889       goto cleanup;
7890
7891     base_time = g_ascii_strtoull (str, NULL, 10);
7892
7893     netclock =
7894         gst_net_client_clock_new ((gchar *) "GstRTSPClock", remote_ip, port,
7895         base_time);
7896
7897     if (src->provided_clock)
7898       gst_object_unref (src->provided_clock);
7899     src->provided_clock = netclock;
7900
7901     gst_element_post_message (GST_ELEMENT_CAST (src),
7902         gst_message_new_clock_provide (GST_OBJECT_CAST (src),
7903             src->provided_clock, TRUE));
7904
7905     res = TRUE;
7906   cleanup:
7907     g_strfreev (fields);
7908     g_strfreev (parts);
7909   }
7910   return res;
7911 }
7912
7913 /* must be called with the RTSP state lock */
7914 static GstRTSPResult
7915 gst_rtspsrc_open_from_sdp (GstRTSPSrc * src, GstSDPMessage * sdp,
7916     gboolean async)
7917 {
7918   GstRTSPResult res;
7919   gint i, n_streams;
7920
7921   /* prepare global stream caps properties */
7922   if (src->props)
7923     gst_structure_remove_all_fields (src->props);
7924   else
7925     src->props = gst_structure_new_empty ("RTSPProperties");
7926
7927   DEBUG_SDP (src, sdp);
7928
7929   gst_rtsp_ext_list_parse_sdp (src->extensions, sdp, src->props);
7930
7931   /* let the app inspect and change the SDP */
7932   g_signal_emit (src, gst_rtspsrc_signals[SIGNAL_ON_SDP], 0, sdp);
7933
7934   gst_segment_init (&src->segment, GST_FORMAT_TIME);
7935
7936   /* parse range for duration reporting. */
7937   {
7938     const gchar *range;
7939
7940     for (i = 0;; i++) {
7941       range = gst_sdp_message_get_attribute_val_n (sdp, "range", i);
7942       if (range == NULL)
7943         break;
7944
7945       /* keep track of the range and configure it in the segment */
7946       if (gst_rtspsrc_parse_range (src, range, &src->segment))
7947         break;
7948     }
7949   }
7950   /* parse clock information. This is GStreamer specific, a server can tell the
7951    * client what clock it is using and wrap that in a network clock. The
7952    * advantage of that is that we can slave to it. */
7953   {
7954     const gchar *gstclock;
7955
7956     for (i = 0;; i++) {
7957       gstclock = gst_sdp_message_get_attribute_val_n (sdp, "x-gst-clock", i);
7958       if (gstclock == NULL)
7959         break;
7960
7961       /* parse the clock and expose it in the provide_clock method */
7962       if (gst_rtspsrc_parse_gst_clock (src, gstclock))
7963         break;
7964     }
7965   }
7966   /* try to find a global control attribute. Note that a '*' means that we should
7967    * do aggregate control with the current url (so we don't do anything and
7968    * leave the current connection as is) */
7969   {
7970     const gchar *control;
7971
7972     for (i = 0;; i++) {
7973       control = gst_sdp_message_get_attribute_val_n (sdp, "control", i);
7974       if (control == NULL)
7975         break;
7976
7977       /* only take fully qualified urls */
7978       if (g_str_has_prefix (control, "rtsp://"))
7979         break;
7980     }
7981     if (control) {
7982       g_free (src->conninfo.location);
7983       src->conninfo.location = g_strdup (control);
7984       /* make a connection for this, if there was a connection already, nothing
7985        * happens. */
7986       if (gst_rtsp_conninfo_connect (src, &src->conninfo, async) < 0) {
7987         GST_ERROR_OBJECT (src, "could not connect");
7988       }
7989     }
7990     /* we need to keep the control url separate from the connection url because
7991      * the rules for constructing the media control url need it */
7992     g_free (src->control);
7993     src->control = g_strdup (control);
7994   }
7995
7996 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
7997   src->is_audio_codec_supported = FALSE;
7998   src->is_video_codec_supported = FALSE;
7999 #endif
8000
8001   /* create streams */
8002   n_streams = gst_sdp_message_medias_len (sdp);
8003   for (i = 0; i < n_streams; i++) {
8004     gst_rtspsrc_create_stream (src, sdp, i, n_streams);
8005   }
8006
8007   src->state = GST_RTSP_STATE_INIT;
8008 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8009   /* Check for the support for the Media codecs */
8010   if ((!src->is_audio_codec_supported) && (!src->is_video_codec_supported)) {
8011     GST_ERROR_OBJECT (src, "UnSupported Media Type !!!! \n");
8012     goto unsupported_file_type;
8013   } else {
8014     GST_DEBUG_OBJECT (src, "Supported Media Type. \n");
8015   }
8016 #endif
8017   /* setup streams */
8018   if ((res = gst_rtspsrc_setup_streams_start (src, async)) < 0)
8019     goto setup_failed;
8020
8021   /* reset our state */
8022   src->need_range = TRUE;
8023   src->skip = FALSE;
8024
8025   src->state = GST_RTSP_STATE_READY;
8026
8027   return res;
8028
8029   /* ERRORS */
8030 setup_failed:
8031   {
8032     GST_ERROR_OBJECT (src, "setup failed");
8033     gst_rtspsrc_cleanup (src);
8034     return res;
8035   }
8036 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8037 unsupported_file_type:
8038   {
8039     gst_rtspsrc_post_error_message (src,
8040         GST_RTSPSRC_ERROR_UNSUPPORTED_MEDIA_TYPE,
8041         "No supported stream was found");
8042     res = GST_RTSP_ERROR;
8043     gst_rtspsrc_cleanup (src);
8044     return res;
8045   }
8046 #endif
8047 }
8048
8049 static GstRTSPResult
8050 gst_rtspsrc_retrieve_sdp (GstRTSPSrc * src, GstSDPMessage ** sdp,
8051     gboolean async)
8052 {
8053   GstRTSPResult res;
8054   GstRTSPMessage request = { 0 };
8055   GstRTSPMessage response = { 0 };
8056   guint8 *data;
8057   guint size;
8058   gchar *respcont = NULL;
8059   GstRTSPVersion versions[] =
8060       { GST_RTSP_VERSION_2_0, GST_RTSP_VERSION_INVALID };
8061
8062   src->version = src->default_version;
8063   if (src->default_version == GST_RTSP_VERSION_2_0) {
8064     versions[0] = GST_RTSP_VERSION_1_0;
8065   }
8066
8067 restart:
8068   src->need_redirect = FALSE;
8069
8070   /* can't continue without a valid url */
8071   if (G_UNLIKELY (src->conninfo.url == NULL)) {
8072     res = GST_RTSP_EINVAL;
8073     goto no_url;
8074   }
8075   src->tried_url_auth = FALSE;
8076
8077   if ((res = gst_rtsp_conninfo_connect (src, &src->conninfo, async)) < 0)
8078     goto connect_failed;
8079
8080   /* create OPTIONS */
8081   GST_DEBUG_OBJECT (src, "create options... (%s)", async ? "async" : "sync");
8082   res =
8083       gst_rtspsrc_init_request (src, &request, GST_RTSP_OPTIONS,
8084       src->conninfo.url_str);
8085   if (res < 0)
8086     goto create_request_failed;
8087
8088   /* send OPTIONS */
8089   request.type_data.request.version = src->version;
8090   GST_DEBUG_OBJECT (src, "send options...");
8091
8092   if (async)
8093     GST_ELEMENT_PROGRESS (src, CONTINUE, "open", ("Retrieving server options"));
8094
8095   if ((res =
8096           gst_rtspsrc_send (src, &src->conninfo, &request, &response,
8097               NULL, versions)) < 0) {
8098     goto send_error;
8099   }
8100
8101   src->version = request.type_data.request.version;
8102   GST_INFO_OBJECT (src, "Now using version: %s",
8103       gst_rtsp_version_as_text (src->version));
8104
8105   /* parse OPTIONS */
8106   if (!gst_rtspsrc_parse_methods (src, &response))
8107     goto methods_error;
8108
8109   /* create DESCRIBE */
8110   GST_DEBUG_OBJECT (src, "create describe...");
8111   res =
8112       gst_rtspsrc_init_request (src, &request, GST_RTSP_DESCRIBE,
8113       src->conninfo.url_str);
8114   if (res < 0)
8115     goto create_request_failed;
8116
8117   /* we only accept SDP for now */
8118   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_ACCEPT,
8119       "application/sdp");
8120
8121   if (src->backchannel == BACKCHANNEL_ONVIF)
8122     gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
8123         BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
8124   /* TODO: Handle the case when backchannel is unsupported and goto restart */
8125
8126   /* send DESCRIBE */
8127   GST_DEBUG_OBJECT (src, "send describe...");
8128
8129   if (async)
8130     GST_ELEMENT_PROGRESS (src, CONTINUE, "open", ("Retrieving media info"));
8131
8132   if ((res =
8133           gst_rtspsrc_send (src, &src->conninfo, &request, &response,
8134               NULL, NULL)) < 0)
8135     goto send_error;
8136
8137   /* we only perform redirect for describe and play, currently */
8138   if (src->need_redirect) {
8139     /* close connection, we don't have to send a TEARDOWN yet, ignore the
8140      * result. */
8141     gst_rtsp_conninfo_close (src, &src->conninfo, TRUE);
8142
8143     gst_rtsp_message_unset (&request);
8144     gst_rtsp_message_unset (&response);
8145
8146     /* and now retry */
8147     goto restart;
8148   }
8149
8150   /* it could be that the DESCRIBE method was not implemented */
8151   if (!(src->methods & GST_RTSP_DESCRIBE))
8152     goto no_describe;
8153
8154   /* check if reply is SDP */
8155   gst_rtsp_message_get_header (&response, GST_RTSP_HDR_CONTENT_TYPE, &respcont,
8156       0);
8157   /* could not be set but since the request returned OK, we assume it
8158    * was SDP, else check it. */
8159   if (respcont) {
8160     const gchar *props = strchr (respcont, ';');
8161
8162     if (props) {
8163       gchar *mimetype = g_strndup (respcont, props - respcont);
8164
8165       mimetype = g_strstrip (mimetype);
8166       if (g_ascii_strcasecmp (mimetype, "application/sdp") != 0) {
8167         g_free (mimetype);
8168         goto wrong_content_type;
8169       }
8170
8171       /* TODO: Check for charset property and do conversions of all messages if
8172        * needed. Some servers actually send that property */
8173
8174       g_free (mimetype);
8175     } else if (g_ascii_strcasecmp (respcont, "application/sdp") != 0) {
8176       goto wrong_content_type;
8177     }
8178   }
8179
8180   /* get message body and parse as SDP */
8181   gst_rtsp_message_get_body (&response, &data, &size);
8182   if (data == NULL || size == 0)
8183     goto no_describe;
8184
8185   GST_DEBUG_OBJECT (src, "parse SDP...");
8186   gst_sdp_message_new (sdp);
8187   gst_sdp_message_parse_buffer (data, size, *sdp);
8188
8189   /* clean up any messages */
8190   gst_rtsp_message_unset (&request);
8191   gst_rtsp_message_unset (&response);
8192
8193   return res;
8194
8195   /* ERRORS */
8196 no_url:
8197   {
8198 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8199     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_INVALID_URL,
8200         "No valid RTSP URL was provided");
8201 #else
8202     GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
8203         ("No valid RTSP URL was provided"));
8204 #endif
8205     goto cleanup_error;
8206   }
8207 connect_failed:
8208   {
8209     gchar *str = gst_rtsp_strresult (res);
8210
8211     if (res != GST_RTSP_EINTR) {
8212 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8213       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
8214           "Failed to connect.");
8215 #else
8216       GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
8217           ("Failed to connect. (%s)", str));
8218 #endif
8219     } else {
8220       GST_WARNING_OBJECT (src, "connect interrupted");
8221     }
8222     g_free (str);
8223     goto cleanup_error;
8224   }
8225 create_request_failed:
8226   {
8227     gchar *str = gst_rtsp_strresult (res);
8228
8229 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8230     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
8231         "Could not create request.");
8232 #else
8233     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
8234         ("Could not create request. (%s)", str));
8235 #endif
8236     g_free (str);
8237     goto cleanup_error;
8238   }
8239 send_error:
8240   {
8241     /* Don't post a message - the rtsp_send method will have
8242      * taken care of it because we passed NULL for the response code */
8243     goto cleanup_error;
8244   }
8245 methods_error:
8246   {
8247     /* error was posted */
8248     res = GST_RTSP_ERROR;
8249     goto cleanup_error;
8250   }
8251 wrong_content_type:
8252   {
8253 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8254     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_OPTION_NOT_SUPPORTED,
8255         "Server does not support SDP. ");
8256 #else
8257     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
8258         ("Server does not support SDP, got %s.", respcont));
8259 #endif
8260     res = GST_RTSP_ERROR;
8261     goto cleanup_error;
8262   }
8263 no_describe:
8264   {
8265 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8266     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_METHOD_NOT_ALLOWED,
8267         "Server can not provide an SDP.");
8268 #else
8269     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
8270         ("Server can not provide an SDP."));
8271 #endif
8272     res = GST_RTSP_ERROR;
8273     goto cleanup_error;
8274   }
8275 cleanup_error:
8276   {
8277     if (src->conninfo.connection) {
8278       GST_DEBUG_OBJECT (src, "free connection");
8279       gst_rtsp_conninfo_close (src, &src->conninfo, TRUE);
8280     }
8281     gst_rtsp_message_unset (&request);
8282     gst_rtsp_message_unset (&response);
8283     return res;
8284   }
8285 }
8286
8287 static GstRTSPResult
8288 gst_rtspsrc_open (GstRTSPSrc * src, gboolean async)
8289 {
8290   GstRTSPResult ret;
8291
8292   src->methods =
8293       GST_RTSP_SETUP | GST_RTSP_PLAY | GST_RTSP_PAUSE | GST_RTSP_TEARDOWN;
8294
8295   if (src->sdp == NULL) {
8296     if ((ret = gst_rtspsrc_retrieve_sdp (src, &src->sdp, async)) < 0)
8297       goto no_sdp;
8298   }
8299
8300   if ((ret = gst_rtspsrc_open_from_sdp (src, src->sdp, async)) < 0)
8301     goto open_failed;
8302
8303 done:
8304   if (async)
8305     gst_rtspsrc_loop_end_cmd (src, CMD_OPEN, ret);
8306
8307   return ret;
8308
8309   /* ERRORS */
8310 no_sdp:
8311   {
8312     GST_WARNING_OBJECT (src, "can't get sdp");
8313     src->open_error = TRUE;
8314     goto done;
8315   }
8316 open_failed:
8317   {
8318     GST_WARNING_OBJECT (src, "can't setup streaming from sdp");
8319     src->open_error = TRUE;
8320     goto done;
8321   }
8322 }
8323
8324 static GstRTSPResult
8325 gst_rtspsrc_close (GstRTSPSrc * src, gboolean async, gboolean only_close)
8326 {
8327   GstRTSPMessage request = { 0 };
8328   GstRTSPMessage response = { 0 };
8329   GstRTSPResult res = GST_RTSP_OK;
8330   GList *walk;
8331   const gchar *control;
8332
8333   GST_DEBUG_OBJECT (src, "TEARDOWN...");
8334
8335   gst_rtspsrc_set_state (src, GST_STATE_READY);
8336
8337   if (src->state < GST_RTSP_STATE_READY) {
8338     GST_DEBUG_OBJECT (src, "not ready, doing cleanup");
8339     goto close;
8340   }
8341
8342   if (only_close)
8343     goto close;
8344
8345   /* construct a control url */
8346   control = get_aggregate_control (src);
8347
8348   if (!(src->methods & (GST_RTSP_PLAY | GST_RTSP_TEARDOWN)))
8349     goto not_supported;
8350
8351   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8352     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8353     const gchar *setup_url;
8354     GstRTSPConnInfo *info;
8355
8356     /* try aggregate control first but do non-aggregate control otherwise */
8357     if (control)
8358       setup_url = control;
8359     else if ((setup_url = stream->conninfo.location) == NULL)
8360       continue;
8361
8362     if (src->conninfo.connection) {
8363       info = &src->conninfo;
8364     } else if (stream->conninfo.connection) {
8365       info = &stream->conninfo;
8366     } else {
8367       continue;
8368     }
8369     if (!info->connected)
8370       goto next;
8371
8372     /* do TEARDOWN */
8373     res =
8374         gst_rtspsrc_init_request (src, &request, GST_RTSP_TEARDOWN, setup_url);
8375     GST_LOG_OBJECT (src, "Teardown on %s", setup_url);
8376     if (res < 0)
8377       goto create_request_failed;
8378
8379     if (stream->is_backchannel && src->backchannel == BACKCHANNEL_ONVIF)
8380       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
8381           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
8382
8383     if (async)
8384       GST_ELEMENT_PROGRESS (src, CONTINUE, "close", ("Closing stream"));
8385
8386     if ((res =
8387             gst_rtspsrc_send (src, info, &request, &response, NULL, NULL)) < 0)
8388       goto send_error;
8389
8390     /* FIXME, parse result? */
8391     gst_rtsp_message_unset (&request);
8392     gst_rtsp_message_unset (&response);
8393
8394   next:
8395     /* early exit when we did aggregate control */
8396     if (control)
8397       break;
8398   }
8399
8400 close:
8401   /* close connections */
8402   GST_DEBUG_OBJECT (src, "closing connection...");
8403   gst_rtsp_conninfo_close (src, &src->conninfo, TRUE);
8404   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8405     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8406     gst_rtsp_conninfo_close (src, &stream->conninfo, TRUE);
8407   }
8408
8409   /* cleanup */
8410   gst_rtspsrc_cleanup (src);
8411
8412   src->state = GST_RTSP_STATE_INVALID;
8413
8414   if (async)
8415     gst_rtspsrc_loop_end_cmd (src, CMD_CLOSE, res);
8416
8417   return res;
8418
8419   /* ERRORS */
8420 create_request_failed:
8421   {
8422     gchar *str = gst_rtsp_strresult (res);
8423
8424 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8425     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
8426         "Could not create request.");
8427 #else
8428     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
8429         ("Could not create request. (%s)", str));
8430 #endif
8431     g_free (str);
8432     goto close;
8433   }
8434 send_error:
8435   {
8436     gchar *str = gst_rtsp_strresult (res);
8437
8438     gst_rtsp_message_unset (&request);
8439     if (res != GST_RTSP_EINTR) {
8440 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8441       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
8442           "Could not send message.");
8443 #else
8444       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
8445           ("Could not send message. (%s)", str));
8446 #endif
8447     } else {
8448       GST_WARNING_OBJECT (src, "TEARDOWN interrupted");
8449     }
8450     g_free (str);
8451     goto close;
8452   }
8453 not_supported:
8454   {
8455     GST_DEBUG_OBJECT (src,
8456         "TEARDOWN and PLAY not supported, can't do TEARDOWN");
8457     goto close;
8458   }
8459 }
8460
8461 /* RTP-Info is of the format:
8462  *
8463  * url=<URL>;[seq=<seqbase>;rtptime=<timebase>] [, url=...]
8464  *
8465  * rtptime corresponds to the timestamp for the NPT time given in the header
8466  * seqbase corresponds to the next sequence number we received. This number
8467  * indicates the first seqnum after the seek and should be used to discard
8468  * packets that are from before the seek.
8469  */
8470 static gboolean
8471 gst_rtspsrc_parse_rtpinfo (GstRTSPSrc * src, gchar * rtpinfo)
8472 {
8473   gchar **infos;
8474   gint i, j;
8475
8476   GST_DEBUG_OBJECT (src, "parsing RTP-Info %s", rtpinfo);
8477
8478   infos = g_strsplit (rtpinfo, ",", 0);
8479   for (i = 0; infos[i]; i++) {
8480     gchar **fields;
8481     GstRTSPStream *stream;
8482     gint32 seqbase;
8483     gint64 timebase;
8484
8485     GST_DEBUG_OBJECT (src, "parsing info %s", infos[i]);
8486
8487     /* init values, types of seqbase and timebase are bigger than needed so we
8488      * can store -1 as uninitialized values */
8489     stream = NULL;
8490     seqbase = -1;
8491     timebase = -1;
8492
8493     /* parse url, find stream for url.
8494      * parse seq and rtptime. The seq number should be configured in the rtp
8495      * depayloader or session manager to detect gaps. Same for the rtptime, it
8496      * should be used to create an initial time newsegment. */
8497     fields = g_strsplit (infos[i], ";", 0);
8498     for (j = 0; fields[j]; j++) {
8499       GST_DEBUG_OBJECT (src, "parsing field %s", fields[j]);
8500       /* remove leading whitespace */
8501       fields[j] = g_strchug (fields[j]);
8502       if (g_str_has_prefix (fields[j], "url=")) {
8503         /* get the url and the stream */
8504         stream =
8505             find_stream (src, (fields[j] + 4), (gpointer) find_stream_by_setup);
8506       } else if (g_str_has_prefix (fields[j], "seq=")) {
8507         seqbase = atoi (fields[j] + 4);
8508       } else if (g_str_has_prefix (fields[j], "rtptime=")) {
8509         timebase = g_ascii_strtoll (fields[j] + 8, NULL, 10);
8510       }
8511     }
8512     g_strfreev (fields);
8513     /* now we need to store the values for the caps of the stream */
8514     if (stream != NULL) {
8515       GST_DEBUG_OBJECT (src,
8516           "found stream %p, setting: seqbase %d, timebase %" G_GINT64_FORMAT,
8517           stream, seqbase, timebase);
8518
8519       /* we have a stream, configure detected params */
8520       stream->seqbase = seqbase;
8521       stream->timebase = timebase;
8522     }
8523   }
8524   g_strfreev (infos);
8525
8526   return TRUE;
8527 }
8528
8529 static void
8530 gst_rtspsrc_handle_rtcp_interval (GstRTSPSrc * src, gchar * rtcp)
8531 {
8532   guint64 interval;
8533   GList *walk;
8534
8535   interval = strtoul (rtcp, NULL, 10);
8536   GST_DEBUG_OBJECT (src, "rtcp interval: %" G_GUINT64_FORMAT " ms", interval);
8537
8538   if (!interval)
8539     return;
8540
8541   interval *= GST_MSECOND;
8542
8543   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8544     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8545
8546     /* already (optionally) retrieved this when configuring manager */
8547     if (stream->session) {
8548       GObject *rtpsession = stream->session;
8549
8550       GST_DEBUG_OBJECT (src, "configure rtcp interval in session %p",
8551           rtpsession);
8552       g_object_set (rtpsession, "rtcp-min-interval", interval, NULL);
8553     }
8554   }
8555
8556   /* now it happens that (Xenon) server sending this may also provide bogus
8557    * RTCP SR sync data (i.e. with quite some jitter), so never mind those
8558    * and just use RTP-Info to sync */
8559   if (src->manager) {
8560     GObjectClass *klass;
8561
8562     klass = G_OBJECT_GET_CLASS (G_OBJECT (src->manager));
8563     if (g_object_class_find_property (klass, "rtcp-sync")) {
8564       GST_DEBUG_OBJECT (src, "configuring rtp sync method");
8565       g_object_set (src->manager, "rtcp-sync", RTCP_SYNC_RTP, NULL);
8566     }
8567   }
8568 }
8569
8570 static gdouble
8571 gst_rtspsrc_get_float (const gchar * dstr)
8572 {
8573   gchar s[G_ASCII_DTOSTR_BUF_SIZE] = { 0, };
8574
8575   /* canonicalise floating point string so we can handle float strings
8576    * in the form "24.930" or "24,930" irrespective of the current locale */
8577   g_strlcpy (s, dstr, sizeof (s));
8578   g_strdelimit (s, ",", '.');
8579   return g_ascii_strtod (s, NULL);
8580 }
8581
8582 static gchar *
8583 gen_range_header (GstRTSPSrc * src, GstSegment * segment)
8584 {
8585   gchar val_str[G_ASCII_DTOSTR_BUF_SIZE] = { 0, };
8586 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8587   if (src->start_position != 0 && segment->position == 0) {
8588     segment->position = src->start_position;
8589     src->start_position = 0;
8590   }
8591 #endif
8592   if (src->range && src->range->min.type == GST_RTSP_TIME_NOW) {
8593     g_strlcpy (val_str, "now", sizeof (val_str));
8594   } else {
8595     if (segment->position == 0) {
8596       g_strlcpy (val_str, "0", sizeof (val_str));
8597     } else {
8598       g_ascii_dtostr (val_str, sizeof (val_str),
8599           ((gdouble) segment->position) / GST_SECOND);
8600     }
8601   }
8602 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8603   GST_DEBUG_OBJECT (src, "Range Header Added : npt=%s-", val_str);
8604 #endif
8605   return g_strdup_printf ("npt=%s-", val_str);
8606 }
8607
8608 static void
8609 clear_rtp_base (GstRTSPSrc * src, GstRTSPStream * stream)
8610 {
8611   guint i, len;
8612
8613   stream->timebase = -1;
8614   stream->seqbase = -1;
8615
8616   len = stream->ptmap->len;
8617   for (i = 0; i < len; i++) {
8618     PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, i);
8619     GstStructure *s;
8620
8621     if (item->caps == NULL)
8622       continue;
8623
8624     item->caps = gst_caps_make_writable (item->caps);
8625     s = gst_caps_get_structure (item->caps, 0);
8626     gst_structure_remove_fields (s, "clock-base", "seqnum-base", NULL);
8627     if (item->pt == stream->default_pt && stream->udpsrc[0])
8628       g_object_set (stream->udpsrc[0], "caps", item->caps, NULL);
8629   }
8630   stream->need_caps = TRUE;
8631 }
8632
8633 static GstRTSPResult
8634 gst_rtspsrc_ensure_open (GstRTSPSrc * src, gboolean async)
8635 {
8636   GstRTSPResult res = GST_RTSP_OK;
8637
8638   if (src->state < GST_RTSP_STATE_READY) {
8639     res = GST_RTSP_ERROR;
8640     if (src->open_error) {
8641       GST_DEBUG_OBJECT (src, "the stream was in error");
8642       goto done;
8643     }
8644     if (async)
8645       gst_rtspsrc_loop_start_cmd (src, CMD_OPEN);
8646
8647     if ((res = gst_rtspsrc_open (src, async)) < 0) {
8648       GST_DEBUG_OBJECT (src, "failed to open stream");
8649       goto done;
8650     }
8651   }
8652
8653 done:
8654   return res;
8655 }
8656
8657 static GstRTSPResult
8658 gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment, gboolean async,
8659     const gchar * seek_style)
8660 {
8661   GstRTSPMessage request = { 0 };
8662   GstRTSPMessage response = { 0 };
8663   GstRTSPResult res = GST_RTSP_OK;
8664   GList *walk;
8665   gchar *hval;
8666   gint hval_idx;
8667   const gchar *control;
8668
8669   GST_DEBUG_OBJECT (src, "PLAY...");
8670
8671 restart:
8672   if ((res = gst_rtspsrc_ensure_open (src, async)) < 0)
8673     goto open_failed;
8674
8675   if (!(src->methods & GST_RTSP_PLAY))
8676     goto not_supported;
8677
8678   if (src->state == GST_RTSP_STATE_PLAYING)
8679     goto was_playing;
8680
8681   if (!src->conninfo.connection || !src->conninfo.connected)
8682     goto done;
8683
8684   /* send some dummy packets before we activate the receive in the
8685    * udp sources */
8686   gst_rtspsrc_send_dummy_packets (src);
8687
8688   /* require new SR packets */
8689   if (src->manager)
8690     g_signal_emit_by_name (src->manager, "reset-sync", NULL);
8691
8692   /* construct a control url */
8693   control = get_aggregate_control (src);
8694
8695   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8696     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8697     const gchar *setup_url;
8698     GstRTSPConnInfo *conninfo;
8699
8700     /* try aggregate control first but do non-aggregate control otherwise */
8701     if (control)
8702       setup_url = control;
8703     else if ((setup_url = stream->conninfo.location) == NULL)
8704       continue;
8705
8706     if (src->conninfo.connection) {
8707       conninfo = &src->conninfo;
8708     } else if (stream->conninfo.connection) {
8709       conninfo = &stream->conninfo;
8710     } else {
8711       continue;
8712     }
8713
8714     /* do play */
8715     res = gst_rtspsrc_init_request (src, &request, GST_RTSP_PLAY, setup_url);
8716     if (res < 0)
8717       goto create_request_failed;
8718
8719     if (src->need_range && src->seekable >= 0.0) {
8720 #ifndef TIZEN_FEATURE_RTSP_MODIFICATION
8721       hval = gen_range_header (src, segment);
8722
8723       gst_rtsp_message_take_header (&request, GST_RTSP_HDR_RANGE, hval);
8724
8725 #endif
8726       /* store the newsegment event so it can be sent from the streaming thread. */
8727       src->need_segment = TRUE;
8728     }
8729 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8730     else {
8731 /*
8732  Updating position with the MSL current position as gst_rtspsrc_get_position() does not return correct position.
8733 */
8734       GST_DEBUG_OBJECT (src,
8735           " During normal pause-resume , segment->position=%" GST_TIME_FORMAT
8736           ",src->start_position=%" GST_TIME_FORMAT,
8737           GST_TIME_ARGS (segment->position),
8738           GST_TIME_ARGS (src->start_position));
8739       segment->position = src->last_pos;
8740     }
8741
8742 /*
8743  Sending the npt range request for each play request for updating the segment position properly.
8744 */
8745     hval = gen_range_header (src, segment);
8746     gst_rtsp_message_take_header (&request, GST_RTSP_HDR_RANGE, hval);
8747 #endif
8748
8749     if (segment->rate != 1.0) {
8750       gchar hval[G_ASCII_DTOSTR_BUF_SIZE];
8751
8752       g_ascii_dtostr (hval, sizeof (hval), segment->rate);
8753       if (src->skip)
8754         gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SCALE, hval);
8755       else
8756         gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SPEED, hval);
8757     }
8758
8759     if (seek_style)
8760       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SEEK_STYLE,
8761           seek_style);
8762
8763     /* when we have an ONVIF audio backchannel, the PLAY request must have the
8764      * Require: header when doing either aggregate or non-aggregate control */
8765     if (src->backchannel == BACKCHANNEL_ONVIF &&
8766         (control || stream->is_backchannel))
8767       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
8768           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
8769
8770     if (async)
8771       GST_ELEMENT_PROGRESS (src, CONTINUE, "request", ("Sending PLAY request"));
8772
8773     if ((res =
8774             gst_rtspsrc_send (src, conninfo, &request, &response, NULL, NULL))
8775         < 0)
8776       goto send_error;
8777
8778     if (src->need_redirect) {
8779       GST_DEBUG_OBJECT (src,
8780           "redirect: tearing down and restarting with new url");
8781       /* teardown and restart with new url */
8782       gst_rtspsrc_close (src, TRUE, FALSE);
8783       /* reset protocols to force re-negotiation with redirected url */
8784       src->cur_protocols = src->protocols;
8785       gst_rtsp_message_unset (&request);
8786       gst_rtsp_message_unset (&response);
8787       goto restart;
8788     }
8789
8790     /* seek may have silently failed as it is not supported */
8791     if (!(src->methods & GST_RTSP_PLAY)) {
8792       GST_DEBUG_OBJECT (src, "PLAY Range not supported; re-enable PLAY");
8793
8794       if (src->version >= GST_RTSP_VERSION_2_0 && src->seekable >= 0.0) {
8795         GST_WARNING_OBJECT (src, "Server declared stream as seekable but"
8796             " playing with range failed... Ignoring information.");
8797       }
8798       /* obviously it is supported as we made it here */
8799       src->methods |= GST_RTSP_PLAY;
8800       src->seekable = -1.0;
8801       /* but there is nothing to parse in the response,
8802        * so convey we have no idea and not to expect anything particular */
8803       clear_rtp_base (src, stream);
8804       if (control) {
8805         GList *run;
8806
8807         /* need to do for all streams */
8808         for (run = src->streams; run; run = g_list_next (run))
8809           clear_rtp_base (src, (GstRTSPStream *) run->data);
8810       }
8811       /* NOTE the above also disables npt based eos detection */
8812       /* and below forces position to 0,
8813        * which is visible feedback we lost the plot */
8814       segment->start = segment->position = src->last_pos;
8815     }
8816
8817     gst_rtsp_message_unset (&request);
8818
8819     /* parse RTP npt field. This is the current position in the stream (Normal
8820      * Play Time) and should be put in the NEWSEGMENT position field. */
8821     if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_RANGE, &hval,
8822             0) == GST_RTSP_OK)
8823       gst_rtspsrc_parse_range (src, hval, segment);
8824
8825     /* assume 1.0 rate now, overwrite when the SCALE or SPEED headers are present. */
8826     segment->rate = 1.0;
8827
8828     /* parse Speed header. This is the intended playback rate of the stream
8829      * and should be put in the NEWSEGMENT rate field. */
8830     if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_SPEED, &hval,
8831             0) == GST_RTSP_OK) {
8832       segment->rate = gst_rtspsrc_get_float (hval);
8833     } else if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_SCALE,
8834             &hval, 0) == GST_RTSP_OK) {
8835       segment->rate = gst_rtspsrc_get_float (hval);
8836     }
8837
8838     /* parse the RTP-Info header field (if ANY) to get the base seqnum and timestamp
8839      * for the RTP packets. If this is not present, we assume all starts from 0...
8840      * This is info for the RTP session manager that we pass to it in caps. */
8841     hval_idx = 0;
8842     while (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_RTP_INFO,
8843             &hval, hval_idx++) == GST_RTSP_OK)
8844       gst_rtspsrc_parse_rtpinfo (src, hval);
8845
8846     /* some servers indicate RTCP parameters in PLAY response,
8847      * rather than properly in SDP */
8848     if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_RTCP_INTERVAL,
8849             &hval, 0) == GST_RTSP_OK)
8850       gst_rtspsrc_handle_rtcp_interval (src, hval);
8851
8852     gst_rtsp_message_unset (&response);
8853
8854     /* early exit when we did aggregate control */
8855     if (control)
8856       break;
8857   }
8858   /* configure the caps of the streams after we parsed all headers. Only reset
8859    * the manager object when we set a new Range header (we did a seek) */
8860   gst_rtspsrc_configure_caps (src, segment, src->need_range);
8861
8862   /* set to PLAYING after we have configured the caps, otherwise we
8863    * might end up calling request_key (with SRTP) while caps are still
8864    * being configured. */
8865   gst_rtspsrc_set_state (src, GST_STATE_PLAYING);
8866
8867   /* set again when needed */
8868   src->need_range = FALSE;
8869
8870   src->running = TRUE;
8871   src->base_time = -1;
8872   src->state = GST_RTSP_STATE_PLAYING;
8873
8874   /* mark discont */
8875   GST_DEBUG_OBJECT (src, "mark DISCONT, we did a seek to another position");
8876   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8877     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8878     stream->discont = TRUE;
8879   }
8880
8881 done:
8882   if (async)
8883     gst_rtspsrc_loop_end_cmd (src, CMD_PLAY, res);
8884
8885   return res;
8886
8887   /* ERRORS */
8888 open_failed:
8889   {
8890     GST_WARNING_OBJECT (src, "failed to open stream");
8891     goto done;
8892   }
8893 not_supported:
8894   {
8895     GST_WARNING_OBJECT (src, "PLAY is not supported");
8896     goto done;
8897   }
8898 was_playing:
8899   {
8900     GST_WARNING_OBJECT (src, "we were already PLAYING");
8901     goto done;
8902   }
8903 create_request_failed:
8904   {
8905     gchar *str = gst_rtsp_strresult (res);
8906
8907 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8908     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
8909         "Could not create request. ");
8910 #else
8911     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
8912         ("Could not create request. (%s)", str));
8913 #endif
8914     g_free (str);
8915     goto done;
8916   }
8917 send_error:
8918   {
8919     gchar *str = gst_rtsp_strresult (res);
8920
8921     gst_rtsp_message_unset (&request);
8922     if (res != GST_RTSP_EINTR) {
8923 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
8924       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
8925           "Could not send message.");
8926 #else
8927       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
8928           ("Could not send message. (%s)", str));
8929 #endif
8930     } else {
8931       GST_WARNING_OBJECT (src, "PLAY interrupted");
8932     }
8933     g_free (str);
8934     goto done;
8935   }
8936 }
8937
8938 static GstRTSPResult
8939 gst_rtspsrc_pause (GstRTSPSrc * src, gboolean async)
8940 {
8941   GstRTSPResult res = GST_RTSP_OK;
8942   GstRTSPMessage request = { 0 };
8943   GstRTSPMessage response = { 0 };
8944   GList *walk;
8945   const gchar *control;
8946
8947   GST_DEBUG_OBJECT (src, "PAUSE...");
8948
8949   if ((res = gst_rtspsrc_ensure_open (src, async)) < 0)
8950     goto open_failed;
8951
8952   if (!(src->methods & GST_RTSP_PAUSE))
8953     goto not_supported;
8954
8955   if (src->state == GST_RTSP_STATE_READY)
8956     goto was_paused;
8957
8958   if (!src->conninfo.connection || !src->conninfo.connected)
8959     goto no_connection;
8960
8961   /* construct a control url */
8962   control = get_aggregate_control (src);
8963
8964   /* loop over the streams. We might exit the loop early when we could do an
8965    * aggregate control */
8966   for (walk = src->streams; walk; walk = g_list_next (walk)) {
8967     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
8968     GstRTSPConnInfo *conninfo;
8969     const gchar *setup_url;
8970
8971     /* try aggregate control first but do non-aggregate control otherwise */
8972     if (control)
8973       setup_url = control;
8974     else if ((setup_url = stream->conninfo.location) == NULL)
8975       continue;
8976
8977     if (src->conninfo.connection) {
8978       conninfo = &src->conninfo;
8979     } else if (stream->conninfo.connection) {
8980       conninfo = &stream->conninfo;
8981     } else {
8982       continue;
8983     }
8984
8985     if (async)
8986       GST_ELEMENT_PROGRESS (src, CONTINUE, "request",
8987           ("Sending PAUSE request"));
8988
8989     if ((res =
8990             gst_rtspsrc_init_request (src, &request, GST_RTSP_PAUSE,
8991                 setup_url)) < 0)
8992       goto create_request_failed;
8993
8994     /* when we have an ONVIF audio backchannel, the PAUSE request must have the
8995      * Require: header when doing either aggregate or non-aggregate control */
8996     if (src->backchannel == BACKCHANNEL_ONVIF &&
8997         (control || stream->is_backchannel))
8998       gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE,
8999           BACKCHANNEL_ONVIF_HDR_REQUIRE_VAL);
9000
9001     if ((res =
9002             gst_rtspsrc_send (src, conninfo, &request, &response, NULL,
9003                 NULL)) < 0)
9004       goto send_error;
9005
9006     gst_rtsp_message_unset (&request);
9007     gst_rtsp_message_unset (&response);
9008
9009     /* exit early when we did agregate control */
9010     if (control)
9011       break;
9012   }
9013
9014   /* change element states now */
9015   gst_rtspsrc_set_state (src, GST_STATE_PAUSED);
9016
9017 no_connection:
9018   src->state = GST_RTSP_STATE_READY;
9019
9020 done:
9021   if (async)
9022     gst_rtspsrc_loop_end_cmd (src, CMD_PAUSE, res);
9023
9024   return res;
9025
9026   /* ERRORS */
9027 open_failed:
9028   {
9029     GST_DEBUG_OBJECT (src, "failed to open stream");
9030     goto done;
9031   }
9032 not_supported:
9033   {
9034     GST_DEBUG_OBJECT (src, "PAUSE is not supported");
9035     goto done;
9036   }
9037 was_paused:
9038   {
9039     GST_DEBUG_OBJECT (src, "we were already PAUSED");
9040     goto done;
9041   }
9042 create_request_failed:
9043   {
9044     gchar *str = gst_rtsp_strresult (res);
9045
9046 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9047     gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
9048         "Could not create request.");
9049 #else
9050     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
9051         ("Could not create request. (%s)", str));
9052 #endif
9053     g_free (str);
9054     goto done;
9055   }
9056 send_error:
9057   {
9058     gchar *str = gst_rtsp_strresult (res);
9059
9060     gst_rtsp_message_unset (&request);
9061     if (res != GST_RTSP_EINTR) {
9062 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9063       gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_CONNECTION_FAIL,
9064           "Could not send message.");
9065 #else
9066       GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
9067           ("Could not send message. (%s)", str));
9068 #endif
9069     } else {
9070       GST_WARNING_OBJECT (src, "PAUSE interrupted");
9071     }
9072     g_free (str);
9073     goto done;
9074   }
9075 }
9076
9077 static void
9078 gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message)
9079 {
9080   GstRTSPSrc *rtspsrc;
9081
9082   rtspsrc = GST_RTSPSRC (bin);
9083
9084   switch (GST_MESSAGE_TYPE (message)) {
9085     case GST_MESSAGE_EOS:
9086       gst_message_unref (message);
9087       break;
9088     case GST_MESSAGE_ELEMENT:
9089     {
9090       const GstStructure *s = gst_message_get_structure (message);
9091
9092       if (gst_structure_has_name (s, "GstUDPSrcTimeout")) {
9093         gboolean ignore_timeout;
9094
9095         GST_DEBUG_OBJECT (bin, "timeout on UDP port");
9096
9097         GST_OBJECT_LOCK (rtspsrc);
9098         ignore_timeout = rtspsrc->ignore_timeout;
9099         rtspsrc->ignore_timeout = TRUE;
9100         GST_OBJECT_UNLOCK (rtspsrc);
9101
9102         /* we only act on the first udp timeout message, others are irrelevant
9103          * and can be ignored. */
9104         if (!ignore_timeout)
9105           gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_RECONNECT, CMD_LOOP);
9106         /* eat and free */
9107         gst_message_unref (message);
9108         return;
9109       }
9110       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
9111       break;
9112     }
9113     case GST_MESSAGE_ERROR:
9114     {
9115       GstObject *udpsrc;
9116       GstRTSPStream *stream;
9117       GstFlowReturn ret;
9118
9119       udpsrc = GST_MESSAGE_SRC (message);
9120
9121       GST_DEBUG_OBJECT (rtspsrc, "got error from %s",
9122           GST_ELEMENT_NAME (udpsrc));
9123
9124       stream = find_stream (rtspsrc, udpsrc, (gpointer) find_stream_by_udpsrc);
9125       if (!stream)
9126         goto forward;
9127
9128       /* we ignore the RTCP udpsrc */
9129       if (stream->udpsrc[1] == GST_ELEMENT_CAST (udpsrc))
9130         goto done;
9131
9132       /* if we get error messages from the udp sources, that's not a problem as
9133        * long as not all of them error out. We also don't really know what the
9134        * problem is, the message does not give enough detail... */
9135       ret = gst_rtspsrc_combine_flows (rtspsrc, stream, GST_FLOW_NOT_LINKED);
9136       GST_DEBUG_OBJECT (rtspsrc, "combined flows: %s", gst_flow_get_name (ret));
9137       if (ret != GST_FLOW_OK)
9138         goto forward;
9139
9140     done:
9141       gst_message_unref (message);
9142       break;
9143
9144     forward:
9145       /* fatal but not our message, forward */
9146       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
9147       break;
9148     }
9149     default:
9150     {
9151       GST_BIN_CLASS (parent_class)->handle_message (bin, message);
9152       break;
9153     }
9154   }
9155 }
9156
9157 /* the thread where everything happens */
9158 static void
9159 gst_rtspsrc_thread (GstRTSPSrc * src)
9160 {
9161   gint cmd;
9162   ParameterRequest *req = NULL;
9163
9164   GST_OBJECT_LOCK (src);
9165   cmd = src->pending_cmd;
9166   if (cmd == CMD_RECONNECT || cmd == CMD_PLAY || cmd == CMD_PAUSE
9167       || cmd == CMD_LOOP || cmd == CMD_OPEN || cmd == CMD_GET_PARAMETER
9168       || cmd == CMD_SET_PARAMETER) {
9169     if (g_queue_is_empty (&src->set_get_param_q)) {
9170       src->pending_cmd = CMD_LOOP;
9171     } else {
9172       ParameterRequest *next_req;
9173       req = g_queue_pop_head (&src->set_get_param_q);
9174       next_req = g_queue_peek_head (&src->set_get_param_q);
9175       src->pending_cmd = next_req ? next_req->cmd : CMD_LOOP;
9176     }
9177   } else
9178     src->pending_cmd = CMD_WAIT;
9179   GST_DEBUG_OBJECT (src, "got command %s", cmd_to_string (cmd));
9180
9181   /* we got the message command, so ensure communication is possible again */
9182   gst_rtspsrc_connection_flush (src, FALSE);
9183
9184   src->busy_cmd = cmd;
9185   GST_OBJECT_UNLOCK (src);
9186
9187   switch (cmd) {
9188     case CMD_OPEN:
9189       gst_rtspsrc_open (src, TRUE);
9190       break;
9191     case CMD_PLAY:
9192       gst_rtspsrc_play (src, &src->segment, TRUE, NULL);
9193       break;
9194     case CMD_PAUSE:
9195       gst_rtspsrc_pause (src, TRUE);
9196       break;
9197     case CMD_CLOSE:
9198       gst_rtspsrc_close (src, TRUE, FALSE);
9199       break;
9200     case CMD_GET_PARAMETER:
9201       gst_rtspsrc_get_parameter (src, req);
9202       break;
9203     case CMD_SET_PARAMETER:
9204       gst_rtspsrc_set_parameter (src, req);
9205       break;
9206     case CMD_LOOP:
9207       gst_rtspsrc_loop (src);
9208       break;
9209     case CMD_RECONNECT:
9210       gst_rtspsrc_reconnect (src, FALSE);
9211       break;
9212     default:
9213       break;
9214   }
9215
9216   GST_OBJECT_LOCK (src);
9217   /* No more cmds, wake any waiters */
9218   g_cond_broadcast (&src->cmd_cond);
9219   /* and go back to sleep */
9220   if (src->pending_cmd == CMD_WAIT) {
9221     if (src->task)
9222       gst_task_pause (src->task);
9223   }
9224   /* reset waiting */
9225   src->busy_cmd = CMD_WAIT;
9226   GST_OBJECT_UNLOCK (src);
9227 }
9228
9229 static gboolean
9230 gst_rtspsrc_start (GstRTSPSrc * src)
9231 {
9232   GST_DEBUG_OBJECT (src, "starting");
9233
9234   GST_OBJECT_LOCK (src);
9235
9236   src->pending_cmd = CMD_WAIT;
9237
9238   if (src->task == NULL) {
9239     src->task = gst_task_new ((GstTaskFunction) gst_rtspsrc_thread, src, NULL);
9240     if (src->task == NULL)
9241       goto task_error;
9242
9243     gst_task_set_lock (src->task, GST_RTSP_STREAM_GET_LOCK (src));
9244   }
9245   GST_OBJECT_UNLOCK (src);
9246
9247   return TRUE;
9248
9249   /* ERRORS */
9250 task_error:
9251   {
9252     GST_OBJECT_UNLOCK (src);
9253     GST_ERROR_OBJECT (src, "failed to create task");
9254     return FALSE;
9255   }
9256 }
9257
9258 static gboolean
9259 gst_rtspsrc_stop (GstRTSPSrc * src)
9260 {
9261   GstTask *task;
9262
9263   GST_DEBUG_OBJECT (src, "stopping");
9264
9265   /* also cancels pending task */
9266   gst_rtspsrc_loop_send_cmd (src, CMD_WAIT, CMD_ALL);
9267
9268   GST_OBJECT_LOCK (src);
9269   if ((task = src->task)) {
9270     src->task = NULL;
9271     GST_OBJECT_UNLOCK (src);
9272
9273     gst_task_stop (task);
9274
9275     /* make sure it is not running */
9276     GST_RTSP_STREAM_LOCK (src);
9277     GST_RTSP_STREAM_UNLOCK (src);
9278
9279     /* now wait for the task to finish */
9280     gst_task_join (task);
9281
9282     /* and free the task */
9283     gst_object_unref (GST_OBJECT (task));
9284
9285     GST_OBJECT_LOCK (src);
9286   }
9287   GST_OBJECT_UNLOCK (src);
9288
9289   /* ensure synchronously all is closed and clean */
9290   gst_rtspsrc_close (src, FALSE, TRUE);
9291
9292   return TRUE;
9293 }
9294
9295 static GstStateChangeReturn
9296 gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
9297 {
9298   GstRTSPSrc *rtspsrc;
9299   GstStateChangeReturn ret;
9300 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9301   guint64 end_time;
9302 #endif
9303
9304   rtspsrc = GST_RTSPSRC (element);
9305 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9306   GST_WARNING_OBJECT (rtspsrc, "State change transition: %d \n", transition);
9307 #endif
9308
9309   switch (transition) {
9310     case GST_STATE_CHANGE_NULL_TO_READY:
9311       if (!gst_rtspsrc_start (rtspsrc))
9312         goto start_failed;
9313       break;
9314     case GST_STATE_CHANGE_READY_TO_PAUSED:
9315       /* init some state */
9316       rtspsrc->cur_protocols = rtspsrc->protocols;
9317       /* first attempt, don't ignore timeouts */
9318       rtspsrc->ignore_timeout = FALSE;
9319       rtspsrc->open_error = FALSE;
9320       gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_OPEN, 0);
9321       break;
9322     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
9323       set_manager_buffer_mode (rtspsrc);
9324       /* fall-through */
9325     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
9326       /* unblock the tcp tasks and make the loop waiting */
9327       if (gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_WAIT, CMD_LOOP)) {
9328         /* make sure it is waiting before we send PAUSE or PLAY below */
9329         GST_RTSP_STREAM_LOCK (rtspsrc);
9330         GST_RTSP_STREAM_UNLOCK (rtspsrc);
9331       }
9332       break;
9333     case GST_STATE_CHANGE_PAUSED_TO_READY:
9334       break;
9335     default:
9336       break;
9337   }
9338
9339   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
9340   if (ret == GST_STATE_CHANGE_FAILURE)
9341     goto done;
9342
9343   switch (transition) {
9344     case GST_STATE_CHANGE_NULL_TO_READY:
9345       ret = GST_STATE_CHANGE_SUCCESS;
9346       break;
9347     case GST_STATE_CHANGE_READY_TO_PAUSED:
9348 #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
9349       /* don't change to PAUSE state before complete stream opend.
9350          see gst_rtspsrc_loop_complete_cmd() */
9351       g_mutex_lock (&(rtspsrc)->pause_lock);
9352       end_time = g_get_monotonic_time () + 10 * G_TIME_SPAN_SECOND;
9353       if (!g_cond_wait_until (&(rtspsrc)->open_end, &(rtspsrc)->pause_lock,
9354               end_time)) {
9355         GST_WARNING_OBJECT (rtspsrc,
9356             "time out: stream opend is not completed yet..");
9357       }
9358       g_mutex_unlock (&(rtspsrc)->pause_lock);
9359 #endif
9360       ret = GST_STATE_CHANGE_NO_PREROLL;
9361       break;
9362     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
9363       gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_PLAY, 0);
9364       ret = GST_STATE_CHANGE_SUCCESS;
9365       break;
9366     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
9367       /* send pause request and keep the idle task around */
9368       gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_PAUSE, CMD_LOOP);
9369       ret = GST_STATE_CHANGE_NO_PREROLL;
9370       break;
9371     case GST_STATE_CHANGE_PAUSED_TO_READY:
9372       gst_rtspsrc_loop_send_cmd_and_wait (rtspsrc, CMD_CLOSE, CMD_ALL,
9373           rtspsrc->teardown_timeout);
9374       ret = GST_STATE_CHANGE_SUCCESS;
9375       break;
9376     case GST_STATE_CHANGE_READY_TO_NULL:
9377       gst_rtspsrc_stop (rtspsrc);
9378       ret = GST_STATE_CHANGE_SUCCESS;
9379       break;
9380     default:
9381       /* Otherwise it's success, we don't want to return spurious
9382        * NO_PREROLL or ASYNC from internal elements as we care for
9383        * state changes ourselves here
9384        *
9385        * This is to catch PAUSED->PAUSED and PLAYING->PLAYING transitions.
9386        */
9387       if (GST_STATE_TRANSITION_NEXT (transition) == GST_STATE_PAUSED)
9388         ret = GST_STATE_CHANGE_NO_PREROLL;
9389       else
9390         ret = GST_STATE_CHANGE_SUCCESS;
9391       break;
9392   }
9393
9394 done:
9395   return ret;
9396
9397 start_failed:
9398   {
9399     GST_DEBUG_OBJECT (rtspsrc, "start failed");
9400     return GST_STATE_CHANGE_FAILURE;
9401   }
9402 }
9403
9404 static gboolean
9405 gst_rtspsrc_send_event (GstElement * element, GstEvent * event)
9406 {
9407   gboolean res;
9408   GstRTSPSrc *rtspsrc;
9409
9410   rtspsrc = GST_RTSPSRC (element);
9411
9412   if (GST_EVENT_IS_DOWNSTREAM (event)) {
9413     res = gst_rtspsrc_push_event (rtspsrc, event);
9414   } else {
9415     res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
9416   }
9417
9418   return res;
9419 }
9420
9421
9422 /*** GSTURIHANDLER INTERFACE *************************************************/
9423
9424 static GstURIType
9425 gst_rtspsrc_uri_get_type (GType type)
9426 {
9427   return GST_URI_SRC;
9428 }
9429
9430 static const gchar *const *
9431 gst_rtspsrc_uri_get_protocols (GType type)
9432 {
9433   static const gchar *protocols[] =
9434       { "rtsp", "rtspu", "rtspt", "rtsph", "rtsp-sdp",
9435     "rtsps", "rtspsu", "rtspst", "rtspsh", NULL
9436   };
9437
9438   return protocols;
9439 }
9440
9441 static gchar *
9442 gst_rtspsrc_uri_get_uri (GstURIHandler * handler)
9443 {
9444   GstRTSPSrc *src = GST_RTSPSRC (handler);
9445
9446   /* FIXME: make thread-safe */
9447   return g_strdup (src->conninfo.location);
9448 }
9449
9450 static gboolean
9451 gst_rtspsrc_uri_set_uri (GstURIHandler * handler, const gchar * uri,
9452     GError ** error)
9453 {
9454   GstRTSPSrc *src;
9455   GstRTSPResult res;
9456   GstSDPResult sres;
9457   GstRTSPUrl *newurl = NULL;
9458   GstSDPMessage *sdp = NULL;
9459
9460   src = GST_RTSPSRC (handler);
9461
9462   /* same URI, we're fine */
9463   if (src->conninfo.location && uri && !strcmp (uri, src->conninfo.location))
9464     goto was_ok;
9465
9466   if (g_str_has_prefix (uri, "rtsp-sdp://")) {
9467     sres = gst_sdp_message_new (&sdp);
9468     if (sres < 0)
9469       goto sdp_failed;
9470
9471     GST_DEBUG_OBJECT (src, "parsing SDP message");
9472     sres = gst_sdp_message_parse_uri (uri, sdp);
9473     if (sres < 0)
9474       goto invalid_sdp;
9475   } else {
9476     /* try to parse */
9477     GST_DEBUG_OBJECT (src, "parsing URI");
9478     if ((res = gst_rtsp_url_parse (uri, &newurl)) < 0)
9479       goto parse_error;
9480   }
9481
9482   /* if worked, free previous and store new url object along with the original
9483    * location. */
9484   GST_DEBUG_OBJECT (src, "configuring URI");
9485   g_free (src->conninfo.location);
9486   src->conninfo.location = g_strdup (uri);
9487   gst_rtsp_url_free (src->conninfo.url);
9488   src->conninfo.url = newurl;
9489   g_free (src->conninfo.url_str);
9490   if (newurl)
9491     src->conninfo.url_str = gst_rtsp_url_get_request_uri (src->conninfo.url);
9492   else
9493     src->conninfo.url_str = NULL;
9494
9495   if (src->sdp)
9496     gst_sdp_message_free (src->sdp);
9497   src->sdp = sdp;
9498   src->from_sdp = sdp != NULL;
9499
9500   GST_DEBUG_OBJECT (src, "set uri: %s", GST_STR_NULL (uri));
9501   GST_DEBUG_OBJECT (src, "request uri is: %s",
9502       GST_STR_NULL (src->conninfo.url_str));
9503
9504   return TRUE;
9505
9506   /* Special cases */
9507 was_ok:
9508   {
9509     GST_DEBUG_OBJECT (src, "URI was ok: '%s'", GST_STR_NULL (uri));
9510     return TRUE;
9511   }
9512 sdp_failed:
9513   {
9514     GST_ERROR_OBJECT (src, "Could not create new SDP (%d)", sres);
9515     g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
9516         "Could not create SDP");
9517     return FALSE;
9518   }
9519 invalid_sdp:
9520   {
9521     GST_ERROR_OBJECT (src, "Not a valid SDP (%d) '%s'", sres,
9522         GST_STR_NULL (uri));
9523     gst_sdp_message_free (sdp);
9524     g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
9525         "Invalid SDP");
9526     return FALSE;
9527   }
9528 parse_error:
9529   {
9530     GST_ERROR_OBJECT (src, "Not a valid RTSP url '%s' (%d)",
9531         GST_STR_NULL (uri), res);
9532     g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
9533         "Invalid RTSP URI");
9534     return FALSE;
9535   }
9536 }
9537
9538 static void
9539 gst_rtspsrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
9540 {
9541   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
9542
9543   iface->get_type = gst_rtspsrc_uri_get_type;
9544   iface->get_protocols = gst_rtspsrc_uri_get_protocols;
9545   iface->get_uri = gst_rtspsrc_uri_get_uri;
9546   iface->set_uri = gst_rtspsrc_uri_set_uri;
9547 }
9548
9549
9550 /* send GET_PARAMETER */
9551 static GstRTSPResult
9552 gst_rtspsrc_get_parameter (GstRTSPSrc * src, ParameterRequest * req)
9553 {
9554   GstRTSPMessage request = { 0 };
9555   GstRTSPMessage response = { 0 };
9556   GstRTSPResult res;
9557   GstRTSPStatusCode code = GST_RTSP_STS_OK;
9558   const gchar *control;
9559   gchar *recv_body = NULL;
9560   guint recv_body_len;
9561
9562   GST_DEBUG_OBJECT (src, "creating server get_parameter");
9563
9564   if ((res = gst_rtspsrc_ensure_open (src, FALSE)) < 0)
9565     goto open_failed;
9566
9567   control = get_aggregate_control (src);
9568   if (control == NULL)
9569     goto no_control;
9570
9571   if (!(src->methods & GST_RTSP_GET_PARAMETER))
9572     goto not_supported;
9573
9574   gst_rtspsrc_connection_flush (src, FALSE);
9575
9576   res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER,
9577       control);
9578   if (res < 0)
9579     goto create_request_failed;
9580
9581   res = gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_TYPE,
9582       req->content_type == NULL ? "text/parameters" : req->content_type);
9583   if (res < 0)
9584     goto add_content_hdr_failed;
9585
9586   if (req->body && req->body->len) {
9587     res =
9588         gst_rtsp_message_set_body (&request, (guint8 *) req->body->str,
9589         req->body->len);
9590     if (res < 0)
9591       goto set_body_failed;
9592   }
9593
9594   if ((res = gst_rtspsrc_send (src, &src->conninfo,
9595               &request, &response, &code, NULL)) < 0)
9596     goto send_error;
9597
9598   res = gst_rtsp_message_get_body (&response, (guint8 **) & recv_body,
9599       &recv_body_len);
9600   if (res < 0)
9601     goto get_body_failed;
9602
9603 done:
9604   {
9605     gst_promise_reply (req->promise,
9606         gst_structure_new ("get-parameter-reply",
9607             "rtsp-result", G_TYPE_INT, res,
9608             "rtsp-code", G_TYPE_INT, code,
9609             "rtsp-reason", G_TYPE_STRING, gst_rtsp_status_as_text (code),
9610             "body", G_TYPE_STRING, GST_STR_NULL (recv_body), NULL));
9611     free_param_data (req);
9612
9613
9614     gst_rtsp_message_unset (&request);
9615     gst_rtsp_message_unset (&response);
9616
9617     return res;
9618   }
9619
9620   /* ERRORS */
9621 open_failed:
9622   {
9623     GST_DEBUG_OBJECT (src, "failed to open stream");
9624     goto done;
9625   }
9626 no_control:
9627   {
9628     GST_DEBUG_OBJECT (src, "no control url to send GET_PARAMETER");
9629     res = GST_RTSP_ERROR;
9630     goto done;
9631   }
9632 not_supported:
9633   {
9634     GST_DEBUG_OBJECT (src, "GET_PARAMETER is not supported");
9635     res = GST_RTSP_ERROR;
9636     goto done;
9637   }
9638 create_request_failed:
9639   {
9640     GST_DEBUG_OBJECT (src, "could not create GET_PARAMETER request");
9641     goto done;
9642   }
9643 add_content_hdr_failed:
9644   {
9645     GST_DEBUG_OBJECT (src, "could not add content header");
9646     goto done;
9647   }
9648 set_body_failed:
9649   {
9650     GST_DEBUG_OBJECT (src, "could not set body");
9651     goto done;
9652   }
9653 send_error:
9654   {
9655     gchar *str = gst_rtsp_strresult (res);
9656
9657     GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
9658         ("Could not send get-parameter. (%s)", str));
9659     g_free (str);
9660     goto done;
9661   }
9662 get_body_failed:
9663   {
9664     GST_DEBUG_OBJECT (src, "could not get body");
9665     goto done;
9666   }
9667 }
9668
9669 /* send SET_PARAMETER */
9670 static GstRTSPResult
9671 gst_rtspsrc_set_parameter (GstRTSPSrc * src, ParameterRequest * req)
9672 {
9673   GstRTSPMessage request = { 0 };
9674   GstRTSPMessage response = { 0 };
9675   GstRTSPResult res = GST_RTSP_OK;
9676   GstRTSPStatusCode code = GST_RTSP_STS_OK;
9677   const gchar *control;
9678
9679   GST_DEBUG_OBJECT (src, "creating server set_parameter");
9680
9681   if ((res = gst_rtspsrc_ensure_open (src, FALSE)) < 0)
9682     goto open_failed;
9683
9684   control = get_aggregate_control (src);
9685   if (control == NULL)
9686     goto no_control;
9687
9688   if (!(src->methods & GST_RTSP_SET_PARAMETER))
9689     goto not_supported;
9690
9691   gst_rtspsrc_connection_flush (src, FALSE);
9692
9693   res =
9694       gst_rtsp_message_init_request (&request, GST_RTSP_SET_PARAMETER, control);
9695   if (res < 0)
9696     goto send_error;
9697
9698   res = gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_TYPE,
9699       req->content_type == NULL ? "text/parameters" : req->content_type);
9700   if (res < 0)
9701     goto add_content_hdr_failed;
9702
9703   if (req->body && req->body->len) {
9704     res =
9705         gst_rtsp_message_set_body (&request, (guint8 *) req->body->str,
9706         req->body->len);
9707
9708     if (res < 0)
9709       goto set_body_failed;
9710   }
9711
9712   if ((res = gst_rtspsrc_send (src, &src->conninfo,
9713               &request, &response, &code, NULL)) < 0)
9714     goto send_error;
9715
9716 done:
9717   {
9718     gst_promise_reply (req->promise, gst_structure_new ("set-parameter-reply",
9719             "rtsp-result", G_TYPE_INT, res,
9720             "rtsp-code", G_TYPE_INT, code,
9721             "rtsp-reason", G_TYPE_STRING, gst_rtsp_status_as_text (code),
9722             NULL));
9723     free_param_data (req);
9724
9725     gst_rtsp_message_unset (&request);
9726     gst_rtsp_message_unset (&response);
9727
9728     return res;
9729   }
9730
9731   /* ERRORS */
9732 open_failed:
9733   {
9734     GST_DEBUG_OBJECT (src, "failed to open stream");
9735     goto done;
9736   }
9737 no_control:
9738   {
9739     GST_DEBUG_OBJECT (src, "no control url to send SET_PARAMETER");
9740     res = GST_RTSP_ERROR;
9741     goto done;
9742   }
9743 not_supported:
9744   {
9745     GST_DEBUG_OBJECT (src, "SET_PARAMETER is not supported");
9746     res = GST_RTSP_ERROR;
9747     goto done;
9748   }
9749 add_content_hdr_failed:
9750   {
9751     GST_DEBUG_OBJECT (src, "could not add content header");
9752     goto done;
9753   }
9754 set_body_failed:
9755   {
9756     GST_DEBUG_OBJECT (src, "could not set body");
9757     goto done;
9758   }
9759 send_error:
9760   {
9761     gchar *str = gst_rtsp_strresult (res);
9762
9763     GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
9764         ("Could not send set-parameter. (%s)", str));
9765     g_free (str);
9766     goto done;
9767   }
9768 }
9769
9770 typedef struct _RTSPKeyValue
9771 {
9772   GstRTSPHeaderField field;
9773   gchar *value;
9774   gchar *custom_key;            /* custom header string (field is INVALID then) */
9775 } RTSPKeyValue;
9776
9777 static void
9778 key_value_foreach (GArray * array, GFunc func, gpointer user_data)
9779 {
9780   guint i;
9781
9782   g_return_if_fail (array != NULL);
9783
9784   for (i = 0; i < array->len; i++) {
9785     (*func) (&g_array_index (array, RTSPKeyValue, i), user_data);
9786   }
9787 }
9788
9789 static void
9790 dump_key_value (gpointer data, gpointer user_data G_GNUC_UNUSED)
9791 {
9792   RTSPKeyValue *key_value = (RTSPKeyValue *) data;
9793   GstRTSPSrc *src = GST_RTSPSRC (user_data);
9794   const gchar *key_string;
9795
9796   if (key_value->custom_key != NULL)
9797     key_string = key_value->custom_key;
9798   else
9799     key_string = gst_rtsp_header_as_text (key_value->field);
9800
9801   GST_LOG_OBJECT (src, "   key: '%s', value: '%s'", key_string,
9802       key_value->value);
9803 }
9804
9805 static void
9806 gst_rtspsrc_print_rtsp_message (GstRTSPSrc * src, const GstRTSPMessage * msg)
9807 {
9808   guint8 *data;
9809   guint size;
9810   GString *body_string = NULL;
9811
9812   g_return_if_fail (src != NULL);
9813   g_return_if_fail (msg != NULL);
9814
9815   if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_LOG)
9816     return;
9817
9818   GST_LOG_OBJECT (src, "--------------------------------------------");
9819   switch (msg->type) {
9820     case GST_RTSP_MESSAGE_REQUEST:
9821       GST_LOG_OBJECT (src, "RTSP request message %p", msg);
9822       GST_LOG_OBJECT (src, " request line:");
9823       GST_LOG_OBJECT (src, "   method: '%s'",
9824           gst_rtsp_method_as_text (msg->type_data.request.method));
9825       GST_LOG_OBJECT (src, "   uri:    '%s'", msg->type_data.request.uri);
9826       GST_LOG_OBJECT (src, "   version: '%s'",
9827           gst_rtsp_version_as_text (msg->type_data.request.version));
9828       GST_LOG_OBJECT (src, " headers:");
9829       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9830       GST_LOG_OBJECT (src, " body:");
9831       gst_rtsp_message_get_body (msg, &data, &size);
9832       if (size > 0) {
9833         body_string = g_string_new_len ((const gchar *) data, size);
9834         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9835         g_string_free (body_string, TRUE);
9836         body_string = NULL;
9837       }
9838       break;
9839     case GST_RTSP_MESSAGE_RESPONSE:
9840       GST_LOG_OBJECT (src, "RTSP response message %p", msg);
9841       GST_LOG_OBJECT (src, " status line:");
9842       GST_LOG_OBJECT (src, "   code:   '%d'", msg->type_data.response.code);
9843       GST_LOG_OBJECT (src, "   reason: '%s'", msg->type_data.response.reason);
9844       GST_LOG_OBJECT (src, "   version: '%s",
9845           gst_rtsp_version_as_text (msg->type_data.response.version));
9846       GST_LOG_OBJECT (src, " headers:");
9847       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9848       gst_rtsp_message_get_body (msg, &data, &size);
9849       GST_LOG_OBJECT (src, " body: length %d", size);
9850       if (size > 0) {
9851         body_string = g_string_new_len ((const gchar *) data, size);
9852         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9853         g_string_free (body_string, TRUE);
9854         body_string = NULL;
9855       }
9856       break;
9857     case GST_RTSP_MESSAGE_HTTP_REQUEST:
9858       GST_LOG_OBJECT (src, "HTTP request message %p", msg);
9859       GST_LOG_OBJECT (src, " request line:");
9860       GST_LOG_OBJECT (src, "   method:  '%s'",
9861           gst_rtsp_method_as_text (msg->type_data.request.method));
9862       GST_LOG_OBJECT (src, "   uri:     '%s'", msg->type_data.request.uri);
9863       GST_LOG_OBJECT (src, "   version: '%s'",
9864           gst_rtsp_version_as_text (msg->type_data.request.version));
9865       GST_LOG_OBJECT (src, " headers:");
9866       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9867       GST_LOG_OBJECT (src, " body:");
9868       gst_rtsp_message_get_body (msg, &data, &size);
9869       if (size > 0) {
9870         body_string = g_string_new_len ((const gchar *) data, size);
9871         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9872         g_string_free (body_string, TRUE);
9873         body_string = NULL;
9874       }
9875       break;
9876     case GST_RTSP_MESSAGE_HTTP_RESPONSE:
9877       GST_LOG_OBJECT (src, "HTTP response message %p", msg);
9878       GST_LOG_OBJECT (src, " status line:");
9879       GST_LOG_OBJECT (src, "   code:    '%d'", msg->type_data.response.code);
9880       GST_LOG_OBJECT (src, "   reason:  '%s'", msg->type_data.response.reason);
9881       GST_LOG_OBJECT (src, "   version: '%s'",
9882           gst_rtsp_version_as_text (msg->type_data.response.version));
9883       GST_LOG_OBJECT (src, " headers:");
9884       key_value_foreach (msg->hdr_fields, dump_key_value, src);
9885       gst_rtsp_message_get_body (msg, &data, &size);
9886       GST_LOG_OBJECT (src, " body: length %d", size);
9887       if (size > 0) {
9888         body_string = g_string_new_len ((const gchar *) data, size);
9889         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9890         g_string_free (body_string, TRUE);
9891         body_string = NULL;
9892       }
9893       break;
9894     case GST_RTSP_MESSAGE_DATA:
9895       GST_LOG_OBJECT (src, "RTSP data message %p", msg);
9896       GST_LOG_OBJECT (src, " channel: '%d'", msg->type_data.data.channel);
9897       GST_LOG_OBJECT (src, " size:    '%d'", msg->body_size);
9898       gst_rtsp_message_get_body (msg, &data, &size);
9899       if (size > 0) {
9900         body_string = g_string_new_len ((const gchar *) data, size);
9901         GST_LOG_OBJECT (src, " %s(%d)", body_string->str, size);
9902         g_string_free (body_string, TRUE);
9903         body_string = NULL;
9904       }
9905       break;
9906     default:
9907       GST_LOG_OBJECT (src, "unsupported message type %d", msg->type);
9908       break;
9909   }
9910   GST_LOG_OBJECT (src, "--------------------------------------------");
9911 }
9912
9913 static void
9914 gst_rtspsrc_print_sdp_media (GstRTSPSrc * src, GstSDPMedia * media)
9915 {
9916   GST_LOG_OBJECT (src, "   media:       '%s'", GST_STR_NULL (media->media));
9917   GST_LOG_OBJECT (src, "   port:        '%u'", media->port);
9918   GST_LOG_OBJECT (src, "   num_ports:   '%u'", media->num_ports);
9919   GST_LOG_OBJECT (src, "   proto:       '%s'", GST_STR_NULL (media->proto));
9920   if (media->fmts && media->fmts->len > 0) {
9921     guint i;
9922
9923     GST_LOG_OBJECT (src, "   formats:");
9924     for (i = 0; i < media->fmts->len; i++) {
9925       GST_LOG_OBJECT (src, "    format  '%s'", g_array_index (media->fmts,
9926               gchar *, i));
9927     }
9928   }
9929   GST_LOG_OBJECT (src, "   information: '%s'",
9930       GST_STR_NULL (media->information));
9931   if (media->connections && media->connections->len > 0) {
9932     guint i;
9933
9934     GST_LOG_OBJECT (src, "   connections:");
9935     for (i = 0; i < media->connections->len; i++) {
9936       GstSDPConnection *conn =
9937           &g_array_index (media->connections, GstSDPConnection, i);
9938
9939       GST_LOG_OBJECT (src, "    nettype:      '%s'",
9940           GST_STR_NULL (conn->nettype));
9941       GST_LOG_OBJECT (src, "    addrtype:     '%s'",
9942           GST_STR_NULL (conn->addrtype));
9943       GST_LOG_OBJECT (src, "    address:      '%s'",
9944           GST_STR_NULL (conn->address));
9945       GST_LOG_OBJECT (src, "    ttl:          '%u'", conn->ttl);
9946       GST_LOG_OBJECT (src, "    addr_number:  '%u'", conn->addr_number);
9947     }
9948   }
9949   if (media->bandwidths && media->bandwidths->len > 0) {
9950     guint i;
9951
9952     GST_LOG_OBJECT (src, "   bandwidths:");
9953     for (i = 0; i < media->bandwidths->len; i++) {
9954       GstSDPBandwidth *bw =
9955           &g_array_index (media->bandwidths, GstSDPBandwidth, i);
9956
9957       GST_LOG_OBJECT (src, "    type:         '%s'", GST_STR_NULL (bw->bwtype));
9958       GST_LOG_OBJECT (src, "    bandwidth:    '%u'", bw->bandwidth);
9959     }
9960   }
9961   GST_LOG_OBJECT (src, "   key:");
9962   GST_LOG_OBJECT (src, "    type:       '%s'", GST_STR_NULL (media->key.type));
9963   GST_LOG_OBJECT (src, "    data:       '%s'", GST_STR_NULL (media->key.data));
9964   if (media->attributes && media->attributes->len > 0) {
9965     guint i;
9966
9967     GST_LOG_OBJECT (src, "   attributes:");
9968     for (i = 0; i < media->attributes->len; i++) {
9969       GstSDPAttribute *attr =
9970           &g_array_index (media->attributes, GstSDPAttribute, i);
9971
9972       GST_LOG_OBJECT (src, "    attribute '%s' : '%s'", attr->key, attr->value);
9973     }
9974   }
9975 }
9976
9977 void
9978 gst_rtspsrc_print_sdp_message (GstRTSPSrc * src, const GstSDPMessage * msg)
9979 {
9980   g_return_if_fail (src != NULL);
9981   g_return_if_fail (msg != NULL);
9982
9983   if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_LOG)
9984     return;
9985
9986   GST_LOG_OBJECT (src, "--------------------------------------------");
9987   GST_LOG_OBJECT (src, "sdp packet %p:", msg);
9988   GST_LOG_OBJECT (src, " version:       '%s'", GST_STR_NULL (msg->version));
9989   GST_LOG_OBJECT (src, " origin:");
9990   GST_LOG_OBJECT (src, "  username:     '%s'",
9991       GST_STR_NULL (msg->origin.username));
9992   GST_LOG_OBJECT (src, "  sess_id:      '%s'",
9993       GST_STR_NULL (msg->origin.sess_id));
9994   GST_LOG_OBJECT (src, "  sess_version: '%s'",
9995       GST_STR_NULL (msg->origin.sess_version));
9996   GST_LOG_OBJECT (src, "  nettype:      '%s'",
9997       GST_STR_NULL (msg->origin.nettype));
9998   GST_LOG_OBJECT (src, "  addrtype:     '%s'",
9999       GST_STR_NULL (msg->origin.addrtype));
10000   GST_LOG_OBJECT (src, "  addr:         '%s'", GST_STR_NULL (msg->origin.addr));
10001   GST_LOG_OBJECT (src, " session_name:  '%s'",
10002       GST_STR_NULL (msg->session_name));
10003   GST_LOG_OBJECT (src, " information:   '%s'", GST_STR_NULL (msg->information));
10004   GST_LOG_OBJECT (src, " uri:           '%s'", GST_STR_NULL (msg->uri));
10005
10006   if (msg->emails && msg->emails->len > 0) {
10007     guint i;
10008
10009     GST_LOG_OBJECT (src, " emails:");
10010     for (i = 0; i < msg->emails->len; i++) {
10011       GST_LOG_OBJECT (src, "  email '%s'", g_array_index (msg->emails, gchar *,
10012               i));
10013     }
10014   }
10015   if (msg->phones && msg->phones->len > 0) {
10016     guint i;
10017
10018     GST_LOG_OBJECT (src, " phones:");
10019     for (i = 0; i < msg->phones->len; i++) {
10020       GST_LOG_OBJECT (src, "  phone '%s'", g_array_index (msg->phones, gchar *,
10021               i));
10022     }
10023   }
10024   GST_LOG_OBJECT (src, " connection:");
10025   GST_LOG_OBJECT (src, "  nettype:      '%s'",
10026       GST_STR_NULL (msg->connection.nettype));
10027   GST_LOG_OBJECT (src, "  addrtype:     '%s'",
10028       GST_STR_NULL (msg->connection.addrtype));
10029   GST_LOG_OBJECT (src, "  address:      '%s'",
10030       GST_STR_NULL (msg->connection.address));
10031   GST_LOG_OBJECT (src, "  ttl:          '%u'", msg->connection.ttl);
10032   GST_LOG_OBJECT (src, "  addr_number:  '%u'", msg->connection.addr_number);
10033   if (msg->bandwidths && msg->bandwidths->len > 0) {
10034     guint i;
10035
10036     GST_LOG_OBJECT (src, " bandwidths:");
10037     for (i = 0; i < msg->bandwidths->len; i++) {
10038       GstSDPBandwidth *bw =
10039           &g_array_index (msg->bandwidths, GstSDPBandwidth, i);
10040
10041       GST_LOG_OBJECT (src, "  type:         '%s'", GST_STR_NULL (bw->bwtype));
10042       GST_LOG_OBJECT (src, "  bandwidth:    '%u'", bw->bandwidth);
10043     }
10044   }
10045   GST_LOG_OBJECT (src, " key:");
10046   GST_LOG_OBJECT (src, "  type:         '%s'", GST_STR_NULL (msg->key.type));
10047   GST_LOG_OBJECT (src, "  data:         '%s'", GST_STR_NULL (msg->key.data));
10048   if (msg->attributes && msg->attributes->len > 0) {
10049     guint i;
10050
10051     GST_LOG_OBJECT (src, " attributes:");
10052     for (i = 0; i < msg->attributes->len; i++) {
10053       GstSDPAttribute *attr =
10054           &g_array_index (msg->attributes, GstSDPAttribute, i);
10055
10056       GST_LOG_OBJECT (src, "  attribute '%s' : '%s'", attr->key, attr->value);
10057     }
10058   }
10059   if (msg->medias && msg->medias->len > 0) {
10060     guint i;
10061
10062     GST_LOG_OBJECT (src, " medias:");
10063     for (i = 0; i < msg->medias->len; i++) {
10064       GST_LOG_OBJECT (src, "  media %u:", i);
10065       gst_rtspsrc_print_sdp_media (src, &g_array_index (msg->medias,
10066               GstSDPMedia, i));
10067     }
10068   }
10069   GST_LOG_OBJECT (src, "--------------------------------------------");
10070 }