Add 'TCP/UDP Switching' feature 80/99480/3 accepted/tizen/common/20161129.173620 accepted/tizen/ivi/20161130.015432 accepted/tizen/mobile/20161130.015212 accepted/tizen/tv/20161130.015258 submit/tizen/20161129.052917
authorHyunsoo, Park <hance.park@samsung.com>
Wed, 23 Nov 2016 04:48:18 +0000 (13:48 +0900)
committerSeokHoon Lee <andy.shlee@samsung.com>
Fri, 25 Nov 2016 06:32:05 +0000 (15:32 +0900)
Using this feature, User can choose transport layer protocol between TCP and UDP.

[Version] 1.6.1-4
[Profile] Common
[Issue Type] Add feature
[Dependency module] N/A
[Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161111.1]

Change-Id: Ief6aec65e3058c32760fc5490631c3bff635c254
Signed-off-by: Hyunsoo, Park <hance.park@samsung.com>
gst/rtsp-server/gstwfdmessage.c [changed mode: 0644->0755]
gst/rtsp-server/gstwfdmessage.h [changed mode: 0644->0755]
gst/rtsp-server/rtsp-client-wfd.c [changed mode: 0755->0644]
gst/rtsp-server/rtsp-client-wfd.h [changed mode: 0644->0755]
gst/rtsp-server/rtsp-server-wfd.c
gst/rtsp-server/rtsp-server-wfd.h [changed mode: 0644->0755]
packaging/gst-rtsp-server.spec

old mode 100644 (file)
new mode 100755 (executable)
index 0e1f7dd..8d75982
@@ -334,6 +334,21 @@ gst_wfd_message_uninit (GstWFDMessage * msg)
   if (msg->idr_request) {
     FREE_STRING (msg->idr_request);
   }
+  if (msg->tcp_ports) {
+    FREE_STRING(msg->tcp_ports);
+  }
+
+  if (msg->buf_len) {
+    FREE_STRING(msg->buf_len);
+  }
+
+  if (msg->audio_status) {
+    FREE_STRING(msg->audio_status);
+  }
+
+  if (msg->video_status) {
+    FREE_STRING(msg->video_status);
+  }
 
   return GST_WFD_OK;
 }
@@ -444,6 +459,7 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg)
 #define WFD_READ_STRING(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); REPLACE_STRING (field, temp)
 #define WFD_READ_UINT32(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 16)
 #define WFD_READ_UINT32_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 10)
+#define WFD_READ_UINT64_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoull (temp, NULL, 10)
 
   _read_string_attr_and_value (attr, value, sizeof (attr), sizeof (value), ':',
       p);
@@ -743,6 +759,40 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg)
   } else if (!g_strcmp0 (attr, GST_STRING_WFD_IDR_REQUEST)) {
     msg->idr_request = g_new0 (GstWFDIdrRequest, 1);
     msg->idr_request->idr_request = TRUE;
+  } else if (!g_strcmp0 (attr, GST_STRING_WFD2_TCP_PORTS)) {
+    msg->tcp_ports = g_new0 (GstWFDTCPPorts, 1);
+    if (strlen (v)) {
+      WFD_SKIP_SPACE (v);
+      WFD_READ_STRING (msg->tcp_ports->profile);
+      WFD_SKIP_SPACE (v);
+      WFD_READ_UINT32_DIGIT (msg->tcp_ports->rtp_port0);
+      WFD_SKIP_SPACE (v);
+      WFD_READ_UINT32_DIGIT (msg->tcp_ports->rtp_port1);
+      WFD_SKIP_SPACE (v);
+      WFD_READ_STRING (msg->tcp_ports->mode);
+    }
+  } else if (!g_strcmp0 (attr, GST_STRING_WFD2_BUFFER_LEN)) {
+    msg->buf_len = g_new0 (GstWFDBufferLen, 1);
+    if (strlen (v)) {
+      WFD_SKIP_SPACE (v);
+      WFD_READ_UINT32_DIGIT (msg->buf_len->buf_len);
+    }
+  } else if (!g_strcmp0 (attr, GST_STRING_WFD2_AUDIO_STATUS)) {
+    msg->audio_status = g_new0 (GstWFDAudioReport, 1);
+    if (strlen (v)) {
+      WFD_SKIP_SPACE (v);
+      WFD_READ_UINT32_DIGIT (msg->audio_status->aud_bufsize);
+      WFD_SKIP_SPACE (v);
+      WFD_READ_UINT64_DIGIT (msg->audio_status->aud_pts);
+    }
+  } else if (!g_strcmp0 (attr, GST_STRING_WFD2_VIDEO_STATUS)) {
+    msg->video_status = g_new0 (GstWFDVideoReport, 1);
+    if (strlen (v)) {
+      WFD_SKIP_SPACE (v);
+      WFD_READ_UINT32_DIGIT (msg->video_status->vid_bufsize);
+      WFD_SKIP_SPACE (v);
+      WFD_READ_UINT64_DIGIT (msg->video_status->vid_pts);
+    }
   }
   return;
 }
@@ -1106,6 +1156,24 @@ gst_wfd_message_as_text (const GstWFDMessage * msg)
     g_string_append_printf (lines, "\r\n");
   }
 
+  if (msg->tcp_ports) {
+    g_string_append_printf (lines, GST_STRING_WFD2_TCP_PORTS);
+    if (msg->tcp_ports->profile) {
+      g_string_append_printf (lines, ":");
+      g_string_append_printf (lines, " %s", msg->tcp_ports->profile);
+      g_string_append_printf (lines, " %d", msg->tcp_ports->rtp_port0);
+      g_string_append_printf (lines, " %d", msg->tcp_ports->rtp_port1);
+      g_string_append_printf (lines, " %s", msg->tcp_ports->mode);
+    }
+    g_string_append_printf (lines, "\r\n");
+  }
+
+  if (msg->buf_len) {
+    g_string_append_printf (lines, GST_STRING_WFD2_BUFFER_LEN);
+    g_string_append_printf (lines, ":");
+    g_string_append_printf (lines, " %d", msg->buf_len->buf_len);
+    g_string_append_printf (lines, "\r\n");
+  }
   return g_string_free (lines, FALSE);
 }
 
@@ -1189,6 +1257,22 @@ gst_wfd_message_param_names_as_text (const GstWFDMessage * msg)
     g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST);
     g_string_append_printf (lines, "\r\n");
   }
+  if (msg->tcp_ports) {
+    g_string_append_printf (lines, GST_STRING_WFD2_TCP_PORTS);
+    g_string_append_printf (lines, "\r\n");
+  }
+  if (msg->buf_len) {
+    g_string_append_printf (lines, GST_STRING_WFD2_BUFFER_LEN);
+    g_string_append_printf (lines, "\r\n");
+  }
+  if (msg->audio_status) {
+    g_string_append_printf (lines, GST_STRING_WFD2_AUDIO_STATUS);
+    g_string_append_printf (lines, "\r\n");
+  }
+  if (msg->video_status) {
+    g_string_append_printf (lines, GST_STRING_WFD2_VIDEO_STATUS);
+    g_string_append_printf (lines, "\r\n");
+  }
 
   return g_string_free (lines, FALSE);
 }
@@ -1383,6 +1467,35 @@ gst_wfd_message_dump (const GstWFDMessage * msg)
     g_print (GST_STRING_WFD_IDR_REQUEST);
     g_print ("\r\n");
   }
+  if (msg->tcp_ports) {
+    g_print (" TCP Ports : \n");
+    if (msg->tcp_ports->profile) {
+      g_print ("%s\n", msg->tcp_ports->profile);
+      g_print ("       %d\n", msg->tcp_ports->rtp_port0);
+      g_print ("       %d\n", msg->tcp_ports->rtp_port1);
+      g_print ("       %s\n", msg->tcp_ports->mode);
+    }
+    g_print ("\r\n");
+  }
+
+  if (msg->buf_len) {
+    g_print (" Buffer Length : %d\n", msg->buf_len->buf_len);
+    g_print ("\r\n");
+  }
+
+  if (msg->audio_status) {
+    g_print ("Audio Playback Status : \n");
+    g_print ("  Current audio buffer size : %d\n", msg->audio_status->aud_bufsize);
+    g_print ("  Current audio decoded PTS : %lld\n", msg->audio_status->aud_pts);
+    g_print ("\r\n");
+  }
+
+  if (msg->video_status) {
+    g_print ("Video Playback Status : \n");
+    g_print ("  Current video buffer size : %d\n", msg->video_status->vid_bufsize);
+    g_print ("  Current video decoded PTS : %lld\n", msg->video_status->vid_pts);
+    g_print ("\r\n");
+  }
 
   return GST_WFD_OK;
 }
@@ -1982,3 +2095,130 @@ gst_wfd_message_get_av_format_change_timing (GstWFDMessage * msg, guint64 * PTS,
 
   return GST_WFD_OK;
 }
+GstWFDResult
+gst_wfd_messge_set_prefered_tcp_ports (GstWFDMessage *msg,
+    GstWFDRTSPTransMode trans,
+    GstWFDRTSPProfile profile,
+    GstWFDRTSPLowerTrans lowertrans,
+    guint32 rtp_port0,
+    guint32 rtp_port1)
+{
+  GString *lines;
+  g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
+
+  if (!msg->tcp_ports)
+    msg->tcp_ports = g_new0 (GstWFDTCPPorts, 1);
+
+  if (trans != GST_WFD_RTSP_TRANS_UNKNOWN) {
+    lines = g_string_new ("");
+    if (trans == GST_WFD_RTSP_TRANS_RTP)
+      g_string_append_printf (lines, "RTP");
+    else if (trans == GST_WFD_RTSP_TRANS_RDT)
+      g_string_append_printf (lines, "RDT");
+
+    if (profile == GST_WFD_RTSP_PROFILE_AVP)
+      g_string_append_printf (lines, "/AVP");
+    else if (profile == GST_WFD_RTSP_PROFILE_SAVP)
+      g_string_append_printf (lines, "/SAVP");
+
+    if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP)
+      g_string_append_printf (lines, "/UDP;unicast");
+    else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST)
+      g_string_append_printf (lines, "/UDP;multicast");
+    else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_TCP)
+      g_string_append_printf (lines, "/TCP;unicast");
+    else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_HTTP)
+      g_string_append_printf (lines, "/HTTP");
+
+    msg->tcp_ports->profile = g_string_free (lines, FALSE);
+    msg->tcp_ports->rtp_port0 = rtp_port0;
+    msg->tcp_ports->rtp_port1 = rtp_port1;
+    msg->tcp_ports->mode = g_strdup ("mode=play");
+  }
+  return GST_WFD_OK;
+}
+
+GstWFDResult
+gst_wfd_message_get_prefered_tcp_ports (GstWFDMessage *msg,
+    GstWFDRTSPTransMode *trans,
+    GstWFDRTSPProfile *profile,
+    GstWFDRTSPLowerTrans *lowertrans,
+    guint32 *rtp_port0,
+    guint32 *rtp_port1)
+{
+  g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
+  g_return_val_if_fail (msg->tcp_ports != NULL, GST_WFD_EINVAL);
+
+  if (g_strrstr (msg->tcp_ports->profile, "RTP"))
+    *trans = GST_WFD_RTSP_TRANS_RTP;
+  if (g_strrstr (msg->tcp_ports->profile, "RDT"))
+    *trans = GST_WFD_RTSP_TRANS_RDT;
+  if (g_strrstr (msg->tcp_ports->profile, "AVP"))
+    *profile = GST_WFD_RTSP_PROFILE_AVP;
+  if (g_strrstr (msg->tcp_ports->profile, "SAVP"))
+    *profile = GST_WFD_RTSP_PROFILE_SAVP;
+  if (g_strrstr (msg->tcp_ports->profile, "UDP;unicast"))
+    *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP;
+  if (g_strrstr (msg->tcp_ports->profile, "UDP;multicast"))
+    *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST;
+  if (g_strrstr (msg->tcp_ports->profile, "TCP;unicast"))
+    *lowertrans = GST_WFD_RTSP_LOWER_TRANS_TCP;
+  if (g_strrstr (msg->tcp_ports->profile, "HTTP"))
+    *lowertrans = GST_WFD_RTSP_LOWER_TRANS_HTTP;
+
+  *rtp_port0 = msg->tcp_ports->rtp_port0;
+  *rtp_port1 = msg->tcp_ports->rtp_port1;
+
+  return GST_WFD_OK;
+}
+
+GstWFDResult
+gst_wfd_message_set_buffer_length (GstWFDMessage *msg, guint buf_len)
+{
+  g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
+
+  if (!msg->buf_len)
+    msg->buf_len = g_new0 (GstWFDBufferLen, 1);
+  msg->buf_len->buf_len = buf_len;
+
+  return GST_WFD_OK;
+}
+
+GstWFDResult
+gst_wfd_message_get_buffer_length (GstWFDMessage *msg, guint *buf_len)
+{
+  g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
+  g_return_val_if_fail (msg->buf_len != NULL, GST_WFD_EINVAL);
+
+  *buf_len = msg->buf_len->buf_len;
+
+  return GST_WFD_OK;
+}
+
+GstWFDResult
+gst_wfd_message_get_audio_playback_status (GstWFDMessage *msg,
+    guint *bufsize,
+    guint64 *pts)
+{
+  g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
+  g_return_val_if_fail (msg->audio_status != NULL, GST_WFD_EINVAL);
+
+  *bufsize = msg->audio_status->aud_bufsize;
+  *pts = msg->audio_status->aud_pts;
+
+  return GST_WFD_OK;
+}
+
+GstWFDResult
+gst_wfd_message_get_video_playback_status (GstWFDMessage *msg,
+    guint *bufsize,
+    guint64 *pts)
+{
+  g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
+  g_return_val_if_fail (msg->video_status != NULL, GST_WFD_EINVAL);
+
+  *bufsize = msg->video_status->vid_bufsize;
+  *pts = msg->video_status->vid_pts;
+
+  return GST_WFD_OK;
+}
old mode 100644 (file)
new mode 100755 (executable)
index b390ef3..5a64696
@@ -66,6 +66,10 @@ G_BEGIN_DECLS
 #define GST_STRING_WFD_CONNECTOR_TYPE             "wfd_connector_type"
 #define GST_STRING_WFD_IDR_REQUEST                "wfd_idr_request"
 
+#define GST_STRING_WFD2_TCP_PORTS                 "wfd2_tcp_ports"
+#define GST_STRING_WFD2_BUFFER_LEN                "wfd2_buffer_len"
+#define GST_STRING_WFD2_AUDIO_STATUS              "wfd2_audio_playback_status"
+#define GST_STRING_WFD2_VIDEO_STATUS              "wfd2_video_playback_status"
 /**
  * GstWFDResult:
  * @GST_WFD_OK: A successful return value
@@ -422,6 +426,26 @@ typedef struct {
   gboolean idr_request;
 } GstWFDIdrRequest;
 
+typedef struct {
+  gchar *profile;
+  guint32 rtp_port0;
+  guint32 rtp_port1;
+  gchar *mode;
+} GstWFDTCPPorts;
+
+typedef struct {
+  guint buf_len;
+} GstWFDBufferLen;
+
+typedef struct {
+  guint aud_bufsize;
+  guint64 aud_pts;
+} GstWFDAudioReport;
+
+typedef struct {
+  guint vid_bufsize;
+  guint64 vid_pts;
+} GstWFDVideoReport;
 /**
  * GstWFDMessage:
  * @version: the protocol version
@@ -459,6 +483,10 @@ typedef struct {
   GstWFDStandby *standby;
   GstWFDConnectorType *connector_type;
   GstWFDIdrRequest *idr_request;
+  GstWFDTCPPorts *tcp_ports;
+  GstWFDBufferLen *buf_len;
+  GstWFDAudioReport *audio_status;
+  GstWFDVideoReport *video_status;
 } GstWFDMessage;
 
 GType                   gst_wfd_message_get_type            (void);
@@ -613,6 +641,33 @@ GstWFDResult gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg,
 GstWFDResult gst_wfd_message_get_av_format_change_timing(GstWFDMessage *msg,
                                         guint64 *PTS,
                                         guint64 *DTS);
+GstWFDResult gst_wfd_messge_set_prefered_tcp_ports (GstWFDMessage *msg,
+                                        GstWFDRTSPTransMode trans,
+                                        GstWFDRTSPProfile profile,
+                                        GstWFDRTSPLowerTrans lowertrans,
+                                        guint32 rtp_port0,
+                                        guint32 rtp_port1);
+
+GstWFDResult gst_wfd_message_get_prefered_tcp_ports (GstWFDMessage *msg,
+                                        GstWFDRTSPTransMode *trans,
+                                        GstWFDRTSPProfile *profile,
+                                        GstWFDRTSPLowerTrans *lowertrans,
+                                        guint32 *rtp_port0,
+                                        guint32 *rtp_port1);
+
+GstWFDResult gst_wfd_message_set_buffer_length (GstWFDMessage *msg,
+                                        guint buf_len);
+
+GstWFDResult gst_wfd_message_get_buffer_length (GstWFDMessage *msg,
+                                        guint *buf_len);
+
+GstWFDResult gst_wfd_message_get_audio_playback_status (GstWFDMessage *msg,
+                                        guint *bufsize,
+                                        guint64 *pts);
+
+GstWFDResult gst_wfd_message_get_video_playback_status (GstWFDMessage *msg,
+                                        guint *bufsize,
+                                        guint64 *pts);
 G_END_DECLS
 
 #endif /* __GST_WFD_MESSAGE_H__ */
old mode 100755 (executable)
new mode 100644 (file)
index 6e5729a..55c32d7
 
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
 
 #include "rtsp-client-wfd.h"
 #include "rtsp-media-factory-wfd.h"
@@ -71,6 +76,16 @@ struct _GstRTSPClientRTPStats
   guint resent_packets;
 };
 
+typedef enum {
+  WFD_TS_UDP,
+  WFD_TS_TCP
+} WFDTSMode;
+
+typedef enum {
+  WFD_TS_REP_AUDIO,
+  WFD_TS_REP_VIDEO
+} WFDTSReportType;
+
 struct _GstRTSPWFDClientPrivate
 {
   GstRTSPWFDClientSendFunc send_func;   /* protected by send_lock */
@@ -141,6 +156,19 @@ struct _GstRTSPWFDClientPrivate
   gboolean rtcp_stats_enabled;
 
   gchar *sink_user_agent;
+  guint ctrans_tcp;
+  guint cprofile_tcp;
+  guint clowertrans_tcp;
+  guint32 crtp_port0_tcp;
+  guint32 crtp_port1_tcp;
+  guint buf_len;
+  WFDTSMode ts_mode;
+  WFDTSReportType report_type;
+  GstRTSPWatch *datawatch;
+  guint datawatchid;
+  GstRTSPConnection *data_conn;
+  gchar *uristr;
+  GMutex tcp_send_lock;
 };
 
 #define DEFAULT_WFD_TIMEOUT 60
@@ -323,6 +351,9 @@ gst_rtsp_wfd_client_init (GstRTSPWFDClient * client)
   memset (&priv->stats, 0x00, sizeof (GstRTSPClientRTPStats));
   priv->sink_user_agent = NULL;
 
+  priv->ts_mode = WFD_TS_UDP;
+  priv->report_type = WFD_TS_REP_AUDIO;
+  g_mutex_init (&priv->tcp_send_lock);
   GST_INFO_OBJECT (client, "Client is initialized");
 }
 
@@ -351,6 +382,7 @@ gst_rtsp_wfd_client_finalize (GObject * obj)
 
   g_mutex_clear (&priv->keep_alive_lock);
   g_mutex_clear (&priv->stats_lock);
+  g_mutex_clear (&priv->tcp_send_lock);
   G_OBJECT_CLASS (gst_rtsp_wfd_client_parent_class)->finalize (obj);
 }
 
@@ -499,6 +531,10 @@ static gboolean
 wfd_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media,
     GstRTSPStream * stream, GstRTSPContext * ctx)
 {
+  if (media) {
+    GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
+    priv->media = media;
+  }
   if (stream) {
     GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
     if (priv)
@@ -1008,6 +1044,378 @@ handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx)
       gst_rtsp_client_wfd_signals[SIGNAL_WFD_PLAYING_DONE], 0, NULL);
 }
 
+static gboolean
+do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
+{
+  GstRTSPMessage message = { 0 };
+  GstRTSPResult res = GST_RTSP_OK;
+  GstMapInfo map_info;
+  guint8 *data;
+  guint usize;
+
+  gst_rtsp_message_init_data (&message, channel);
+
+  /* FIXME, need some sort of iovec RTSPMessage here */
+  if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ))
+    return FALSE;
+
+  gst_rtsp_message_take_body (&message, map_info.data, map_info.size);
+
+  g_mutex_lock (&(GST_RTSP_WFD_CLIENT (client)->priv->tcp_send_lock));
+
+  gst_rtsp_watch_send_message (GST_RTSP_WFD_CLIENT (client)->priv->datawatch, &message, NULL);
+
+  g_mutex_unlock (&(GST_RTSP_WFD_CLIENT (client)->priv->tcp_send_lock));
+
+  gst_rtsp_message_steal_body (&message, &data, &usize);
+  gst_buffer_unmap (buffer, &map_info);
+
+  gst_rtsp_message_unset (&message);
+
+  return res == GST_RTSP_OK;
+}
+static GstRTSPResult
+message_received (GstRTSPWatch * watch, GstRTSPMessage * message,
+    gpointer user_data)
+{
+  return gst_rtsp_client_handle_message (GST_RTSP_CLIENT (user_data), message);
+}
+
+static GstRTSPResult
+message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data)
+{
+  GstRTSPClient *client;
+
+  client = GST_RTSP_CLIENT (user_data);
+  if(client == NULL)
+    return GST_RTSP_ERROR;
+  return GST_RTSP_OK;
+}
+
+static GstRTSPResult
+error (GstRTSPWatch * watch, GstRTSPResult result, gpointer user_data)
+{
+  GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+  gchar *str;
+
+  str = gst_rtsp_strresult (result);
+  GST_INFO ("client %p: received an error %s", client, str);
+  g_free (str);
+
+  return GST_RTSP_OK;
+}
+static GstRTSPResult
+closed_tcp (GstRTSPWatch * watch, gpointer user_data)
+{
+  GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+
+  GST_INFO ("client %p: connection closed", client);
+
+  return GST_RTSP_OK;
+}
+
+static GstRTSPResult
+error_full_tcp (GstRTSPWatch * watch, GstRTSPResult result,
+    GstRTSPMessage * message, guint id, gpointer user_data)
+{
+  GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+  gchar *str;
+
+  str = gst_rtsp_strresult (result);
+  GST_INFO
+    ("client %p: received an error %s when handling message %p with id %d",
+     client, str, message, id);
+  g_free (str);
+
+  return GST_RTSP_OK;
+}
+
+static GstRTSPWatchFuncs watch_funcs_tcp = {
+  message_received,
+  message_sent,
+  closed_tcp,
+  error,
+  NULL,
+  NULL,
+  error_full_tcp,
+  NULL
+};
+static void
+client_watch_notify_tcp (GstRTSPClient * client)
+{
+  GST_INFO ("client %p: watch destroyed", client);
+  GST_RTSP_WFD_CLIENT (client)->priv->datawatch = NULL;
+  GST_RTSP_WFD_CLIENT (client)->priv->data_conn = NULL;
+}
+
+static GstRTSPResult
+new_tcp (GstRTSPWFDClient * client)
+{
+  int fd;
+  GstRTSPResult res = GST_RTSP_OK;
+  GstRTSPConnection *conn = NULL;
+  GstRTSPConnection *parent_conn = NULL;
+  GstRTSPUrl *url;
+  guint64 timeout = 20000000;
+  struct sockaddr_in server_addr;
+  socklen_t sin_len;
+  GSource *source;
+  GMainContext *context;
+  int retry = 0;
+  int bsize = 1024000;
+  int rn = sizeof(int);
+  int state = 1;
+  GSocket *tcp = NULL;
+
+  struct sockaddr_in my_addr;
+  /* client's address */
+  gint sockoptval = 1;
+  int ret;
+  GSocketAddress *local;
+
+  /* Get the client connection details */
+  parent_conn = gst_rtsp_client_get_connection (GST_RTSP_CLIENT (client));
+  url = gst_rtsp_connection_get_url (parent_conn);
+  if(!url)
+    return GST_RTSP_ERROR;
+
+  gst_rtsp_url_set_port (url, client->priv->crtp_port0_tcp);
+
+  GST_INFO ("create new connection %p ip %s:%d", client, url->host, url->port);
+
+  /* create a TCP/IP socket */
+  if ((tcp = g_socket_new (AF_INET, SOCK_STREAM, 0, NULL)) == NULL) {
+    GST_ERROR ("cannot create socket");
+    return GST_RTSP_ERROR;
+  }
+  /* allow immediate reuse of the port */
+  ret = g_socket_set_option (tcp, SOL_SOCKET, SO_REUSEADDR, sockoptval, NULL);
+  if(ret == 0)
+  {
+    GST_ERROR ("cannot change socket options");
+    return GST_RTSP_ERROR;
+  }
+  /* bind the socket to our source address */
+  memset ((char*)&my_addr, 0, sizeof(my_addr));
+  /* 0 out the structure */
+  my_addr.sin_family = AF_INET;
+  /* address family */
+  my_addr.sin_port = htons (url->port);
+  my_addr.sin_addr.s_addr = inet_addr(url->host);
+
+  local = g_socket_address_new_from_native (&my_addr, sizeof(my_addr));
+
+  g_socket_set_blocking (tcp, FALSE);
+
+tcp_retry:
+  if ((g_socket_connect (tcp, local, NULL, NULL))) {
+    g_print( "Error connecting socket : %s\n", strerror( errno ) );
+    if (retry < 50) {
+      GST_ERROR("Connection failed... Try again...");
+      usleep(100000);
+      retry++;
+      goto tcp_retry;
+    }
+
+    return GST_RTSP_ERROR;
+  }
+
+  if ((res = gst_rtsp_connection_create_from_socket (tcp, url->host, url->port, NULL, &conn)) < 0)
+    return GST_RTSP_ERROR;
+
+  GST_DEBUG_OBJECT (client, "Able to connect to new port");
+
+  sin_len = sizeof(struct sockaddr);
+  fd = g_socket_get_fd (gst_rtsp_connection_get_read_socket (conn));
+  if (fd == -1) {
+    return GST_RTSP_EINVAL;
+  }
+
+  if (getsockname (fd, (struct sockaddr *)&server_addr, &sin_len) < 0) {
+    GST_ERROR_OBJECT (client, "Getsockname fail");
+    close(fd);
+    return GST_RTSP_ERROR;
+  }
+
+  GST_DEBUG_OBJECT (client, "New port created : %d", ntohs(server_addr.sin_port));
+
+  /* Set send buffer size to 5242880 */
+  if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bsize, (socklen_t)rn) < 0) {
+    GST_ERROR_OBJECT(client, "setsockopt failed");
+  } else {
+    getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bsize, (socklen_t *)&rn);
+    GST_WARNING_OBJECT(client, "New Send buf size : %d\n", bsize);
+  }
+
+  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state)) < 0) {
+    GST_ERROR_OBJECT(client, "setsockopt failed");
+  } else {
+    GST_WARNING_OBJECT(client, "TCP NO DELAY");
+  }
+
+  client->priv->data_conn = conn;
+
+  /* create watch for the connection and attach */
+  client->priv->datawatch = gst_rtsp_watch_new (client->priv->data_conn, &watch_funcs_tcp, client, (GDestroyNotify) client_watch_notify_tcp);
+  GST_DEBUG_OBJECT (client, "data watch : %p", client->priv->datawatch);
+   /* find the context to add the watch */
+   if ((source = g_main_current_source ()))
+     context = g_source_get_context (source);
+   else
+     context = NULL;
+
+   GST_DEBUG (" source = %p", source);
+   GST_INFO ("attaching to context %p", context);
+   client->priv->datawatchid = gst_rtsp_watch_attach (client->priv->datawatch, context);
+   gst_rtsp_watch_unref (client->priv->datawatch);
+   return res;
+}
+
+static void
+do_keepalive (GstRTSPSession * session)
+{
+  GST_INFO ("keep session %p alive", session);
+  gst_rtsp_session_touch (session);
+}
+static void
+map_transport (GstRTSPWFDClient * client, GstRTSPTransport  * ct)
+{
+  switch(client->priv->ctrans) {
+    case GST_WFD_RTSP_TRANS_RTP:
+      ct->trans = GST_RTSP_TRANS_RTP;
+      break;
+    case GST_WFD_RTSP_TRANS_RDT:
+      ct->trans = GST_RTSP_TRANS_RDT;
+      break;
+    default:
+      ct->trans = GST_RTSP_TRANS_UNKNOWN;
+      break;
+  }
+  switch(client->priv->cprofile) {
+    case GST_WFD_RTSP_PROFILE_AVP:
+      ct->profile = GST_RTSP_PROFILE_AVP;
+      break;
+    case GST_WFD_RTSP_PROFILE_SAVP:
+      ct->profile = GST_RTSP_PROFILE_SAVP;
+      break;
+    default:
+      ct->profile = GST_RTSP_PROFILE_UNKNOWN;
+      break;
+  }
+  switch(client->priv->clowertrans) {
+    case GST_WFD_RTSP_LOWER_TRANS_UDP:
+      ct->lower_transport = GST_RTSP_LOWER_TRANS_UDP;
+      break;
+    case GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST:
+      ct->lower_transport = GST_RTSP_LOWER_TRANS_UDP_MCAST;
+      break;
+    case GST_WFD_RTSP_LOWER_TRANS_TCP:
+      ct->lower_transport = GST_RTSP_LOWER_TRANS_TCP;
+      break;
+    case GST_WFD_RTSP_LOWER_TRANS_HTTP:
+      ct->lower_transport = GST_RTSP_LOWER_TRANS_HTTP;
+      break;
+    default:
+      ct->lower_transport = GST_RTSP_LOWER_TRANS_UNKNOWN;
+      break;
+  }
+
+  if (client->priv->ts_mode == WFD_TS_TCP)
+    ct->lower_transport = GST_RTSP_LOWER_TRANS_TCP;
+}
+
+static GstRTSPResult
+handle_ts_response (GstRTSPWFDClient * client, GstRTSPContext * ctx)
+{
+  GstRTSPResult res = GST_RTSP_OK;
+  GstRTSPTransport *ct;
+  GstRTSPConnection *conn;
+  GstRTSPUrl *url = NULL;
+  GList *t = NULL;
+  GstRTSPStreamTransport *tr = NULL;
+  GPtrArray *ta = NULL;
+
+  ta = g_ptr_array_new();
+
+  t = client->priv->transports;
+  tr = GST_RTSP_STREAM_TRANSPORT (t->data);
+  g_ptr_array_add (ta, t->data);
+
+  gst_rtsp_stream_transport_set_callbacks (tr, NULL, NULL, NULL, NULL);
+  gst_rtsp_stream_transport_set_keepalive (tr, NULL, ctx->session, NULL);
+
+  gst_rtsp_transport_new (&ct);
+  gst_rtsp_transport_init (ct);
+
+  map_transport (client, ct);
+
+  if (ct->trans != GST_RTSP_TRANS_RTP || ct->profile != GST_RTSP_PROFILE_AVP) {
+    GST_WARNING_OBJECT (client, "Trans or profile is wrong");
+    goto error;
+  }
+  if (ct->lower_transport == GST_RTSP_LOWER_TRANS_HTTP ||
+      ct->lower_transport == GST_RTSP_LOWER_TRANS_UNKNOWN) {
+    GST_WARNING_OBJECT (client, "Lowertrans is wrong");
+    goto error;
+  }
+  g_free (ct->destination);
+  if (client->priv->ts_mode == WFD_TS_UDP) {
+    g_print ("\nSwitched to UDP !!!\n");
+    /* Free any previous TCP connection */
+    if(client->priv->data_conn)
+    {
+      gst_rtsp_connection_close (client->priv->data_conn);
+      gst_rtsp_connection_free(client->priv->data_conn);
+      if (client->priv->datawatch) {
+        g_source_destroy ((GSource *)client->priv->datawatch);
+      }
+    }
+    conn = gst_rtsp_client_get_connection (GST_RTSP_CLIENT (client));
+    url = gst_rtsp_connection_get_url (conn);
+    gst_rtsp_url_set_port (url, client->priv->crtp_port0);
+    ct->destination = g_strdup (url->host);
+    ct->client_port.min = client->priv->crtp_port0;
+    if(client->priv->crtp_port1 == 0)
+      ct->client_port.max = client->priv->crtp_port0 + 1;
+    else ct->client_port.max = client->priv->crtp_port1;
+  } else if (client->priv->ts_mode == WFD_TS_TCP) {
+    res = new_tcp(client);
+    if(res != GST_RTSP_OK)
+      goto error;
+
+    conn = gst_rtsp_client_get_connection (GST_RTSP_CLIENT (client));
+    url = gst_rtsp_connection_get_url (conn);
+    ct->destination = g_strdup (url->host);
+    ct->client_port.min = client->priv->crtp_port0_tcp;
+    if(client->priv->crtp_port1_tcp == 0)
+      ct->client_port.max = client->priv->crtp_port0_tcp + 1;
+    else ct->client_port.max = client->priv->crtp_port1_tcp;
+  }
+
+  gst_rtsp_stream_transport_set_transport (tr, ct);
+
+  GST_DEBUG ("client %p: linking transport", client);
+  if (client->priv->ts_mode == WFD_TS_TCP) {
+    g_print ("\nSwitched to TCP !!!\n");
+    gst_rtsp_stream_transport_set_callbacks (tr, (GstRTSPSendFunc) do_send_data,
+        (GstRTSPSendFunc) do_send_data, client, NULL);
+  }
+  else if(client->priv->ts_mode == WFD_TS_UDP ) {
+    g_print ("\nSwitched to UDP !!!\n");
+    /* configure keepalive for this transport */
+    gst_rtsp_stream_transport_set_keepalive (tr, (GstRTSPKeepAliveFunc) do_keepalive, ctx->session, NULL);
+    gst_rtsp_stream_transport_set_callbacks (tr, NULL, NULL, client, NULL);
+  }
+
+  gst_rtsp_media_set_state (client->priv->media, GST_STATE_PLAYING, ta);
+
+  g_ptr_array_free (ta, FALSE);
+
+  return res;
+
+error:
+  return GST_RTSP_ERROR;
+}
 static void
 handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx)
 {
@@ -1111,6 +1519,28 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx)
           goto error;
         }
       }
+      if (msg->tcp_ports) {
+        /* Get the TCP ports preferred by WFDSink */
+        wfd_res =
+            gst_wfd_message_get_prefered_tcp_ports (msg, &priv->ctrans_tcp,
+            &priv->cprofile_tcp, &priv->clowertrans_tcp, &priv->crtp_port0_tcp,
+            &priv->crtp_port1_tcp);
+        if (wfd_res != GST_WFD_OK) {
+          GST_WARNING_OBJECT (client,
+              "Failed to get wfd prefered RTP ports...");
+          goto error;
+        }
+      }
+
+      if (msg->buf_len) {
+        wfd_res =
+          gst_wfd_message_get_buffer_length (msg, &priv->buf_len);
+        if (wfd_res != GST_WFD_OK) {
+          GST_WARNING_OBJECT (client,
+              "Failed to get wfd prefered RTP ports...");
+          goto error;
+        }
+      }
 
       if (msg->display_edid) {
         guint32 edid_block_count = 0;
@@ -1176,6 +1606,41 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx)
           gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST], 0,
           ctx);
     } else {
+      if (g_strrstr((char *)data, "wfd2_buffer_len")) {
+        GstWFDResult wfd_res;
+        GstWFDMessage *msg = NULL;
+        GST_DEBUG_OBJECT (_client, "Get TS message responce");
+
+        /* Parse TS response from sink */
+        wfd_res = gst_wfd_message_new (&msg);
+        if (wfd_res != GST_WFD_OK) {
+          GST_ERROR_OBJECT (client, "Failed to create wfd message...");
+          goto error;
+        }
+
+        wfd_res = gst_wfd_message_init (msg);
+        if (wfd_res != GST_WFD_OK) {
+          GST_ERROR_OBJECT (client, "Failed to init wfd message...");
+          goto error;
+        }
+
+        wfd_res = gst_wfd_message_parse_buffer (data, size, msg);
+        if (wfd_res != GST_WFD_OK) {
+          GST_ERROR_OBJECT (client, "Failed to parse wfd message...");
+          goto error;
+        }
+
+        wfd_res = gst_wfd_message_get_buffer_length (msg, &_client->priv->buf_len);
+        if (wfd_res != GST_WFD_OK) {
+          GST_ERROR_OBJECT (client, "Failed to parse wfd message...");
+          goto error;
+        }
+
+        if (GST_RTSP_OK != handle_ts_response (_client, ctx)) {
+          GST_ERROR_OBJECT (client, "Failed to handle transport switch response");
+          goto error;
+        }
+      }
       /* TODO-WFD: Handle another GET_PARAMETER response with body */
     }
   } else if (size == 0) {
@@ -1431,6 +1896,8 @@ typedef enum
   TEARDOWN_TRIGGER,
   PLAY_TRIGGER,
   PAUSE_TRIGGER,
+  TS_REQ_MSG,
+  TS_REP_REQ_MSG,
 } GstWFDMessageType;
 
 static gboolean
@@ -1605,6 +2072,24 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type,
       goto error;
     }
 
+    /* set the preffered TCP ports for the WFD server */
+    wfd_res =
+        gst_wfd_messge_set_prefered_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP,
+        GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1);
+    if (wfd_res != GST_WFD_OK) {
+      GST_ERROR_OBJECT (client,
+          "Failed to set tcp ports parameter on wfd message...");
+      goto error;
+    }
+
+    /* set the buffer length for the WFD server */
+    wfd_res =
+        gst_wfd_message_set_buffer_length (msg, 0);
+    if (wfd_res != GST_WFD_OK) {
+      GST_ERROR_OBJECT (client,
+          "Failed to set tcp ports parameter on wfd message...");
+      goto error;
+    }
     *data = gst_wfd_message_param_names_as_text (msg);
     if (*data == NULL) {
       GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
@@ -1794,6 +2279,69 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type,
       GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
       goto error;
     } else {
+      *len = strlen (*data);
+    }
+
+  } else if (msg_type == TS_REQ_MSG) {
+    /* create transport switch request to be sent */
+    wfd_res = gst_wfd_message_new (&msg);
+    if (wfd_res != GST_WFD_OK) {
+      GST_ERROR_OBJECT (client, "Failed to create wfd message...");
+      goto error;
+    }
+
+    wfd_res = gst_wfd_message_init (msg);
+    if (wfd_res != GST_WFD_OK) {
+      GST_ERROR_OBJECT (client, "Failed to init wfd message...");
+      goto error;
+    }
+
+    g_string_append_printf (buf, "rtsp://");
+
+    if (priv->host_address) {
+      g_string_append (buf, priv->host_address);
+    } else {
+      GST_ERROR_OBJECT (client, "Failed to get host address");
+      if (buf) g_string_free (buf, TRUE);
+      goto error;
+    }
+
+    g_string_append_printf (buf, "/wfd1.0/streamid=0");
+
+    /* set the preffered TCP ports for the WFD server */
+    if (priv->ts_mode == WFD_TS_UDP) {
+      wfd_res =
+        gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP,
+            GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1);
+      if (wfd_res != GST_WFD_OK) {
+        GST_ERROR_OBJECT (client,
+            "Failed to set prefered RTP ports on wfd message...");
+        goto error;
+      }
+    } else {
+      wfd_res =
+        gst_wfd_messge_set_prefered_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP,
+            GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_TCP, priv->crtp_port0_tcp, priv->crtp_port1_tcp);
+      if (wfd_res != GST_WFD_OK) {
+        GST_ERROR_OBJECT (client,
+            "Failed to set prefered TCP ports on wfd message...");
+        goto error;
+      }
+    }
+
+    wfd_res =
+      gst_wfd_message_set_buffer_length (msg, 200);
+    if (wfd_res != GST_WFD_OK) {
+      GST_ERROR_OBJECT (client,
+          "Failed to set prefered buffer length on wfd message...");
+      goto error;
+    }
+
+    *data = gst_wfd_message_as_text (msg);
+    if (*data == NULL) {
+      GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
+      goto error;
+    } else {
       gchar *append_data = NULL;
 
       g_signal_emit (client,
@@ -3102,8 +3650,157 @@ gst_rtsp_wfd_client_set_rtp_port1 (GstRTSPWFDClient * client, guint32 port)
   priv->crtp_port1 = port;
 }
 
-gchar *
-gst_rtsp_wfd_client_get_sink_user_agent (GstRTSPWFDClient * client)
+
+/**
+* prepare_transport_switch_request:
+* @client: client object
+* @request : requst message to be prepared
+* @url : url need to be in the request
+*
+* Prepares request based on @method & @message_type
+*
+* Returns: a #GstRTSPResult.
+*/
+static GstRTSPResult
+prepare_transport_switch_request (GstRTSPWFDClient * client, GstRTSPMessage * request)
+{
+  GstRTSPResult res = GST_RTSP_OK;
+  gchar *url = NULL;
+  gchar *msg = NULL;
+  guint msglen = 0;
+  GString *msglength;
+
+  GstRTSPMethod method = GST_RTSP_SET_PARAMETER;
+
+  url = g_strdup ("rtsp://localhost/wfd1.0");
+
+  GST_DEBUG_OBJECT (client, "Preparing request for transport switch");
+
+  /* initialize the request */
+  res = gst_rtsp_message_init_request (request, method, url);
+  if (res < 0) {
+    GST_ERROR ("init request failed");
+    return res;
+  }
+
+  /* add content type */
+  res =
+    gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
+        "text/parameters");
+  if (res != GST_RTSP_OK) {
+    GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
+    goto error;
+  }
+
+  _set_wfd_message_body (client, TS_REQ_MSG, &msg, &msglen);
+  msglength = g_string_new ("");
+  g_string_append_printf (msglength, "%d", msglen);
+  GST_DEBUG ("Transport switch server side message body: %s", msg);
+
+  /* add content-length type */
+  res =
+    gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
+        g_string_free (msglength, FALSE));
+  if (res != GST_RTSP_OK) {
+    GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
+    goto error;
+  }
+
+  res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
+  if (res != GST_RTSP_OK) {
+    GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
+    goto error;
+  }
+
+  g_free (msg);
+
+  return res;
+
+error:
+  return GST_RTSP_ERROR;
+}
+
+GstRTSPResult
+gst_rtsp_wfd_client_switch_to_udp (GstRTSPWFDClient * client)
+{
+  GstRTSPResult res = GST_RTSP_OK;
+  GstRTSPMessage request = { 0 };
+  GList *tl = NULL;
+  GPtrArray *ta = NULL;
+
+  ta = g_ptr_array_new();
+
+  tl = gst_rtsp_stream_transport_filter (client->priv->stats.stream, NULL, NULL);
+  client->priv->transports = tl;
+  g_ptr_array_add (ta, tl->data);
+
+  if (client->priv->ts_mode == WFD_TS_UDP) {
+    GST_ERROR_OBJECT (client, "Transport already UDP");
+    return res;
+  }
+
+  client->priv->ts_mode = WFD_TS_UDP;
+  res = prepare_transport_switch_request (client, &request);
+  if (GST_RTSP_OK != res) {
+    GST_ERROR_OBJECT (client, "Failed to prepare transport switch request....\n");
+    goto error;
+  }
+
+  GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message for transport switch...");
+
+  gst_send_request (client, NULL, &request);
+
+  gst_rtsp_media_set_state (client->priv->media, GST_STATE_PAUSED, ta);
+
+  g_ptr_array_free (ta, FALSE);
+
+  return res;
+
+error:
+  return res;
+
+}
+
+GstRTSPResult
+gst_rtsp_wfd_client_switch_to_tcp (GstRTSPWFDClient * client)
+{
+  GstRTSPResult res = GST_RTSP_OK;
+  GstRTSPMessage request = { 0 };
+  GList *tl = NULL;
+  GPtrArray *ta = NULL;
+
+  ta = g_ptr_array_new();
+
+  tl = gst_rtsp_stream_transport_filter (client->priv->stats.stream, NULL, NULL);
+  client->priv->transports = tl;
+  g_ptr_array_add (ta, tl->data);
+
+  if (client->priv->ts_mode == WFD_TS_TCP) {
+    GST_ERROR_OBJECT (client, "Transport already TCP");
+    return res;
+  }
+
+  client->priv->ts_mode = WFD_TS_TCP;
+  res = prepare_transport_switch_request (client, &request);
+  if (GST_RTSP_OK != res) {
+    GST_ERROR_OBJECT (client, "Failed to prepare transport switch request....\n");
+    goto error;
+  }
+
+  GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message for transport switch...");
+
+  gst_send_request (client, NULL, &request);
+
+  gst_rtsp_media_set_state (client->priv->media, GST_STATE_PAUSED, ta);
+
+  g_ptr_array_free (ta, FALSE);
+
+  return res;
+
+error:
+  return res;
+}
+gchar * gst_rtsp_wfd_client_get_sink_user_agent (GstRTSPWFDClient * client)
 {
   char *str = NULL;
   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
old mode 100644 (file)
new mode 100755 (executable)
index f59835b..4d78382
@@ -149,6 +149,8 @@ GstRTSPResult         gst_prepare_request (GstRTSPWFDClient * client,
                           GstRTSPMessage * request, GstRTSPMethod method, gchar * url);
 void                  gst_send_request (GstRTSPWFDClient * client,
                           GstRTSPSession * session, GstRTSPMessage * request);
+GstRTSPResult         gst_rtsp_wfd_client_switch_to_udp (GstRTSPWFDClient * client);
+GstRTSPResult         gst_rtsp_wfd_client_switch_to_tcp (GstRTSPWFDClient * client);
 
 guint     gst_rtsp_wfd_client_get_audio_codec(GstRTSPWFDClient *client);
 guint     gst_rtsp_wfd_client_get_audio_freq(GstRTSPWFDClient *client);
index 0fa2cd5..042ec3b 100644 (file)
@@ -334,3 +334,61 @@ gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer * server,
   GST_RTSP_WFD_SERVER_UNLOCK (server);
   return res;
 }
+
+GstRTSPResult
+gst_rtsp_wfd_server_switch_to_udp (GstRTSPWFDServer *server)
+{
+  GstRTSPResult res = GST_RTSP_OK;
+  GList *clients, *walk, *next;
+
+  g_return_val_if_fail (GST_IS_RTSP_SERVER (server), GST_RTSP_ERROR);
+
+  clients = gst_rtsp_server_client_filter (GST_RTSP_SERVER(server), NULL, NULL);
+  if (clients == NULL) {
+    GST_ERROR_OBJECT (server, "There is no client in this server");
+  }
+
+  for (walk = clients; walk; walk = next) {
+    GstRTSPClient *client = walk->data;
+
+    next = g_list_next (walk);
+
+    res =
+        gst_rtsp_wfd_client_switch_to_udp (GST_RTSP_WFD_CLIENT (client));
+    if (res != GST_RTSP_OK) {
+      GST_ERROR_OBJECT (server, "Failed to switch transport to UDP");
+    }
+    g_object_unref (client);
+  }
+
+  return res;
+}
+
+GstRTSPResult
+gst_rtsp_wfd_server_switch_to_tcp (GstRTSPWFDServer *server)
+{
+  GstRTSPResult res = GST_RTSP_OK;
+  GList *clients, *walk, *next;
+
+  g_return_val_if_fail (GST_IS_RTSP_SERVER (server), GST_RTSP_ERROR);
+
+  clients = gst_rtsp_server_client_filter (GST_RTSP_SERVER(server), NULL, NULL);
+  if (clients == NULL) {
+    GST_ERROR_OBJECT (server, "There is no client in this server");
+  }
+
+  for (walk = clients; walk; walk = next) {
+    GstRTSPClient *client = walk->data;
+
+    next = g_list_next (walk);
+
+    res =
+        gst_rtsp_wfd_client_switch_to_tcp (GST_RTSP_WFD_CLIENT (client));
+    if (res != GST_RTSP_OK) {
+      GST_ERROR_OBJECT (server, "Failed to switch transport to TCP");
+    }
+    g_object_unref (client);
+  }
+
+  return res;
+}
old mode 100644 (file)
new mode 100755 (executable)
index e718e62..1666f18
@@ -81,6 +81,8 @@ GstRTSPResult         gst_rtsp_wfd_server_trigger_request      (GstRTSPServer *s
 GstRTSPResult         gst_rtsp_wfd_server_set_supported_reso (GstRTSPWFDServer *server, guint64 supported_reso);
 GstRTSPResult         gst_rtsp_wfd_server_set_video_native_reso    (GstRTSPWFDServer *server, guint64 native_reso);
 GstRTSPResult         gst_rtsp_wfd_server_set_audio_codec    (GstRTSPWFDServer *server, guint8 audio_codec);
+GstRTSPResult         gst_rtsp_wfd_server_switch_to_udp (GstRTSPWFDServer *server);
+GstRTSPResult         gst_rtsp_wfd_server_switch_to_tcp (GstRTSPWFDServer *server);
 
 #if 0
 void                  gst_rtsp_server_set_address          (GstRTSPServer *server, const gchar *address);
index f73387c..d6ae977 100644 (file)
@@ -1,7 +1,7 @@
 Name:       gst-rtsp-server
 Summary:    Multimedia Framework Library
 Version:    1.6.1
-Release:    3
+Release:    4
 Url:        http://gstreamer.freedesktop.org/
 Group:      System/Libraries
 License:    LGPL-2.0+