Add AL-FEC feature
[platform/upstream/gst-rtsp-server.git] / gst / rtsp-server / rtsp-client-wfd.c
1 /* GStreamer
2  * Copyright (C) 2015 Samsung Electronics Hyunjun Ko <zzoon.ko@samsung.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 /**
20  * SECTION:rtsp-client
21  * @short_description: A client connection state
22  * @see_also: #GstRTSPServer, #GstRTSPThreadPool
23  *
24  * The client object handles the connection with a client for as long as a TCP
25  * connection is open.
26  *
27  * A #GstRTSPWFDClient is created by #GstRTSPServer when a new connection is
28  * accepted and it inherits the #GstRTSPMountPoints, #GstRTSPSessionPool,
29  * #GstRTSPAuth and #GstRTSPThreadPool from the server.
30  *
31  * The client connection should be configured with the #GstRTSPConnection using
32  * gst_rtsp_wfd_client_set_connection() before it can be attached to a #GMainContext
33  * using gst_rtsp_wfd_client_attach(). From then on the client will handle requests
34  * on the connection.
35  *
36  * Use gst_rtsp_wfd_client_session_filter() to iterate or modify all the
37  * #GstRTSPSession objects managed by the client object.
38  *
39  * Last reviewed on 2013-07-11 (1.0.0)
40  */
41
42 #include <stdio.h>
43 #include <string.h>
44
45 #include "rtsp-client-wfd.h"
46 #include "rtsp-media-factory-wfd.h"
47 #include "rtsp-sdp.h"
48 #include "rtsp-params.h"
49
50 #define GST_RTSP_WFD_CLIENT_GET_PRIVATE(obj)  \
51    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_WFD_CLIENT, GstRTSPWFDClientPrivate))
52
53 typedef struct _GstRTSPClientRTPStats GstRTSPClientRTPStats;
54
55 struct _GstRTSPClientRTPStats
56 {
57   GstRTSPStream *stream;
58   guint64 last_sent_bytes;
59   guint64 sent_bytes;
60   guint last_seqnum;
61   guint seqnum;
62
63   /* Info in RR (Receiver Report) */
64   guint8 fraction_lost;
65   guint32 cumulative_lost_num;
66   guint16 max_seqnum;
67   guint32 arrival_jitter;
68   guint32 lsr;
69   guint32 dlsr;
70   guint32 rtt;
71   guint resent_packets;
72 };
73
74 struct _GstRTSPWFDClientPrivate
75 {
76   GstRTSPWFDClientSendFunc send_func;   /* protected by send_lock */
77   gpointer send_data;           /* protected by send_lock */
78   GDestroyNotify send_notify;   /* protected by send_lock */
79
80   /* used to cache the media in the last requested DESCRIBE so that
81    * we can pick it up in the next SETUP immediately */
82   gchar *path;
83   GstRTSPMedia *media;
84
85   GList *transports;
86   GList *sessions;
87
88   guint8 m1_done;
89   guint8 m3_done;
90   guint8 m4_done;
91
92   /* Host's URL info */
93   gchar *host_address;
94
95   /* Parameters for WIFI-DISPLAY */
96   guint caCodec;
97   guint8 audio_codec;
98   guint cFreq;
99   guint cChanels;
100   guint cBitwidth;
101   guint caLatency;
102   guint cvCodec;
103   guint cNative;
104   guint64 cNativeResolution;
105   guint64 video_resolution_supported;
106   gint video_native_resolution;
107   guint64 cCEAResolution;
108   guint64 cVESAResolution;
109   guint64 cHHResolution;
110   guint cProfile;
111   guint cLevel;
112   guint32 cMaxHeight;
113   guint32 cMaxWidth;
114   guint32 cFramerate;
115   guint32 cInterleaved;
116   guint32 cmin_slice_size;
117   guint32 cslice_enc_params;
118   guint cframe_rate_control;
119   guint cvLatency;
120   guint ctrans;
121   guint cprofile;
122   guint clowertrans;
123   guint32 crtp_port0;
124   guint32 crtp_port1;
125
126   gboolean protection_enabled;
127   GstWFDHDCPProtection hdcp_version;
128   guint32 hdcp_tcpport;
129
130   gboolean edid_supported;
131   guint32 edid_hres;
132   guint32 edid_vres;
133
134   gboolean keep_alive_flag;
135   GMutex keep_alive_lock;
136
137   /* RTP statistics */
138   GstRTSPClientRTPStats stats;
139   GMutex stats_lock;
140   guint stats_timer_id;
141   gboolean rtcp_stats_enabled;
142
143   gchar *sink_user_agent;
144 };
145
146 #define DEFAULT_WFD_TIMEOUT 60
147 #define WFD_MOUNT_POINT "/wfd1.0/streamid=0"
148
149 enum
150 {
151   SIGNAL_WFD_OPTIONS_REQUEST,
152   SIGNAL_WFD_GET_PARAMETER_REQUEST,
153   SIGNAL_WFD_KEEP_ALIVE_FAIL,
154   SIGNAL_WFD_PLAYING_DONE,
155   SIGNAL_WFD_RTP_STATS,
156   SIGNAL_WFD_M3_REQ_MSG,
157   SIGNAL_WFD_M3_RES_MSG,
158   SIGNAL_WFD_M4_REQ_MSG,
159   SIGNAL_WFD_SET_PARAM_MSG,
160   SIGNAL_WFD_LAST
161 };
162
163 GST_DEBUG_CATEGORY_STATIC (rtsp_wfd_client_debug);
164 #define GST_CAT_DEFAULT rtsp_wfd_client_debug
165
166 static guint gst_rtsp_client_wfd_signals[SIGNAL_WFD_LAST] = { 0 };
167
168 static void gst_rtsp_wfd_client_get_property (GObject * object, guint propid,
169     GValue * value, GParamSpec * pspec);
170 static void gst_rtsp_wfd_client_set_property (GObject * object, guint propid,
171     const GValue * value, GParamSpec * pspec);
172 static void gst_rtsp_wfd_client_finalize (GObject * obj);
173
174 static gboolean handle_wfd_options_request (GstRTSPClient * client,
175     GstRTSPContext * ctx);
176 static gboolean handle_wfd_set_param_request (GstRTSPClient * client,
177     GstRTSPContext * ctx);
178 static gboolean handle_wfd_get_param_request (GstRTSPClient * client,
179     GstRTSPContext * ctx);
180
181 static void send_generic_wfd_response (GstRTSPWFDClient * client,
182     GstRTSPStatusCode code, GstRTSPContext * ctx);
183 static gchar *wfd_make_path_from_uri (GstRTSPClient * client,
184     const GstRTSPUrl * uri);
185 static void wfd_options_request_done (GstRTSPWFDClient * client,
186     GstRTSPContext * ctx);
187 static void wfd_get_param_request_done (GstRTSPWFDClient * client,
188     GstRTSPContext * ctx);
189 static void handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx);
190 static void handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx);
191 static void wfd_set_keep_alive_condition (GstRTSPWFDClient * client);
192 static gboolean wfd_ckeck_keep_alive_response (gpointer userdata);
193 static gboolean keep_alive_condition (gpointer userdata);
194 static gboolean wfd_configure_client_media (GstRTSPClient * client,
195     GstRTSPMedia * media, GstRTSPStream * stream, GstRTSPContext * ctx);
196
197 GstRTSPResult prepare_trigger_request (GstRTSPWFDClient * client,
198     GstRTSPMessage * request, GstWFDTriggerType trigger_type, gchar * url);
199
200 GstRTSPResult
201 prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request,
202     GstRTSPMessage * response, GstRTSPMethod method);
203
204 static GstRTSPResult handle_M1_message (GstRTSPWFDClient * client);
205 static GstRTSPResult handle_M3_message (GstRTSPWFDClient * client);
206 static GstRTSPResult handle_M4_message (GstRTSPWFDClient * client);
207 static GstRTSPResult handle_M16_message (GstRTSPWFDClient * client);
208
209 G_DEFINE_TYPE (GstRTSPWFDClient, gst_rtsp_wfd_client, GST_TYPE_RTSP_CLIENT);
210
211 static void
212 gst_rtsp_wfd_client_class_init (GstRTSPWFDClientClass * klass)
213 {
214   GObjectClass *gobject_class;
215   GstRTSPClientClass *rtsp_client_class;
216
217   g_type_class_add_private (klass, sizeof (GstRTSPWFDClientPrivate));
218
219   gobject_class = G_OBJECT_CLASS (klass);
220   rtsp_client_class = GST_RTSP_CLIENT_CLASS (klass);
221
222   gobject_class->get_property = gst_rtsp_wfd_client_get_property;
223   gobject_class->set_property = gst_rtsp_wfd_client_set_property;
224   gobject_class->finalize = gst_rtsp_wfd_client_finalize;
225
226   //klass->create_sdp = create_sdp;
227   //klass->configure_client_transport = default_configure_client_transport;
228   //klass->params_set = default_params_set;
229   //klass->params_get = default_params_get;
230
231   rtsp_client_class->handle_options_request = handle_wfd_options_request;
232   rtsp_client_class->handle_set_param_request = handle_wfd_set_param_request;
233   rtsp_client_class->handle_get_param_request = handle_wfd_get_param_request;
234   rtsp_client_class->make_path_from_uri = wfd_make_path_from_uri;
235   rtsp_client_class->configure_client_media = wfd_configure_client_media;
236
237   rtsp_client_class->handle_response = handle_wfd_response;
238   rtsp_client_class->play_request = handle_wfd_play;
239
240   gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST] =
241       g_signal_new ("wfd-options-request", G_TYPE_FROM_CLASS (klass),
242       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
243           wfd_options_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER,
244       G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
245
246   gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST] =
247       g_signal_new ("wfd-get-parameter-request", G_TYPE_FROM_CLASS (klass),
248       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
249           wfd_get_param_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER,
250       G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
251
252   gst_rtsp_client_wfd_signals[SIGNAL_WFD_KEEP_ALIVE_FAIL] =
253       g_signal_new ("wfd-keep-alive-fail", G_TYPE_FROM_CLASS (klass),
254       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
255           wfd_keep_alive_fail), NULL, NULL, g_cclosure_marshal_generic,
256       G_TYPE_NONE, 0, G_TYPE_NONE);
257
258   gst_rtsp_client_wfd_signals[SIGNAL_WFD_PLAYING_DONE] =
259       g_signal_new ("wfd-playing-done", G_TYPE_FROM_CLASS (klass),
260       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
261           wfd_playing_done), NULL, NULL, g_cclosure_marshal_generic,
262       G_TYPE_NONE, 0, G_TYPE_NONE);
263
264   gst_rtsp_client_wfd_signals[SIGNAL_WFD_RTP_STATS] =
265       g_signal_new ("wfd-rtp-stats", G_TYPE_FROM_CLASS (klass),
266       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
267           wfd_rtp_stats), NULL, NULL, g_cclosure_marshal_generic,
268       G_TYPE_NONE, 1, GST_TYPE_STRUCTURE);
269
270   gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_REQ_MSG] =
271       g_signal_new ("wfd-m3-request-msg", G_TYPE_FROM_CLASS (klass),
272       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
273           wfd_handle_m3_req_msg), NULL, NULL, g_cclosure_marshal_generic,
274       G_TYPE_STRING, 1, G_TYPE_STRING);
275
276   gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_RES_MSG] =
277       g_signal_new ("wfd-m3-response-msg", G_TYPE_FROM_CLASS (klass),
278       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
279           wfd_handle_m3_res_msg), NULL, NULL, g_cclosure_marshal_generic,
280       G_TYPE_NONE, 1, G_TYPE_STRING);
281
282   gst_rtsp_client_wfd_signals[SIGNAL_WFD_M4_REQ_MSG] =
283       g_signal_new ("wfd-m4-request-msg", G_TYPE_FROM_CLASS (klass),
284       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
285           wfd_handle_m4_req_msg), NULL, NULL, g_cclosure_marshal_generic,
286       G_TYPE_STRING, 1, G_TYPE_STRING);
287
288   gst_rtsp_client_wfd_signals[SIGNAL_WFD_SET_PARAM_MSG] =
289       g_signal_new ("wfd-set-param-msg", G_TYPE_FROM_CLASS (klass),
290       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
291           wfd_handle_set_param_msg), NULL, NULL, g_cclosure_marshal_generic,
292       G_TYPE_NONE, 1, G_TYPE_STRING);
293
294   klass->wfd_options_request = wfd_options_request_done;
295   klass->wfd_get_param_request = wfd_get_param_request_done;
296   klass->configure_client_media = wfd_configure_client_media;
297
298   GST_DEBUG_CATEGORY_INIT (rtsp_wfd_client_debug, "rtspwfdclient", 0,
299       "GstRTSPWFDClient");
300 }
301
302 static void
303 gst_rtsp_wfd_client_init (GstRTSPWFDClient * client)
304 {
305   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
306
307   g_return_if_fail (priv != NULL);
308
309   client->priv = priv;
310   priv->protection_enabled = FALSE;
311   priv->video_native_resolution = GST_WFD_VIDEO_CEA_RESOLUTION;
312   priv->video_resolution_supported = GST_WFD_CEA_640x480P60;
313   priv->audio_codec = GST_WFD_AUDIO_AAC;
314   priv->keep_alive_flag = FALSE;
315
316   g_mutex_init (&priv->keep_alive_lock);
317   g_mutex_init (&priv->stats_lock);
318
319   priv->host_address = NULL;
320
321   priv->stats_timer_id = -1;
322   priv->rtcp_stats_enabled = FALSE;
323   memset (&priv->stats, 0x00, sizeof (GstRTSPClientRTPStats));
324   priv->sink_user_agent = NULL;
325
326   GST_INFO_OBJECT (client, "Client is initialized");
327 }
328
329 /* A client is finalized when the connection is broken */
330 static void
331 gst_rtsp_wfd_client_finalize (GObject * obj)
332 {
333   GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (obj);
334   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
335
336   g_return_if_fail (GST_IS_RTSP_WFD_CLIENT (obj));
337   g_return_if_fail (priv != NULL);
338
339   GST_INFO ("finalize client %p", client);
340
341   if (priv->host_address)
342     g_free (priv->host_address);
343
344   if (priv->stats_timer_id > 0)
345     g_source_remove (priv->stats_timer_id);
346
347   if (priv->sink_user_agent) {
348     g_free (priv->sink_user_agent);
349     priv->sink_user_agent = NULL;
350   }
351
352   g_mutex_clear (&priv->keep_alive_lock);
353   g_mutex_clear (&priv->stats_lock);
354   G_OBJECT_CLASS (gst_rtsp_wfd_client_parent_class)->finalize (obj);
355 }
356
357 static void
358 gst_rtsp_wfd_client_get_property (GObject * object, guint propid,
359     GValue * value, GParamSpec * pspec)
360 {
361   //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object);
362
363   switch (propid) {
364     default:
365       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
366   }
367 }
368
369 static void
370 gst_rtsp_wfd_client_set_property (GObject * object, guint propid,
371     const GValue * value, GParamSpec * pspec)
372 {
373   //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object);
374
375   switch (propid) {
376     default:
377       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
378   }
379 }
380
381 /**
382  * gst_rtsp_wfd_client_new:
383  *
384  * Create a new #GstRTSPWFDClient instance.
385  *
386  * Returns: a new #GstRTSPWFDClient
387  */
388 GstRTSPWFDClient *
389 gst_rtsp_wfd_client_new (void)
390 {
391   GstRTSPWFDClient *result;
392
393   result = g_object_new (GST_TYPE_RTSP_WFD_CLIENT, NULL);
394
395   return result;
396 }
397
398 void
399 gst_rtsp_wfd_client_start_wfd (GstRTSPWFDClient * client)
400 {
401   GstRTSPResult res = GST_RTSP_OK;
402   GST_INFO_OBJECT (client, "gst_rtsp_wfd_client_start_wfd");
403
404   res = handle_M1_message (client);
405   if (res < GST_RTSP_OK) {
406     GST_ERROR_OBJECT (client, "handle_M1_message failed : %d", res);
407   }
408
409   return;
410 }
411
412 static gboolean
413 wfd_display_rtp_stats (gpointer userdata)
414 {
415   guint16 seqnum = 0;
416   guint64 bytes = 0;
417
418   GstRTSPWFDClient *client = NULL;
419   GstRTSPWFDClientPrivate *priv = NULL;
420
421   client = (GstRTSPWFDClient *) userdata;
422   priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
423
424   if (!priv) {
425     GST_ERROR ("No priv");
426     return FALSE;
427   }
428
429   g_mutex_lock (&priv->stats_lock);
430
431   seqnum = gst_rtsp_stream_get_current_seqnum (priv->stats.stream);
432   bytes = gst_rtsp_stream_get_udp_sent_bytes (priv->stats.stream);
433
434   GST_INFO ("----------------------------------------------------\n");
435   GST_INFO ("Sent RTP packets : %d", seqnum - priv->stats.last_seqnum);
436   GST_INFO ("Sent Bytes of RTP packets : %lld bytes",
437       bytes - priv->stats.last_sent_bytes);
438
439   priv->stats.last_seqnum = seqnum;
440   priv->stats.last_sent_bytes = bytes;
441
442   if (priv->rtcp_stats_enabled) {
443     GST_INFO ("Fraction Lost: %d", priv->stats.fraction_lost);
444     GST_INFO ("Cumulative number of packets lost: %d",
445         priv->stats.cumulative_lost_num);
446     GST_INFO ("Extended highest sequence number received: %d",
447         priv->stats.max_seqnum);
448     GST_INFO ("Interarrival Jitter: %d", priv->stats.arrival_jitter);
449     GST_INFO ("Round trip time : %d", priv->stats.rtt);
450   }
451
452   GST_INFO ("----------------------------------------------------\n");
453
454   g_mutex_unlock (&priv->stats_lock);
455
456   return TRUE;
457 }
458
459 static void
460 on_rtcp_stats (GstRTSPStream * stream, GstStructure * stats,
461     GstRTSPClient * client)
462 {
463   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
464
465   guint fraction_lost, exthighestseq, jitter, lsr, dlsr, rtt;
466   gint packetslost;
467
468   if (!priv)
469     return;
470
471   g_mutex_lock (&priv->stats_lock);
472
473   gst_structure_get_uint (stats, "rb-fractionlost", &fraction_lost);
474   gst_structure_get_int (stats, "rb-packetslost", &packetslost);
475   gst_structure_get_uint (stats, "rb-exthighestseq", &exthighestseq);
476   gst_structure_get_uint (stats, "rb-jitter", &jitter);
477   gst_structure_get_uint (stats, "rb-lsr", &lsr);
478   gst_structure_get_uint (stats, "rb-dlsr", &dlsr);
479   gst_structure_get_uint (stats, "rb-round-trip", &rtt);
480
481   if (!priv->rtcp_stats_enabled)
482     priv->rtcp_stats_enabled = TRUE;
483
484   priv->stats.stream = stream;
485   priv->stats.fraction_lost = (guint8) fraction_lost;
486   priv->stats.cumulative_lost_num += (guint32) fraction_lost;
487   priv->stats.max_seqnum = (guint16) exthighestseq;
488   priv->stats.arrival_jitter = (guint32) jitter;
489   priv->stats.lsr = (guint32) lsr;
490   priv->stats.dlsr = (guint32) dlsr;
491   priv->stats.rtt = (guint32) rtt;
492
493   g_mutex_unlock (&priv->stats_lock);
494   g_signal_emit (client, gst_rtsp_client_wfd_signals[SIGNAL_WFD_RTP_STATS], 0,
495       stats);
496 }
497
498 static gboolean
499 wfd_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media,
500     GstRTSPStream * stream, GstRTSPContext * ctx)
501 {
502   if (stream) {
503     GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
504     if (priv)
505       priv->stats.stream = stream;
506     g_signal_connect (stream, "rtcp-statistics", (GCallback) on_rtcp_stats,
507         client);
508   }
509
510   return GST_RTSP_CLIENT_CLASS (gst_rtsp_wfd_client_parent_class)->
511       configure_client_media (client, media, stream, ctx);
512 }
513
514 static void
515 wfd_options_request_done (GstRTSPWFDClient * client, GstRTSPContext * ctx)
516 {
517   GstRTSPResult res = GST_RTSP_OK;
518   GstRTSPWFDClientClass *klass = GST_RTSP_WFD_CLIENT_GET_CLASS (client);
519
520   g_return_if_fail (klass != NULL);
521
522   GST_INFO_OBJECT (client, "M2 done..");
523
524   res = handle_M3_message (client);
525   if (res < GST_RTSP_OK) {
526     GST_ERROR_OBJECT (client, "handle_M3_message failed : %d", res);
527   }
528
529   if (klass->prepare_resource) {
530     klass->prepare_resource (client, ctx);
531   }
532
533   return;
534 }
535
536 static void
537 wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext * ctx)
538 {
539   GstRTSPResult res = GST_RTSP_OK;
540   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
541   GstRTSPWFDClientClass *klass = GST_RTSP_WFD_CLIENT_GET_CLASS (client);
542
543   g_return_if_fail (priv != NULL && klass != NULL);
544
545   priv->m3_done = TRUE;
546   GST_INFO_OBJECT (client, "M3 done..");
547
548   res = handle_M4_message (client);
549   if (res < GST_RTSP_OK) {
550     GST_ERROR_OBJECT (client, "handle_M4_message failed : %d", res);
551   }
552
553   if (klass->confirm_resource) {
554     klass->confirm_resource (client, ctx);
555   }
556
557   return;
558 }
559
560 static guint
561 wfd_get_prefered_audio_codec (guint8 srcAudioCodec, guint sinkAudioCodec)
562 {
563   int i = 0;
564   guint codec = 0;
565   for (i = 0; i < 8; i++) {
566     if (((sinkAudioCodec << i) & 0x80)
567         && ((srcAudioCodec << i) & 0x80)) {
568       codec = (0x01 << (7 - i));
569       break;
570     }
571   }
572   return codec;
573 }
574
575 static guint64
576 wfd_get_prefered_resolution (guint64 srcResolution,
577     guint64 sinkResolution,
578     GstWFDVideoNativeResolution native,
579     guint32 * cMaxWidth,
580     guint32 * cMaxHeight, guint32 * cFramerate, guint32 * interleaved)
581 {
582   int i = 0;
583   guint64 resolution = 0;
584   for (i = 0; i < 32; i++) {
585     if (((sinkResolution << i) & 0x80000000)
586         && ((srcResolution << i) & 0x80000000)) {
587       resolution = ((guint64) 0x00000001 << (31 - i));
588       break;
589     }
590   }
591   switch (native) {
592     case GST_WFD_VIDEO_CEA_RESOLUTION:
593     {
594       switch (resolution) {
595         case GST_WFD_CEA_640x480P60:
596           *cMaxWidth = 640;
597           *cMaxHeight = 480;
598           *cFramerate = 60;
599           *interleaved = 0;
600           break;
601         case GST_WFD_CEA_720x480P60:
602           *cMaxWidth = 720;
603           *cMaxHeight = 480;
604           *cFramerate = 60;
605           *interleaved = 0;
606           break;
607         case GST_WFD_CEA_720x480I60:
608           *cMaxWidth = 720;
609           *cMaxHeight = 480;
610           *cFramerate = 60;
611           *interleaved = 1;
612           break;
613         case GST_WFD_CEA_720x576P50:
614           *cMaxWidth = 720;
615           *cMaxHeight = 576;
616           *cFramerate = 50;
617           *interleaved = 0;
618           break;
619         case GST_WFD_CEA_720x576I50:
620           *cMaxWidth = 720;
621           *cMaxHeight = 576;
622           *cFramerate = 50;
623           *interleaved = 1;
624           break;
625         case GST_WFD_CEA_1280x720P30:
626           *cMaxWidth = 1280;
627           *cMaxHeight = 720;
628           *cFramerate = 30;
629           *interleaved = 0;
630           break;
631         case GST_WFD_CEA_1280x720P60:
632           *cMaxWidth = 1280;
633           *cMaxHeight = 720;
634           *cFramerate = 60;
635           *interleaved = 0;
636           break;
637         case GST_WFD_CEA_1920x1080P30:
638           *cMaxWidth = 1920;
639           *cMaxHeight = 1080;
640           *cFramerate = 30;
641           *interleaved = 0;
642           break;
643         case GST_WFD_CEA_1920x1080P60:
644           *cMaxWidth = 1920;
645           *cMaxHeight = 1080;
646           *cFramerate = 60;
647           *interleaved = 0;
648           break;
649         case GST_WFD_CEA_1920x1080I60:
650           *cMaxWidth = 1920;
651           *cMaxHeight = 1080;
652           *cFramerate = 60;
653           *interleaved = 1;
654           break;
655         case GST_WFD_CEA_1280x720P25:
656           *cMaxWidth = 1280;
657           *cMaxHeight = 720;
658           *cFramerate = 25;
659           *interleaved = 0;
660           break;
661         case GST_WFD_CEA_1280x720P50:
662           *cMaxWidth = 1280;
663           *cMaxHeight = 720;
664           *cFramerate = 50;
665           *interleaved = 0;
666           break;
667         case GST_WFD_CEA_1920x1080P25:
668           *cMaxWidth = 1920;
669           *cMaxHeight = 1080;
670           *cFramerate = 25;
671           *interleaved = 0;
672           break;
673         case GST_WFD_CEA_1920x1080P50:
674           *cMaxWidth = 1920;
675           *cMaxHeight = 1080;
676           *cFramerate = 50;
677           *interleaved = 0;
678           break;
679         case GST_WFD_CEA_1920x1080I50:
680           *cMaxWidth = 1920;
681           *cMaxHeight = 1080;
682           *cFramerate = 50;
683           *interleaved = 1;
684           break;
685         case GST_WFD_CEA_1280x720P24:
686           *cMaxWidth = 1280;
687           *cMaxHeight = 720;
688           *cFramerate = 24;
689           *interleaved = 0;
690           break;
691         case GST_WFD_CEA_1920x1080P24:
692           *cMaxWidth = 1920;
693           *cMaxHeight = 1080;
694           *cFramerate = 24;
695           *interleaved = 0;
696           break;
697         default:
698           *cMaxWidth = 0;
699           *cMaxHeight = 0;
700           *cFramerate = 0;
701           *interleaved = 0;
702           break;
703       }
704     }
705       break;
706     case GST_WFD_VIDEO_VESA_RESOLUTION:
707     {
708       switch (resolution) {
709         case GST_WFD_VESA_800x600P30:
710           *cMaxWidth = 800;
711           *cMaxHeight = 600;
712           *cFramerate = 30;
713           *interleaved = 0;
714           break;
715         case GST_WFD_VESA_800x600P60:
716           *cMaxWidth = 800;
717           *cMaxHeight = 600;
718           *cFramerate = 60;
719           *interleaved = 0;
720           break;
721         case GST_WFD_VESA_1024x768P30:
722           *cMaxWidth = 1024;
723           *cMaxHeight = 768;
724           *cFramerate = 30;
725           *interleaved = 0;
726           break;
727         case GST_WFD_VESA_1024x768P60:
728           *cMaxWidth = 1024;
729           *cMaxHeight = 768;
730           *cFramerate = 60;
731           *interleaved = 0;
732           break;
733         case GST_WFD_VESA_1152x864P30:
734           *cMaxWidth = 1152;
735           *cMaxHeight = 864;
736           *cFramerate = 30;
737           *interleaved = 0;
738           break;
739         case GST_WFD_VESA_1152x864P60:
740           *cMaxWidth = 1152;
741           *cMaxHeight = 864;
742           *cFramerate = 60;
743           *interleaved = 0;
744           break;
745         case GST_WFD_VESA_1280x768P30:
746           *cMaxWidth = 1280;
747           *cMaxHeight = 768;
748           *cFramerate = 30;
749           *interleaved = 0;
750           break;
751         case GST_WFD_VESA_1280x768P60:
752           *cMaxWidth = 1280;
753           *cMaxHeight = 768;
754           *cFramerate = 60;
755           *interleaved = 0;
756           break;
757         case GST_WFD_VESA_1280x800P30:
758           *cMaxWidth = 1280;
759           *cMaxHeight = 800;
760           *cFramerate = 30;
761           *interleaved = 0;
762           break;
763         case GST_WFD_VESA_1280x800P60:
764           *cMaxWidth = 1280;
765           *cMaxHeight = 800;
766           *cFramerate = 60;
767           *interleaved = 0;
768           break;
769         case GST_WFD_VESA_1360x768P30:
770           *cMaxWidth = 1360;
771           *cMaxHeight = 768;
772           *cFramerate = 30;
773           *interleaved = 0;
774           break;
775         case GST_WFD_VESA_1360x768P60:
776           *cMaxWidth = 1360;
777           *cMaxHeight = 768;
778           *cFramerate = 60;
779           *interleaved = 0;
780           break;
781         case GST_WFD_VESA_1366x768P30:
782           *cMaxWidth = 1366;
783           *cMaxHeight = 768;
784           *cFramerate = 30;
785           *interleaved = 0;
786           break;
787         case GST_WFD_VESA_1366x768P60:
788           *cMaxWidth = 1366;
789           *cMaxHeight = 768;
790           *cFramerate = 60;
791           *interleaved = 0;
792           break;
793         case GST_WFD_VESA_1280x1024P30:
794           *cMaxWidth = 1280;
795           *cMaxHeight = 1024;
796           *cFramerate = 30;
797           *interleaved = 0;
798           break;
799         case GST_WFD_VESA_1280x1024P60:
800           *cMaxWidth = 1280;
801           *cMaxHeight = 1024;
802           *cFramerate = 60;
803           *interleaved = 0;
804           break;
805         case GST_WFD_VESA_1400x1050P30:
806           *cMaxWidth = 1400;
807           *cMaxHeight = 1050;
808           *cFramerate = 30;
809           *interleaved = 0;
810           break;
811         case GST_WFD_VESA_1400x1050P60:
812           *cMaxWidth = 1400;
813           *cMaxHeight = 1050;
814           *cFramerate = 60;
815           *interleaved = 0;
816           break;
817         case GST_WFD_VESA_1440x900P30:
818           *cMaxWidth = 1440;
819           *cMaxHeight = 900;
820           *cFramerate = 30;
821           *interleaved = 0;
822           break;
823         case GST_WFD_VESA_1440x900P60:
824           *cMaxWidth = 1440;
825           *cMaxHeight = 900;
826           *cFramerate = 60;
827           *interleaved = 0;
828           break;
829         case GST_WFD_VESA_1600x900P30:
830           *cMaxWidth = 1600;
831           *cMaxHeight = 900;
832           *cFramerate = 30;
833           *interleaved = 0;
834           break;
835         case GST_WFD_VESA_1600x900P60:
836           *cMaxWidth = 1600;
837           *cMaxHeight = 900;
838           *cFramerate = 60;
839           *interleaved = 0;
840           break;
841         case GST_WFD_VESA_1600x1200P30:
842           *cMaxWidth = 1600;
843           *cMaxHeight = 1200;
844           *cFramerate = 30;
845           *interleaved = 0;
846           break;
847         case GST_WFD_VESA_1600x1200P60:
848           *cMaxWidth = 1600;
849           *cMaxHeight = 1200;
850           *cFramerate = 60;
851           *interleaved = 0;
852           break;
853         case GST_WFD_VESA_1680x1024P30:
854           *cMaxWidth = 1680;
855           *cMaxHeight = 1024;
856           *cFramerate = 30;
857           *interleaved = 0;
858           break;
859         case GST_WFD_VESA_1680x1024P60:
860           *cMaxWidth = 1680;
861           *cMaxHeight = 1024;
862           *cFramerate = 60;
863           *interleaved = 0;
864           break;
865         case GST_WFD_VESA_1680x1050P30:
866           *cMaxWidth = 1680;
867           *cMaxHeight = 1050;
868           *cFramerate = 30;
869           *interleaved = 0;
870           break;
871         case GST_WFD_VESA_1680x1050P60:
872           *cMaxWidth = 1680;
873           *cMaxHeight = 1050;
874           *cFramerate = 60;
875           *interleaved = 0;
876           break;
877         case GST_WFD_VESA_1920x1200P30:
878           *cMaxWidth = 1920;
879           *cMaxHeight = 1200;
880           *cFramerate = 30;
881           *interleaved = 0;
882           break;
883         case GST_WFD_VESA_1920x1200P60:
884           *cMaxWidth = 1920;
885           *cMaxHeight = 1200;
886           *cFramerate = 60;
887           *interleaved = 0;
888           break;
889         default:
890           *cMaxWidth = 0;
891           *cMaxHeight = 0;
892           *cFramerate = 0;
893           *interleaved = 0;
894           break;
895       }
896     }
897       break;
898     case GST_WFD_VIDEO_HH_RESOLUTION:
899     {
900       *interleaved = 0;
901       switch (resolution) {
902         case GST_WFD_HH_800x480P30:
903           *cMaxWidth = 800;
904           *cMaxHeight = 480;
905           *cFramerate = 30;
906           break;
907         case GST_WFD_HH_800x480P60:
908           *cMaxWidth = 800;
909           *cMaxHeight = 480;
910           *cFramerate = 60;
911           break;
912         case GST_WFD_HH_854x480P30:
913           *cMaxWidth = 854;
914           *cMaxHeight = 480;
915           *cFramerate = 30;
916           break;
917         case GST_WFD_HH_854x480P60:
918           *cMaxWidth = 854;
919           *cMaxHeight = 480;
920           *cFramerate = 60;
921           break;
922         case GST_WFD_HH_864x480P30:
923           *cMaxWidth = 864;
924           *cMaxHeight = 480;
925           *cFramerate = 30;
926           break;
927         case GST_WFD_HH_864x480P60:
928           *cMaxWidth = 864;
929           *cMaxHeight = 480;
930           *cFramerate = 60;
931           break;
932         case GST_WFD_HH_640x360P30:
933           *cMaxWidth = 640;
934           *cMaxHeight = 360;
935           *cFramerate = 30;
936           break;
937         case GST_WFD_HH_640x360P60:
938           *cMaxWidth = 640;
939           *cMaxHeight = 360;
940           *cFramerate = 60;
941           break;
942         case GST_WFD_HH_960x540P30:
943           *cMaxWidth = 960;
944           *cMaxHeight = 540;
945           *cFramerate = 30;
946           break;
947         case GST_WFD_HH_960x540P60:
948           *cMaxWidth = 960;
949           *cMaxHeight = 540;
950           *cFramerate = 60;
951           break;
952         case GST_WFD_HH_848x480P30:
953           *cMaxWidth = 848;
954           *cMaxHeight = 480;
955           *cFramerate = 30;
956           break;
957         case GST_WFD_HH_848x480P60:
958           *cMaxWidth = 848;
959           *cMaxHeight = 480;
960           *cFramerate = 60;
961           break;
962         default:
963           *cMaxWidth = 0;
964           *cMaxHeight = 0;
965           *cFramerate = 0;
966           *interleaved = 0;
967           break;
968       }
969     }
970       break;
971
972     default:
973       *cMaxWidth = 0;
974       *cMaxHeight = 0;
975       *cFramerate = 0;
976       *interleaved = 0;
977       break;
978   }
979   return resolution;
980 }
981
982 static gchar *
983 wfd_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri)
984 {
985   gchar *path;
986
987   GST_DEBUG_OBJECT (client, "Got URI host : %s", uri->host);
988   GST_DEBUG_OBJECT (client, "Got URI abspath : %s", uri->abspath);
989
990   path = g_strdup ("/wfd1.0/streamid=0");
991
992   return path;
993 }
994
995 static void
996 handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx)
997 {
998   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
999   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
1000
1001   g_return_if_fail (priv != NULL);
1002
1003   wfd_set_keep_alive_condition (_client);
1004
1005   priv->stats_timer_id = g_timeout_add (2000, wfd_display_rtp_stats, _client);
1006
1007   g_signal_emit (client,
1008       gst_rtsp_client_wfd_signals[SIGNAL_WFD_PLAYING_DONE], 0, NULL);
1009 }
1010
1011 static void
1012 handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx)
1013 {
1014   GstRTSPResult res = GST_RTSP_OK;
1015   guint8 *data = NULL;
1016   guint size = 0;
1017
1018   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
1019   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
1020
1021   g_return_if_fail (priv != NULL);
1022
1023   GST_INFO_OBJECT (_client, "Handling response..");
1024
1025   if (!ctx) {
1026     GST_ERROR_OBJECT (_client, "Context is NULL");
1027     goto error;
1028   }
1029
1030   if (!ctx->response) {
1031     GST_ERROR_OBJECT (_client, "Response is NULL");
1032     goto error;
1033   }
1034
1035   if (priv->sink_user_agent == NULL) {
1036     gchar *user_agent = NULL;
1037     gst_rtsp_message_get_header (ctx->response, GST_RTSP_HDR_USER_AGENT,
1038         &user_agent, 0);
1039     priv->sink_user_agent = g_strdup (user_agent);
1040
1041     GST_INFO_OBJECT (_client, "sink user_agent : %s", priv->sink_user_agent);
1042   }
1043
1044   /* parsing the GET_PARAMTER response */
1045   res = gst_rtsp_message_get_body (ctx->response, (guint8 **) & data, &size);
1046   if (res != GST_RTSP_OK) {
1047     GST_ERROR_OBJECT (_client, "Failed to get body of response...");
1048     return;
1049   }
1050
1051   GST_INFO_OBJECT (_client, "Response body is %d", size);
1052   if (size > 0) {
1053     if (!priv->m3_done) {
1054       GstWFDResult wfd_res;
1055       GstWFDMessage *msg = NULL;
1056       /* Parse M3 response from sink */
1057       wfd_res = gst_wfd_message_new (&msg);
1058       if (wfd_res != GST_WFD_OK) {
1059         GST_ERROR_OBJECT (client, "Failed to create wfd message...");
1060         goto error;
1061       }
1062
1063       wfd_res = gst_wfd_message_init (msg);
1064       if (wfd_res != GST_WFD_OK) {
1065         GST_ERROR_OBJECT (client, "Failed to init wfd message...");
1066         goto error;
1067       }
1068
1069       wfd_res = gst_wfd_message_parse_buffer (data, size, msg);
1070
1071       GST_DEBUG_OBJECT (client, "M3 response server side message body: %s",
1072           gst_wfd_message_as_text (msg));
1073
1074       /* Get the audio formats supported by WFDSink */
1075       if (msg->audio_codecs) {
1076         wfd_res =
1077             gst_wfd_message_get_supported_audio_format (msg, &priv->caCodec,
1078             &priv->cFreq, &priv->cChanels, &priv->cBitwidth, &priv->caLatency);
1079         if (wfd_res != GST_WFD_OK) {
1080           GST_WARNING_OBJECT (client,
1081               "Failed to get wfd support audio formats...");
1082           goto error;
1083         }
1084       }
1085
1086       /* Get the Video formats supported by WFDSink */
1087       wfd_res =
1088           gst_wfd_message_get_supported_video_format (msg, &priv->cvCodec,
1089           &priv->cNative, &priv->cNativeResolution,
1090           (guint64 *) & priv->cCEAResolution,
1091           (guint64 *) & priv->cVESAResolution,
1092           (guint64 *) & priv->cHHResolution, &priv->cProfile, &priv->cLevel,
1093           &priv->cvLatency, &priv->cMaxHeight, &priv->cMaxWidth,
1094           &priv->cmin_slice_size, &priv->cslice_enc_params,
1095           &priv->cframe_rate_control);
1096       if (wfd_res != GST_WFD_OK) {
1097         GST_WARNING_OBJECT (client,
1098             "Failed to get wfd supported video formats...");
1099         goto error;
1100       }
1101
1102       if (msg->client_rtp_ports) {
1103         /* Get the RTP ports preferred by WFDSink */
1104         wfd_res =
1105             gst_wfd_message_get_prefered_rtp_ports (msg, &priv->ctrans,
1106             &priv->cprofile, &priv->clowertrans, &priv->crtp_port0,
1107             &priv->crtp_port1);
1108         if (wfd_res != GST_WFD_OK) {
1109           GST_WARNING_OBJECT (client,
1110               "Failed to get wfd prefered RTP ports...");
1111           goto error;
1112         }
1113       }
1114
1115       if (msg->display_edid) {
1116         guint32 edid_block_count = 0;
1117         gchar *edid_payload = NULL;
1118         priv->edid_supported = FALSE;
1119         /* Get the display edid preferred by WFDSink */
1120         GST_DEBUG_OBJECT (client, "Going to gst_wfd_message_get_display_edid");
1121         wfd_res =
1122             gst_wfd_message_get_display_edid (msg, &priv->edid_supported,
1123             &edid_block_count, &edid_payload);
1124         if (wfd_res != GST_WFD_OK) {
1125           GST_ERROR_OBJECT (client, "Failed to get wfd display edid...");
1126           goto error;
1127         }
1128         GST_DEBUG_OBJECT (client, " edid supported: %d edid_block_count: %d",
1129             priv->edid_supported, edid_block_count);
1130         if (priv->edid_supported) {
1131           priv->edid_hres = 0;
1132           priv->edid_vres = 0;
1133           priv->edid_hres =
1134               (guint32) (((edid_payload[54 + 4] >> 4) << 8) | edid_payload[54 +
1135                   2]);
1136           priv->edid_vres =
1137               (guint32) (((edid_payload[54 + 7] >> 4) << 8) | edid_payload[54 +
1138                   5]);
1139           GST_DEBUG_OBJECT (client, " edid supported Hres: %d Wres: %d",
1140               priv->edid_hres, priv->edid_vres);
1141           if ((priv->edid_hres < 640) || (priv->edid_vres < 480)
1142               || (priv->edid_hres > 1920) || (priv->edid_vres > 1080)) {
1143             priv->edid_hres = 0;
1144             priv->edid_vres = 0;
1145             priv->edid_supported = FALSE;
1146             GST_WARNING_OBJECT (client, " edid invalid resolutions");
1147           }
1148         }
1149       }
1150
1151       if (msg->content_protection) {
1152 #if 0
1153         /*Get the hdcp version and tcp port by WFDSink */
1154         wfd_res =
1155             gst_wfd_message_get_contentprotection_type (msg,
1156             &priv->hdcp_version, &priv->hdcp_tcpport);
1157         GST_DEBUG ("hdcp version =%d, tcp port = %d", priv->hdcp_version,
1158             priv->hdcp_tcpport);
1159         if (priv->hdcp_version > 0 && priv->hdcp_tcpport > 0)
1160           priv->protection_enabled = TRUE;
1161
1162         if (wfd_res != GST_WFD_OK) {
1163           GST_WARNING_OBJECT (client,
1164               "Failed to get wfd content protection...");
1165           goto error;
1166         }
1167 #else
1168         GST_WARNING_OBJECT (client, "Don't use content protection");
1169 #endif
1170       }
1171
1172       g_signal_emit (client,
1173           gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_RES_MSG], 0, data);
1174
1175       g_signal_emit (_client,
1176           gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST], 0,
1177           ctx);
1178     } else {
1179       /* TODO-WFD: Handle another GET_PARAMETER response with body */
1180     }
1181   } else if (size == 0) {
1182     if (!priv->m1_done) {
1183       GST_INFO_OBJECT (_client, "M1 response is done");
1184       priv->m1_done = TRUE;
1185     } else if (!priv->m4_done) {
1186       GST_INFO_OBJECT (_client, "M4 response is done");
1187       priv->m4_done = TRUE;
1188
1189       gst_rtsp_wfd_client_trigger_request (_client, WFD_TRIGGER_SETUP);
1190     } else {
1191       g_mutex_lock (&priv->keep_alive_lock);
1192       if (priv->keep_alive_flag == FALSE) {
1193         GST_INFO_OBJECT (_client, "M16 response is done");
1194         priv->keep_alive_flag = TRUE;
1195       }
1196       g_mutex_unlock (&priv->keep_alive_lock);
1197     }
1198   }
1199
1200   return;
1201
1202 error:
1203   return;
1204 }
1205
1206 static gboolean
1207 handle_wfd_options_request (GstRTSPClient * client, GstRTSPContext * ctx)
1208 {
1209   GstRTSPResult res = GST_RTSP_OK;
1210   GstRTSPMethod options;
1211   gchar *tmp = NULL;
1212   gchar *str = NULL;
1213   gchar *user_agent = NULL;
1214
1215   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
1216
1217   options = GST_RTSP_OPTIONS |
1218       GST_RTSP_PAUSE |
1219       GST_RTSP_PLAY |
1220       GST_RTSP_SETUP |
1221       GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
1222
1223   str = gst_rtsp_options_as_text (options);
1224
1225   /*append WFD specific method */
1226   tmp = g_strdup (", org.wfa.wfd1.0");
1227   g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
1228
1229   gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK,
1230       gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request);
1231
1232   gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_PUBLIC, str);
1233   g_free (str);
1234   g_free (tmp);
1235
1236   str = NULL;
1237
1238   res =
1239       gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_USER_AGENT,
1240       &user_agent, 0);
1241   if (res == GST_RTSP_OK) {
1242     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_USER_AGENT,
1243         user_agent);
1244   } else {
1245     return FALSE;
1246   }
1247
1248   res = gst_rtsp_client_send_message (client, NULL, ctx->response);
1249   if (res != GST_RTSP_OK) {
1250     GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
1251     return FALSE;
1252   }
1253
1254   GST_DEBUG_OBJECT (client, "Sent M2 response...");
1255
1256   g_signal_emit (_client,
1257       gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST], 0, ctx);
1258
1259   return TRUE;
1260 }
1261
1262 static gboolean
1263 handle_wfd_get_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
1264 {
1265   GstRTSPResult res = GST_RTSP_OK;
1266   guint8 *data = NULL;
1267   guint size = 0;
1268
1269   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
1270
1271   /* parsing the GET_PARAMTER request */
1272   res = gst_rtsp_message_get_body (ctx->request, (guint8 **) & data, &size);
1273   if (res != GST_RTSP_OK) {
1274     GST_ERROR_OBJECT (_client, "Failed to get body of request...");
1275     return FALSE;
1276   }
1277
1278   if (size == 0) {
1279     send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1280   } else {
1281     /* TODO-WFD: Handle other GET_PARAMETER request from sink */
1282   }
1283
1284   return TRUE;
1285 }
1286
1287 static gboolean
1288 handle_wfd_set_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
1289 {
1290   GstRTSPResult res = GST_RTSP_OK;
1291   guint8 *data = NULL;
1292   guint size = 0;
1293
1294   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
1295
1296   res = gst_rtsp_message_get_body (ctx->request, &data, &size);
1297   if (res != GST_RTSP_OK)
1298     goto bad_request;
1299
1300   if (size == 0) {
1301     /* no body, keep-alive request */
1302     send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1303   } else {
1304     if (data != NULL) {
1305       GST_INFO_OBJECT (_client, "SET_PARAMETER Request : %s(%d)", data, size);
1306       if (g_strcmp0 ((const gchar *) data, "wfd_idr_request"))
1307         send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1308       else {
1309         send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1310         g_signal_emit (client,
1311             gst_rtsp_client_wfd_signals[SIGNAL_WFD_SET_PARAM_MSG], 0, data);
1312       }
1313     } else {
1314       goto bad_request;
1315     }
1316   }
1317
1318   return TRUE;
1319
1320   /* ERRORS */
1321 bad_request:
1322   {
1323     GST_ERROR ("_client %p: bad request", _client);
1324     send_generic_wfd_response (_client, GST_RTSP_STS_BAD_REQUEST, ctx);
1325     return FALSE;
1326   }
1327 }
1328
1329 #if 0
1330 static gboolean
1331 gst_rtsp_wfd_client_parse_methods (GstRTSPWFDClient * client,
1332     GstRTSPMessage * response)
1333 {
1334   GstRTSPHeaderField field;
1335   gchar *respoptions;
1336   gchar **options;
1337   gint indx = 0;
1338   gint i;
1339   gboolean found_wfd_method = FALSE;
1340
1341   /* reset supported methods */
1342   client->supported_methods = 0;
1343
1344   /* Try Allow Header first */
1345   field = GST_RTSP_HDR_ALLOW;
1346   while (TRUE) {
1347     respoptions = NULL;
1348     gst_rtsp_message_get_header (response, field, &respoptions, indx);
1349     if (indx == 0 && !respoptions) {
1350       /* if no Allow header was found then try the Public header... */
1351       field = GST_RTSP_HDR_PUBLIC;
1352       gst_rtsp_message_get_header (response, field, &respoptions, indx);
1353     }
1354     if (!respoptions)
1355       break;
1356
1357     /* If we get here, the server gave a list of supported methods, parse
1358      * them here. The string is like:
1359      *
1360      * OPTIONS,  PLAY, SETUP, ...
1361      */
1362     options = g_strsplit (respoptions, ",", 0);
1363
1364     for (i = 0; options[i]; i++) {
1365       gchar *stripped;
1366       gint method;
1367
1368       stripped = g_strstrip (options[i]);
1369       method = gst_rtsp_find_method (stripped);
1370
1371       if (!g_ascii_strcasecmp ("org.wfa.wfd1.0", stripped))
1372         found_wfd_method = TRUE;
1373
1374       /* keep bitfield of supported methods */
1375       if (method != GST_RTSP_INVALID)
1376         client->supported_methods |= method;
1377     }
1378     g_strfreev (options);
1379
1380     indx++;
1381   }
1382
1383   if (!found_wfd_method) {
1384     GST_ERROR_OBJECT (client,
1385         "WFD client is not supporting WFD mandatory message : org.wfa.wfd1.0...");
1386     goto no_required_methods;
1387   }
1388
1389   /* Checking mandatory method */
1390   if (!(client->supported_methods & GST_RTSP_SET_PARAMETER)) {
1391     GST_ERROR_OBJECT (client,
1392         "WFD client is not supporting WFD mandatory message : SET_PARAMETER...");
1393     goto no_required_methods;
1394   }
1395
1396   /* Checking mandatory method */
1397   if (!(client->supported_methods & GST_RTSP_GET_PARAMETER)) {
1398     GST_ERROR_OBJECT (client,
1399         "WFD client is not supporting WFD mandatory message : GET_PARAMETER...");
1400     goto no_required_methods;
1401   }
1402
1403   if (!(client->supported_methods & GST_RTSP_OPTIONS)) {
1404     GST_INFO_OBJECT (client, "assuming OPTIONS is supported by client...");
1405     client->supported_methods |= GST_RTSP_OPTIONS;
1406   }
1407
1408   return TRUE;
1409
1410 /* ERRORS */
1411 no_required_methods:
1412   {
1413     GST_ELEMENT_ERROR (client, RESOURCE, OPEN_READ, (NULL),
1414         ("WFD Client does not support mandatory methods."));
1415     return FALSE;
1416   }
1417 }
1418 #endif
1419
1420 typedef enum
1421 {
1422   M1_REQ_MSG,
1423   M1_RES_MSG,
1424   M2_REQ_MSG,
1425   M2_RES_MSG,
1426   M3_REQ_MSG,
1427   M3_RES_MSG,
1428   M4_REQ_MSG,
1429   M4_RES_MSG,
1430   M5_REQ_MSG,
1431   TEARDOWN_TRIGGER,
1432   PLAY_TRIGGER,
1433   PAUSE_TRIGGER,
1434 } GstWFDMessageType;
1435
1436 static gboolean
1437 _set_negotiated_audio_codec (GstRTSPWFDClient * client, guint audio_codec)
1438 {
1439   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1440
1441   GstRTSPMediaFactory *factory = NULL;
1442   GstRTSPMountPoints *mount_points = NULL;
1443   gchar *path = NULL;
1444   gint matched = 0;
1445   gboolean ret = TRUE;
1446
1447   if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) {
1448     ret = FALSE;
1449     GST_ERROR_OBJECT (client,
1450         "Failed to set negotiated audio codec: no mount points...");
1451     goto no_mount_points;
1452   }
1453
1454   path = g_strdup (WFD_MOUNT_POINT);
1455   if (!path) {
1456     ret = FALSE;
1457     GST_ERROR_OBJECT (client,
1458         "Failed to set negotiated audio codec: no path...");
1459     goto no_path;
1460   }
1461
1462   if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) {
1463     GST_ERROR_OBJECT (client,
1464         "Failed to set negotiated audio codec: no factory...");
1465     ret = FALSE;
1466     goto no_factory;
1467   }
1468
1469   gst_rtsp_media_factory_wfd_set_audio_codec (factory, audio_codec);
1470   ret = TRUE;
1471
1472   g_object_unref (factory);
1473
1474 no_factory:
1475   g_free (path);
1476 no_path:
1477   g_object_unref (mount_points);
1478 no_mount_points:
1479   return ret;
1480 }
1481
1482 static gboolean
1483 _set_negotiated_resolution (GstRTSPWFDClient * client,
1484     guint32 width, guint32 height)
1485 {
1486   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1487
1488   GstRTSPMediaFactory *factory = NULL;
1489   GstRTSPMountPoints *mount_points = NULL;
1490   gchar *path = NULL;
1491   gint matched = 0;
1492   gboolean ret = TRUE;
1493
1494   if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) {
1495     ret = FALSE;
1496     GST_ERROR_OBJECT (client,
1497         "Failed to set negotiated resolution: no mount points...");
1498     goto no_mount_points;
1499   }
1500
1501   path = g_strdup (WFD_MOUNT_POINT);
1502   if (!path) {
1503     ret = FALSE;
1504     GST_ERROR_OBJECT (client,
1505         "Failed to set negotiated resolution: no path...");
1506     goto no_path;
1507   }
1508
1509   if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) {
1510     GST_ERROR_OBJECT (client,
1511         "Failed to set negotiated resolution: no factory...");
1512     ret = FALSE;
1513     goto no_factory;
1514   }
1515
1516   gst_rtsp_media_factory_wfd_set_negotiated_resolution (factory, width, height);
1517   ret = TRUE;
1518
1519   g_object_unref (factory);
1520
1521 no_factory:
1522   g_free (path);
1523 no_path:
1524   g_object_unref (mount_points);
1525 no_mount_points:
1526   return ret;
1527 }
1528
1529 static void
1530 _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type,
1531     gchar ** data, guint * len)
1532 {
1533   GString *buf = NULL;
1534   GstWFDMessage *msg = NULL;
1535   GstWFDResult wfd_res = GST_WFD_EINVAL;
1536   GstRTSPWFDClientPrivate *priv = NULL;
1537   priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
1538
1539   g_return_if_fail (priv != NULL);
1540
1541   buf = g_string_new ("");
1542   g_return_if_fail (buf != NULL);
1543
1544   if (msg_type == M3_REQ_MSG) {
1545     /* create M3 request to be sent */
1546     wfd_res = gst_wfd_message_new (&msg);
1547     if (wfd_res != GST_WFD_OK) {
1548       GST_ERROR_OBJECT (client, "Failed to create wfd message...");
1549       goto error;
1550     }
1551
1552     wfd_res = gst_wfd_message_init (msg);
1553     if (wfd_res != GST_WFD_OK) {
1554       GST_ERROR_OBJECT (client, "Failed to init wfd message...");
1555       goto error;
1556     }
1557
1558     /* set the supported audio formats by the WFD server */
1559     wfd_res =
1560         gst_wfd_message_set_supported_audio_format (msg, GST_WFD_AUDIO_UNKNOWN,
1561         GST_WFD_FREQ_UNKNOWN, GST_WFD_CHANNEL_UNKNOWN, 0, 0);
1562     if (wfd_res != GST_WFD_OK) {
1563       GST_ERROR_OBJECT (client,
1564           "Failed to set supported audio formats on wfd message...");
1565       goto error;
1566     }
1567
1568     /* set the supported Video formats by the WFD server */
1569     wfd_res =
1570         gst_wfd_message_set_supported_video_format (msg, GST_WFD_VIDEO_UNKNOWN,
1571         GST_WFD_VIDEO_CEA_RESOLUTION, GST_WFD_CEA_UNKNOWN, GST_WFD_CEA_UNKNOWN,
1572         GST_WFD_VESA_UNKNOWN, GST_WFD_HH_UNKNOWN, GST_WFD_H264_UNKNOWN_PROFILE,
1573         GST_WFD_H264_LEVEL_UNKNOWN, 0, 0, 0, 0, 0, 0);
1574     if (wfd_res != GST_WFD_OK) {
1575       GST_ERROR_OBJECT (client,
1576           "Failed to set supported video formats on wfd message...");
1577       goto error;
1578     }
1579
1580     wfd_res = gst_wfd_message_set_display_edid (msg, 0, 0, NULL);
1581     if (wfd_res != GST_WFD_OK) {
1582       GST_ERROR_OBJECT (client,
1583           "Failed to set display edid type on wfd message...");
1584       goto error;
1585     }
1586
1587     if (priv->protection_enabled) {
1588       wfd_res =
1589           gst_wfd_message_set_contentprotection_type (msg, GST_WFD_HDCP_NONE,
1590           0);
1591       if (wfd_res != GST_WFD_OK) {
1592         GST_ERROR_OBJECT (client,
1593             "Failed to set supported content protection type on wfd message...");
1594         goto error;
1595       }
1596     }
1597
1598     /* set the preffered RTP ports for the WFD server */
1599     wfd_res =
1600         gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_UNKNOWN,
1601         GST_WFD_RTSP_PROFILE_UNKNOWN, GST_WFD_RTSP_LOWER_TRANS_UNKNOWN, 0, 0);
1602     if (wfd_res != GST_WFD_OK) {
1603       GST_ERROR_OBJECT (client,
1604           "Failed to set supported video formats on wfd message...");
1605       goto error;
1606     }
1607
1608     *data = gst_wfd_message_param_names_as_text (msg);
1609     if (*data == NULL) {
1610       GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
1611       goto error;
1612     } else {
1613       gchar *append_data = NULL;
1614
1615       g_signal_emit (client, gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_REQ_MSG],
1616           0, *data, &append_data);
1617
1618       if (append_data) {
1619         g_free (*data);
1620         *data = append_data;
1621       }
1622
1623       *len = strlen (*data);
1624     }
1625   } else if (msg_type == M4_REQ_MSG) {
1626     GstRTSPUrl *url = NULL;
1627
1628     GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1629     GstRTSPConnection *connection =
1630         gst_rtsp_client_get_connection (parent_client);
1631
1632     /* Parameters for the preffered audio formats */
1633     GstWFDAudioFormats taudiocodec = GST_WFD_AUDIO_UNKNOWN;
1634     GstWFDAudioFreq taudiofreq = GST_WFD_FREQ_UNKNOWN;
1635     GstWFDAudioChannels taudiochannels = GST_WFD_CHANNEL_UNKNOWN;
1636
1637     /* Parameters for the preffered video formats */
1638     GstWFDVideoCEAResolution tcCEAResolution = GST_WFD_CEA_UNKNOWN;
1639     GstWFDVideoVESAResolution tcVESAResolution = GST_WFD_VESA_UNKNOWN;
1640     GstWFDVideoHHResolution tcHHResolution = GST_WFD_HH_UNKNOWN;
1641     GstWFDVideoH264Profile tcProfile;
1642     GstWFDVideoH264Level tcLevel;
1643     guint64 resolution_supported = 0;
1644
1645     url = gst_rtsp_connection_get_url (connection);
1646     if (url == NULL) {
1647       GST_ERROR_OBJECT (client, "Failed to get connection URL");
1648       return;
1649     }
1650
1651     /* Logic to negotiate with information of M3 response */
1652     /* create M4 request to be sent */
1653     wfd_res = gst_wfd_message_new (&msg);
1654     if (wfd_res != GST_WFD_OK) {
1655       GST_ERROR_OBJECT (client, "Failed to create wfd message...");
1656       goto error;
1657     }
1658
1659     wfd_res = gst_wfd_message_init (msg);
1660     if (wfd_res != GST_WFD_OK) {
1661       GST_ERROR_OBJECT (client, "Failed to init wfd message...");
1662       goto error;
1663     }
1664
1665     g_string_append_printf (buf, "rtsp://");
1666
1667     if (priv->host_address) {
1668       g_string_append (buf, priv->host_address);
1669     } else {
1670       GST_ERROR_OBJECT (client, "Failed to get host address");
1671       if (buf)
1672         g_string_free (buf, TRUE);
1673       goto error;
1674     }
1675
1676     g_string_append_printf (buf, "/wfd1.0/streamid=0");
1677     wfd_res =
1678         gst_wfd_message_set_presentation_url (msg, g_string_free (buf, FALSE),
1679         NULL);
1680
1681     if (wfd_res != GST_WFD_OK) {
1682       GST_ERROR_OBJECT (client, "Failed to set presentation url");
1683       goto error;
1684     }
1685
1686     taudiocodec =
1687         wfd_get_prefered_audio_codec (priv->audio_codec, priv->caCodec);
1688     priv->caCodec = taudiocodec;
1689     if (!_set_negotiated_audio_codec (client, priv->caCodec)) {
1690       GST_ERROR_OBJECT (client, "Failed to set negotiated "
1691           "audio codec to media factory...");
1692     }
1693
1694     if (priv->cFreq & GST_WFD_FREQ_48000)
1695       taudiofreq = GST_WFD_FREQ_48000;
1696     else if (priv->cFreq & GST_WFD_FREQ_44100)
1697       taudiofreq = GST_WFD_FREQ_44100;
1698     priv->cFreq = taudiofreq;
1699
1700     /* TODO-WFD: Currently only 2 channels is present */
1701     if (priv->cChanels & GST_WFD_CHANNEL_8)
1702       taudiochannels = GST_WFD_CHANNEL_2;
1703     else if (priv->cChanels & GST_WFD_CHANNEL_6)
1704       taudiochannels = GST_WFD_CHANNEL_2;
1705     else if (priv->cChanels & GST_WFD_CHANNEL_4)
1706       taudiochannels = GST_WFD_CHANNEL_2;
1707     else if (priv->cChanels & GST_WFD_CHANNEL_2)
1708       taudiochannels = GST_WFD_CHANNEL_2;
1709     priv->cChanels = taudiochannels;
1710
1711     wfd_res =
1712         gst_wfd_message_set_prefered_audio_format (msg, taudiocodec, taudiofreq,
1713         taudiochannels, priv->cBitwidth, priv->caLatency);
1714     if (wfd_res != GST_WFD_OK) {
1715       GST_ERROR_OBJECT (priv, "Failed to set preffered audio formats...");
1716       goto error;
1717     }
1718
1719     /* Set the preffered video formats */
1720     priv->cvCodec = GST_WFD_VIDEO_H264;
1721     priv->cProfile = tcProfile = GST_WFD_H264_BASE_PROFILE;
1722     priv->cLevel = tcLevel = GST_WFD_H264_LEVEL_3_1;
1723
1724     resolution_supported = priv->video_resolution_supported;
1725
1726     /* TODO-WFD: Need to verify this logic
1727        if(priv->edid_supported) {
1728        if (priv->edid_hres < 1920) resolution_supported = resolution_supported & 0x8C7F;
1729        if (priv->edid_hres < 1280) resolution_supported = resolution_supported & 0x1F;
1730        if (priv->edid_hres < 720) resolution_supported = resolution_supported & 0x01;
1731        }
1732      */
1733
1734     if (priv->video_native_resolution == GST_WFD_VIDEO_CEA_RESOLUTION) {
1735       tcCEAResolution =
1736           wfd_get_prefered_resolution (resolution_supported,
1737           priv->cCEAResolution, priv->video_native_resolution, &priv->cMaxWidth,
1738           &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved);
1739       GST_DEBUG
1740           ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1741           tcCEAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1742           priv->cInterleaved);
1743     } else if (priv->video_native_resolution == GST_WFD_VIDEO_VESA_RESOLUTION) {
1744       tcVESAResolution =
1745           wfd_get_prefered_resolution (resolution_supported,
1746           priv->cVESAResolution, priv->video_native_resolution,
1747           &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate,
1748           &priv->cInterleaved);
1749       GST_DEBUG
1750           ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1751           tcVESAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1752           priv->cInterleaved);
1753     } else if (priv->video_native_resolution == GST_WFD_VIDEO_HH_RESOLUTION) {
1754       tcHHResolution =
1755           wfd_get_prefered_resolution (resolution_supported,
1756           priv->cHHResolution, priv->video_native_resolution, &priv->cMaxWidth,
1757           &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved);
1758       GST_DEBUG
1759           ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1760           tcHHResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1761           priv->cInterleaved);
1762     }
1763
1764     if (!_set_negotiated_resolution (client, priv->cMaxWidth, priv->cMaxHeight)) {
1765       GST_ERROR_OBJECT (client, "Failed to set negotiated "
1766           "resolution to media factory...");
1767     }
1768
1769     wfd_res =
1770         gst_wfd_message_set_prefered_video_format (msg, priv->cvCodec,
1771         priv->video_native_resolution, GST_WFD_CEA_UNKNOWN, tcCEAResolution,
1772         tcVESAResolution, tcHHResolution, tcProfile, tcLevel, priv->cvLatency,
1773         priv->cMaxWidth, priv->cMaxHeight, priv->cmin_slice_size,
1774         priv->cslice_enc_params, priv->cframe_rate_control);
1775
1776     if (wfd_res != GST_WFD_OK) {
1777       GST_ERROR_OBJECT (client, "Failed to set preffered video formats...");
1778       goto error;
1779     }
1780
1781     /* set the preffered RTP ports for the WFD server */
1782     wfd_res =
1783         gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP,
1784         GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP,
1785         priv->crtp_port0, priv->crtp_port1);
1786     if (wfd_res != GST_WFD_OK) {
1787       GST_ERROR_OBJECT (client,
1788           "Failed to set supported video formats on wfd message...");
1789       goto error;
1790     }
1791
1792     *data = gst_wfd_message_as_text (msg);
1793     if (*data == NULL) {
1794       GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
1795       goto error;
1796     } else {
1797       gchar *append_data = NULL;
1798
1799       g_signal_emit (client,
1800           gst_rtsp_client_wfd_signals[SIGNAL_WFD_M4_REQ_MSG], 0, *data,
1801           &append_data);
1802
1803       if (append_data) {
1804         g_free (*data);
1805         *data = append_data;
1806       }
1807       *len = strlen (*data);
1808     }
1809   } else if (msg_type == M5_REQ_MSG) {
1810     g_string_append (buf, "wfd_trigger_method: SETUP");
1811     g_string_append (buf, "\r\n");
1812     *len = buf->len;
1813     *data = g_string_free (buf, FALSE);
1814   } else if (msg_type == TEARDOWN_TRIGGER) {
1815     g_string_append (buf, "wfd_trigger_method: TEARDOWN");
1816     g_string_append (buf, "\r\n");
1817     *len = buf->len;
1818     *data = g_string_free (buf, FALSE);
1819   } else if (msg_type == PLAY_TRIGGER) {
1820     g_string_append (buf, "wfd_trigger_method: PLAY");
1821     g_string_append (buf, "\r\n");
1822     *len = buf->len;
1823     *data = g_string_free (buf, FALSE);
1824   } else if (msg_type == PAUSE_TRIGGER) {
1825     g_string_append (buf, "wfd_trigger_method: PAUSE");
1826     g_string_append (buf, "\r\n");
1827     *len = buf->len;
1828     *data = g_string_free (buf, FALSE);
1829   } else {
1830     return;
1831   }
1832
1833   return;
1834
1835 error:
1836   *data = NULL;
1837   *len = 0;
1838
1839   return;
1840 }
1841
1842 /**
1843 * gst_prepare_request:
1844 * @client: client object
1845 * @request : requst message to be prepared
1846 * @method : RTSP method of the request
1847 * @url : url need to be in the request
1848 * @message_type : WFD message type
1849 * @trigger_type : trigger method to be used for M5 mainly
1850 *
1851 * Prepares request based on @method & @message_type
1852 *
1853 * Returns: a #GstRTSPResult.
1854 */
1855 GstRTSPResult
1856 gst_prepare_request (GstRTSPWFDClient * client, GstRTSPMessage * request,
1857     GstRTSPMethod method, gchar * url)
1858 {
1859   GstRTSPResult res = GST_RTSP_OK;
1860   gchar *str = NULL;
1861
1862   if (method == GST_RTSP_GET_PARAMETER || method == GST_RTSP_SET_PARAMETER) {
1863     g_free (url);
1864     url = g_strdup ("rtsp://localhost/wfd1.0");
1865   }
1866
1867   GST_DEBUG_OBJECT (client, "Preparing request: %d", method);
1868
1869   /* initialize the request */
1870   res = gst_rtsp_message_init_request (request, method, url);
1871
1872   if (method == GST_RTSP_GET_PARAMETER || method == GST_RTSP_SET_PARAMETER) {
1873     g_free (url);
1874   }
1875
1876   if (res < 0) {
1877     GST_ERROR ("init request failed");
1878     return res;
1879   }
1880
1881   switch (method) {
1882       /* Prepare OPTIONS request to send */
1883     case GST_RTSP_OPTIONS:{
1884       /* add wfd specific require filed "org.wfa.wfd1.0" */
1885       str = g_strdup ("org.wfa.wfd1.0");
1886       res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_REQUIRE, str);
1887       if (res < 0) {
1888         GST_ERROR ("Failed to add header");
1889         g_free (str);
1890         return res;
1891       }
1892
1893       g_free (str);
1894       break;
1895     }
1896
1897       /* Prepare GET_PARAMETER request */
1898     case GST_RTSP_GET_PARAMETER:{
1899       gchar *msg = NULL;
1900       guint msglen = 0;
1901       GString *msglength;
1902
1903       /* add content type */
1904       res =
1905           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1906           "text/parameters");
1907       if (res < 0) {
1908         GST_ERROR ("Failed to add header");
1909         return res;
1910       }
1911
1912       _set_wfd_message_body (client, M3_REQ_MSG, &msg, &msglen);
1913       msglength = g_string_new ("");
1914       g_string_append_printf (msglength, "%d", msglen);
1915       GST_DEBUG ("M3 server side message body: %s", msg);
1916
1917       /* add content-length type */
1918       res =
1919           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1920           g_string_free (msglength, FALSE));
1921       if (res != GST_RTSP_OK) {
1922         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1923         goto error;
1924       }
1925
1926       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1927       if (res != GST_RTSP_OK) {
1928         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1929         goto error;
1930       }
1931
1932       g_free (msg);
1933       break;
1934     }
1935
1936       /* Prepare SET_PARAMETER request */
1937     case GST_RTSP_SET_PARAMETER:{
1938       gchar *msg = NULL;
1939       guint msglen = 0;
1940       GString *msglength;
1941
1942       /* add content type */
1943       res =
1944           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1945           "text/parameters");
1946       if (res != GST_RTSP_OK) {
1947         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1948         goto error;
1949       }
1950
1951       _set_wfd_message_body (client, M4_REQ_MSG, &msg, &msglen);
1952       msglength = g_string_new ("");
1953       g_string_append_printf (msglength, "%d", msglen);
1954       GST_DEBUG ("M4 server side message body: %s", msg);
1955
1956       /* add content-length type */
1957       res =
1958           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1959           g_string_free (msglength, FALSE));
1960       if (res != GST_RTSP_OK) {
1961         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1962         goto error;
1963       }
1964
1965       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1966       if (res != GST_RTSP_OK) {
1967         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1968         goto error;
1969       }
1970
1971       g_free (msg);
1972       break;
1973     }
1974
1975     default:{
1976     }
1977   }
1978
1979   return res;
1980
1981 error:
1982   return GST_RTSP_ERROR;
1983 }
1984
1985 GstRTSPResult
1986 prepare_trigger_request (GstRTSPWFDClient * client, GstRTSPMessage * request,
1987     GstWFDTriggerType trigger_type, gchar * url)
1988 {
1989   GstRTSPResult res = GST_RTSP_OK;
1990
1991   /* initialize the request */
1992   res = gst_rtsp_message_init_request (request, GST_RTSP_SET_PARAMETER, url);
1993   if (res < 0) {
1994     GST_ERROR ("init request failed");
1995     return res;
1996   }
1997
1998   switch (trigger_type) {
1999     case WFD_TRIGGER_SETUP:{
2000       gchar *msg;
2001       guint msglen = 0;
2002       GString *msglength;
2003
2004       /* add content type */
2005       res =
2006           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
2007           "text/parameters");
2008       if (res != GST_RTSP_OK) {
2009         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
2010         goto error;
2011       }
2012
2013       _set_wfd_message_body (client, M5_REQ_MSG, &msg, &msglen);
2014       msglength = g_string_new ("");
2015       g_string_append_printf (msglength, "%d", msglen);
2016       GST_DEBUG ("M5 server side message body: %s", msg);
2017
2018       /* add content-length type */
2019       res =
2020           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
2021           g_string_free (msglength, FALSE));
2022       if (res != GST_RTSP_OK) {
2023         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2024         goto error;
2025       }
2026
2027       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
2028       if (res != GST_RTSP_OK) {
2029         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2030         goto error;
2031       }
2032
2033       g_free (msg);
2034       break;
2035     }
2036     case WFD_TRIGGER_TEARDOWN:{
2037       gchar *msg;
2038       guint msglen = 0;
2039       GString *msglength;
2040
2041       /* add content type */
2042       res =
2043           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
2044           "text/parameters");
2045       if (res != GST_RTSP_OK) {
2046         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
2047         goto error;
2048       }
2049
2050       _set_wfd_message_body (client, TEARDOWN_TRIGGER, &msg, &msglen);
2051       msglength = g_string_new ("");
2052       g_string_append_printf (msglength, "%d", msglen);
2053       GST_DEBUG ("Trigger TEARDOWN server side message body: %s", msg);
2054
2055       /* add content-length type */
2056       res =
2057           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
2058           g_string_free (msglength, FALSE));
2059       if (res != GST_RTSP_OK) {
2060         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2061         goto error;
2062       }
2063
2064       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
2065       if (res != GST_RTSP_OK) {
2066         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2067         goto error;
2068       }
2069
2070       g_free (msg);
2071       break;
2072     }
2073     case WFD_TRIGGER_PLAY:{
2074       gchar *msg;
2075       guint msglen = 0;
2076       GString *msglength;
2077
2078       /* add content type */
2079       res =
2080           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
2081           "text/parameters");
2082       if (res != GST_RTSP_OK) {
2083         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
2084         goto error;
2085       }
2086
2087       _set_wfd_message_body (client, PLAY_TRIGGER, &msg, &msglen);
2088       msglength = g_string_new ("");
2089       g_string_append_printf (msglength, "%d", msglen);
2090       GST_DEBUG ("Trigger PLAY server side message body: %s", msg);
2091
2092       /* add content-length type */
2093       res =
2094           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
2095           g_string_free (msglength, FALSE));
2096       if (res != GST_RTSP_OK) {
2097         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2098         goto error;
2099       }
2100
2101       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
2102       if (res != GST_RTSP_OK) {
2103         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2104         goto error;
2105       }
2106
2107       g_free (msg);
2108       break;
2109     }
2110     case WFD_TRIGGER_PAUSE:{
2111       gchar *msg;
2112       guint msglen = 0;
2113       GString *msglength;
2114
2115       /* add content type */
2116       res =
2117           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
2118           "text/parameters");
2119       if (res != GST_RTSP_OK) {
2120         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
2121         goto error;
2122       }
2123
2124       _set_wfd_message_body (client, PAUSE_TRIGGER, &msg, &msglen);
2125       msglength = g_string_new ("");
2126       g_string_append_printf (msglength, "%d", msglen);
2127       GST_DEBUG ("Trigger PAUSE server side message body: %s", msg);
2128
2129       /* add content-length type */
2130       res =
2131           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
2132           g_string_free (msglength, FALSE));
2133       if (res != GST_RTSP_OK) {
2134         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2135         goto error;
2136       }
2137
2138       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
2139       if (res != GST_RTSP_OK) {
2140         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2141         goto error;
2142       }
2143
2144       g_free (msg);
2145       break;
2146     }
2147       /* TODO-WFD: implement to handle other trigger type */
2148     default:{
2149     }
2150   }
2151
2152   return res;
2153
2154 error:
2155   return res;
2156 }
2157
2158
2159 void
2160 gst_send_request (GstRTSPWFDClient * client, GstRTSPSession * session,
2161     GstRTSPMessage * request)
2162 {
2163   GstRTSPResult res = GST_RTSP_OK;
2164   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2165
2166   /* remove any previous header */
2167   gst_rtsp_message_remove_header (request, GST_RTSP_HDR_SESSION, -1);
2168
2169   /* add the new session header for new session ids */
2170   if (session) {
2171     guint timeout;
2172     const gchar *sessionid = NULL;
2173     gchar *str;
2174
2175     sessionid = gst_rtsp_session_get_sessionid (session);
2176     GST_INFO_OBJECT (client, "Session id : %s", sessionid);
2177
2178     timeout = gst_rtsp_session_get_timeout (session);
2179     if (timeout != DEFAULT_WFD_TIMEOUT)
2180       str = g_strdup_printf ("%s; timeout=%d", sessionid, timeout);
2181     else
2182       str = g_strdup (sessionid);
2183
2184     gst_rtsp_message_take_header (request, GST_RTSP_HDR_SESSION, str);
2185   }
2186 #if 0
2187   if (gst_debug_category_get_threshold (rtsp_wfd_client_debug) >= GST_LEVEL_LOG) {
2188     gst_rtsp_message_dump (request);
2189   }
2190 #endif
2191   res = gst_rtsp_client_send_message (parent_client, session, request);
2192   if (res != GST_RTSP_OK) {
2193     GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
2194   }
2195
2196   gst_rtsp_message_unset (request);
2197 }
2198
2199 /**
2200 * prepare_response:
2201 * @client: client object
2202 * @request : requst message received
2203 * @response : response to be prepare based on request
2204 * @method : RTSP method
2205 *
2206 * prepare response to the request based on @method & @message_type
2207 *
2208 * Returns: a #GstRTSPResult.
2209 */
2210 GstRTSPResult
2211 prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request,
2212     GstRTSPMessage * response, GstRTSPMethod method)
2213 {
2214   GstRTSPResult res = GST_RTSP_OK;
2215
2216   switch (method) {
2217       /* prepare OPTIONS response */
2218     case GST_RTSP_OPTIONS:{
2219       GstRTSPMethod options;
2220       gchar *tmp = NULL;
2221       gchar *str = NULL;
2222       gchar *user_agent = NULL;
2223
2224       options = GST_RTSP_OPTIONS |
2225           GST_RTSP_PAUSE |
2226           GST_RTSP_PLAY |
2227           GST_RTSP_SETUP |
2228           GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
2229
2230       str = gst_rtsp_options_as_text (options);
2231
2232       /*append WFD specific method */
2233       tmp = g_strdup (", org.wfa.wfd1.0");
2234       g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
2235
2236       gst_rtsp_message_init_response (response, GST_RTSP_STS_OK,
2237           gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
2238
2239       gst_rtsp_message_add_header (response, GST_RTSP_HDR_PUBLIC, str);
2240       g_free (str);
2241       g_free (tmp);
2242       str = NULL;
2243       res =
2244           gst_rtsp_message_get_header (request, GST_RTSP_HDR_USER_AGENT,
2245           &user_agent, 0);
2246       if (res == GST_RTSP_OK) {
2247         gst_rtsp_message_add_header (response, GST_RTSP_HDR_USER_AGENT,
2248             user_agent);
2249       } else
2250         res = GST_RTSP_OK;
2251       break;
2252     }
2253     default:
2254       GST_ERROR_OBJECT (client, "Unhandled method...");
2255       return GST_RTSP_EINVAL;
2256       break;
2257   }
2258
2259   return res;
2260 }
2261
2262 static void
2263 send_generic_wfd_response (GstRTSPWFDClient * client, GstRTSPStatusCode code,
2264     GstRTSPContext * ctx)
2265 {
2266   GstRTSPResult res = GST_RTSP_OK;
2267   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2268
2269   gst_rtsp_message_init_response (ctx->response, code,
2270       gst_rtsp_status_as_text (code), ctx->request);
2271
2272   res = gst_rtsp_client_send_message (parent_client, NULL, ctx->response);
2273   if (res != GST_RTSP_OK) {
2274     GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
2275   }
2276 }
2277
2278
2279 static GstRTSPResult
2280 handle_M1_message (GstRTSPWFDClient * client)
2281 {
2282   GstRTSPResult res = GST_RTSP_OK;
2283   GstRTSPMessage request = { 0 };
2284
2285   res = gst_prepare_request (client, &request, GST_RTSP_OPTIONS, (gchar *) "*");
2286   if (GST_RTSP_OK != res) {
2287     GST_ERROR_OBJECT (client, "Failed to prepare M1 request....\n");
2288     return res;
2289   }
2290
2291   GST_DEBUG_OBJECT (client, "Sending M1 request.. (OPTIONS request)");
2292
2293   gst_send_request (client, NULL, &request);
2294
2295   return res;
2296 }
2297
2298 /**
2299 * handle_M3_message:
2300 * @client: client object
2301 *
2302 * Handles M3 WFD message.
2303 * This API will send M3 message (GET_PARAMETER) to WFDSink to query supported formats by the WFDSink.
2304 * After getting supported formats info, this API will set those values on WFDConfigMessage obj
2305 *
2306 * Returns: a #GstRTSPResult.
2307 */
2308 static GstRTSPResult
2309 handle_M3_message (GstRTSPWFDClient * client)
2310 {
2311   GstRTSPResult res = GST_RTSP_OK;
2312   GstRTSPMessage request = { 0 };
2313   GstRTSPUrl *url = NULL;
2314   gchar *url_str = NULL;
2315
2316   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2317   GstRTSPConnection *connection =
2318       gst_rtsp_client_get_connection (parent_client);
2319
2320   url = gst_rtsp_connection_get_url (connection);
2321   if (url == NULL) {
2322     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2323     res = GST_RTSP_ERROR;
2324     goto error;
2325   }
2326
2327   url_str = gst_rtsp_url_get_request_uri (url);
2328   if (url_str == NULL) {
2329     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2330     res = GST_RTSP_ERROR;
2331     goto error;
2332   }
2333
2334   res = gst_prepare_request (client, &request, GST_RTSP_GET_PARAMETER, url_str);
2335   if (GST_RTSP_OK != res) {
2336     GST_ERROR_OBJECT (client, "Failed to prepare M3 request....\n");
2337     goto error;
2338   }
2339
2340   GST_DEBUG_OBJECT (client, "Sending GET_PARAMETER request message (M3)...");
2341
2342   gst_send_request (client, NULL, &request);
2343
2344   return res;
2345
2346 error:
2347   return res;
2348 }
2349
2350 static GstRTSPResult
2351 handle_M4_message (GstRTSPWFDClient * client)
2352 {
2353   GstRTSPResult res = GST_RTSP_OK;
2354   GstRTSPMessage request = { 0 };
2355   GstRTSPUrl *url = NULL;
2356   gchar *url_str = NULL;
2357
2358   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2359   GstRTSPConnection *connection =
2360       gst_rtsp_client_get_connection (parent_client);
2361
2362   url = gst_rtsp_connection_get_url (connection);
2363   if (url == NULL) {
2364     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2365     res = GST_RTSP_ERROR;
2366     goto error;
2367   }
2368
2369   url_str = gst_rtsp_url_get_request_uri (url);
2370   if (url_str == NULL) {
2371     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2372     res = GST_RTSP_ERROR;
2373     goto error;
2374   }
2375
2376   res = gst_prepare_request (client, &request, GST_RTSP_SET_PARAMETER, url_str);
2377   if (GST_RTSP_OK != res) {
2378     GST_ERROR_OBJECT (client, "Failed to prepare M4 request....\n");
2379     goto error;
2380   }
2381
2382   GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message (M4)...");
2383
2384   gst_send_request (client, NULL, &request);
2385
2386   return res;
2387
2388 error:
2389   return res;
2390 }
2391
2392 GstRTSPResult
2393 gst_rtsp_wfd_client_trigger_request (GstRTSPWFDClient * client,
2394     GstWFDTriggerType type)
2395 {
2396   GstRTSPResult res = GST_RTSP_OK;
2397   GstRTSPMessage request = { 0 };
2398   GstRTSPUrl *url = NULL;
2399   gchar *url_str = NULL;
2400
2401   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2402   GstRTSPConnection *connection =
2403       gst_rtsp_client_get_connection (parent_client);
2404
2405   url = gst_rtsp_connection_get_url (connection);
2406   if (url == NULL) {
2407     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2408     res = GST_RTSP_ERROR;
2409     goto error;
2410   }
2411
2412   url_str = gst_rtsp_url_get_request_uri (url);
2413   if (url_str == NULL) {
2414     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2415     res = GST_RTSP_ERROR;
2416     goto error;
2417   }
2418
2419   res = prepare_trigger_request (client, &request, type, url_str);
2420   if (GST_RTSP_OK != res) {
2421     GST_ERROR_OBJECT (client, "Failed to prepare M5 request....\n");
2422     goto error;
2423   }
2424
2425   GST_DEBUG_OBJECT (client, "Sending trigger request message...: %d", type);
2426
2427   gst_send_request (client, NULL, &request);
2428
2429   return res;
2430
2431 error:
2432   return res;
2433 }
2434
2435 GstRTSPResult
2436 gst_rtsp_wfd_client_set_video_supported_resolution (GstRTSPWFDClient * client,
2437     guint64 supported_reso)
2438 {
2439   GstRTSPResult res = GST_RTSP_OK;
2440   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2441
2442   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2443
2444   priv->video_resolution_supported = supported_reso;
2445   GST_DEBUG ("Resolution : %" G_GUINT64_FORMAT, supported_reso);
2446
2447   return res;
2448 }
2449
2450 GstRTSPResult
2451 gst_rtsp_wfd_client_set_video_native_resolution (GstRTSPWFDClient * client,
2452     guint64 native_reso)
2453 {
2454   GstRTSPResult res = GST_RTSP_OK;
2455   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2456
2457   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2458
2459   priv->video_native_resolution = native_reso;
2460   GST_DEBUG ("Native Resolution : %" G_GUINT64_FORMAT, native_reso);
2461
2462   return res;
2463 }
2464
2465 GstRTSPResult
2466 gst_rtsp_wfd_client_set_audio_codec (GstRTSPWFDClient * client,
2467     guint8 audio_codec)
2468 {
2469   GstRTSPResult res = GST_RTSP_OK;
2470   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2471
2472   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2473
2474   priv->audio_codec = audio_codec;
2475   GST_DEBUG ("Audio codec : %d", audio_codec);
2476
2477   return res;
2478 }
2479
2480 static gboolean
2481 wfd_ckeck_keep_alive_response (gpointer userdata)
2482 {
2483   GstRTSPWFDClient *client = (GstRTSPWFDClient *) userdata;
2484   GstRTSPWFDClientPrivate *priv = NULL;
2485   if (!client) {
2486     return FALSE;
2487   }
2488
2489   priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2490   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2491
2492   if (priv->keep_alive_flag) {
2493     return FALSE;
2494   }
2495   else {
2496     GST_INFO ("%p: source error notification", client);
2497
2498     g_signal_emit (client,
2499         gst_rtsp_client_wfd_signals[SIGNAL_WFD_KEEP_ALIVE_FAIL], 0, NULL);
2500     return FALSE;
2501   }
2502 }
2503
2504 /*Sending keep_alive (M16) message.
2505   Without calling gst_prepare_request function.*/
2506 static GstRTSPResult
2507 handle_M16_message (GstRTSPWFDClient * client)
2508 {
2509   GstRTSPResult res = GST_RTSP_OK;
2510   GstRTSPMessage request = { 0 };
2511   gchar *url_str = NULL;
2512
2513   url_str = g_strdup ("rtsp://localhost/wfd1.0");
2514
2515   res =
2516       gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str);
2517   if (res < 0) {
2518     GST_ERROR ("init request failed");
2519     g_free (url_str);
2520     return FALSE;
2521   }
2522
2523   gst_send_request (client, NULL, &request);
2524   g_free (url_str);
2525   return GST_RTSP_OK;
2526 }
2527
2528 /*CHecking whether source has got response of any request.
2529  * If yes, keep alive message is sent otherwise error message
2530  * will be displayed.*/
2531 static gboolean
2532 keep_alive_condition (gpointer userdata)
2533 {
2534   GstRTSPWFDClient *client;
2535   GstRTSPWFDClientPrivate *priv;
2536   GstRTSPResult res;
2537   client = (GstRTSPWFDClient *) userdata;
2538   if (!client) {
2539     return FALSE;
2540   }
2541   priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2542
2543   g_return_val_if_fail (priv != NULL, FALSE);
2544
2545   g_mutex_lock (&priv->keep_alive_lock);
2546   if (!priv->keep_alive_flag) {
2547     g_timeout_add (5000, wfd_ckeck_keep_alive_response, client);
2548   }
2549   else {
2550     GST_DEBUG_OBJECT (client, "have received last keep alive message response");
2551   }
2552
2553   GST_DEBUG ("sending keep alive message");
2554   res = handle_M16_message (client);
2555   if (res == GST_RTSP_OK) {
2556     priv->keep_alive_flag = FALSE;
2557   } else {
2558     GST_ERROR_OBJECT (client, "Failed to send Keep Alive Message");
2559     g_mutex_unlock (&priv->keep_alive_lock);
2560     return FALSE;
2561   }
2562
2563   g_mutex_unlock (&priv->keep_alive_lock);
2564   return TRUE;
2565 }
2566
2567 static void
2568 wfd_set_keep_alive_condition (GstRTSPWFDClient * client)
2569 {
2570   g_timeout_add ((DEFAULT_WFD_TIMEOUT - 5) * 1000, keep_alive_condition,
2571       client);
2572 }
2573
2574 void
2575 gst_rtsp_wfd_client_set_host_address (GstRTSPWFDClient * client,
2576     const gchar * address)
2577 {
2578   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2579
2580   g_return_if_fail (priv != NULL);
2581
2582   if (priv->host_address) {
2583     g_free (priv->host_address);
2584   }
2585
2586   priv->host_address = g_strdup (address);
2587 }
2588
2589 guint
2590 gst_rtsp_wfd_client_get_audio_codec (GstRTSPWFDClient * client)
2591 {
2592   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2593   g_return_val_if_fail (priv != NULL, 0);
2594
2595   return priv->caCodec;
2596 }
2597
2598 guint
2599 gst_rtsp_wfd_client_get_audio_freq (GstRTSPWFDClient * client)
2600 {
2601   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2602   g_return_val_if_fail (priv != NULL, 0);
2603
2604   return priv->cFreq;
2605 }
2606
2607 guint
2608 gst_rtsp_wfd_client_get_audio_channels (GstRTSPWFDClient * client)
2609 {
2610   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2611   g_return_val_if_fail (priv != NULL, 0);
2612
2613   return priv->cChanels;
2614 }
2615
2616 guint
2617 gst_rtsp_wfd_client_get_audio_bit_width (GstRTSPWFDClient * client)
2618 {
2619   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2620   g_return_val_if_fail (priv != NULL, 0);
2621
2622   return priv->cBitwidth;
2623 }
2624
2625 guint
2626 gst_rtsp_wfd_client_get_audio_latency (GstRTSPWFDClient * client)
2627 {
2628   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2629   g_return_val_if_fail (priv != NULL, 0);
2630
2631   return priv->caLatency;
2632 }
2633
2634 guint
2635 gst_rtsp_wfd_client_get_video_codec (GstRTSPWFDClient * client)
2636 {
2637   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2638   g_return_val_if_fail (priv != NULL, 0);
2639
2640   return priv->cvCodec;
2641 }
2642
2643 guint
2644 gst_rtsp_wfd_client_get_video_native (GstRTSPWFDClient * client)
2645 {
2646   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2647   g_return_val_if_fail (priv != NULL, 0);
2648
2649   return priv->cNative;
2650 }
2651
2652 guint64
2653 gst_rtsp_wfd_client_get_video_native_resolution (GstRTSPWFDClient * client)
2654 {
2655   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2656   g_return_val_if_fail (priv != NULL, 0);
2657
2658   return priv->cNativeResolution;
2659 }
2660
2661 guint64
2662 gst_rtsp_wfd_client_get_video_cea_resolution (GstRTSPWFDClient * client)
2663 {
2664   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2665   g_return_val_if_fail (priv != NULL, 0);
2666
2667   return priv->cCEAResolution;
2668 }
2669
2670 guint64
2671 gst_rtsp_wfd_client_get_video_vesa_resolution (GstRTSPWFDClient * client)
2672 {
2673   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2674   g_return_val_if_fail (priv != NULL, 0);
2675
2676   return priv->cVESAResolution;
2677 }
2678
2679 guint64
2680 gst_rtsp_wfd_client_get_video_hh_resolution (GstRTSPWFDClient * client)
2681 {
2682   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2683   g_return_val_if_fail (priv != NULL, 0);
2684
2685   return priv->cHHResolution;
2686 }
2687
2688 guint
2689 gst_rtsp_wfd_client_get_video_profile (GstRTSPWFDClient * client)
2690 {
2691   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2692   g_return_val_if_fail (priv != NULL, 0);
2693
2694   return priv->cProfile;
2695 }
2696
2697 guint
2698 gst_rtsp_wfd_client_get_video_level (GstRTSPWFDClient * client)
2699 {
2700   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2701   g_return_val_if_fail (priv != NULL, 0);
2702
2703   return priv->cLevel;
2704 }
2705
2706 guint
2707 gst_rtsp_wfd_client_get_video_latency (GstRTSPWFDClient * client)
2708 {
2709   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2710   g_return_val_if_fail (priv != NULL, 0);
2711
2712   return priv->cvLatency;
2713 }
2714
2715 guint32
2716 gst_rtsp_wfd_client_get_video_max_height (GstRTSPWFDClient * client)
2717 {
2718   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2719   g_return_val_if_fail (priv != NULL, 0);
2720
2721   return priv->cMaxHeight;
2722 }
2723
2724 guint32
2725 gst_rtsp_wfd_client_get_video_max_width (GstRTSPWFDClient * client)
2726 {
2727   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2728   g_return_val_if_fail (priv != NULL, 0);
2729
2730   return priv->cMaxWidth;
2731 }
2732
2733 guint32
2734 gst_rtsp_wfd_client_get_video_framerate (GstRTSPWFDClient * client)
2735 {
2736   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2737   g_return_val_if_fail (priv != NULL, 0);
2738
2739   return priv->cFramerate;
2740 }
2741
2742 guint32
2743 gst_rtsp_wfd_client_get_video_min_slice_size (GstRTSPWFDClient * client)
2744 {
2745   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2746   g_return_val_if_fail (priv != NULL, 0);
2747
2748   return priv->cmin_slice_size;
2749 }
2750
2751 guint32
2752 gst_rtsp_wfd_client_get_video_slice_enc_params (GstRTSPWFDClient * client)
2753 {
2754   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2755   g_return_val_if_fail (priv != NULL, 0);
2756
2757   return priv->cslice_enc_params;
2758 }
2759
2760 guint
2761 gst_rtsp_wfd_client_get_video_framerate_control (GstRTSPWFDClient * client)
2762 {
2763   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2764   g_return_val_if_fail (priv != NULL, 0);
2765
2766   return priv->cframe_rate_control;
2767 }
2768
2769 guint32
2770 gst_rtsp_wfd_client_get_rtp_port0 (GstRTSPWFDClient * client)
2771 {
2772   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2773   g_return_val_if_fail (priv != NULL, 0);
2774
2775   return priv->crtp_port0;
2776 }
2777
2778 guint32
2779 gst_rtsp_wfd_client_get_rtp_port1 (GstRTSPWFDClient * client)
2780 {
2781   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2782   g_return_val_if_fail (priv != NULL, 0);
2783
2784   return priv->crtp_port1;
2785 }
2786
2787 gboolean
2788 gst_rtsp_wfd_client_get_edid_supported (GstRTSPWFDClient * client)
2789 {
2790   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2791   g_return_val_if_fail (priv != NULL, 0);
2792
2793   return priv->edid_supported;
2794 }
2795
2796 guint32
2797 gst_rtsp_wfd_client_get_edid_hresolution (GstRTSPWFDClient * client)
2798 {
2799   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2800   g_return_val_if_fail (priv != NULL, 0);
2801
2802   return priv->edid_hres;
2803 }
2804
2805 guint32
2806 gst_rtsp_wfd_client_get_edid_vresolution (GstRTSPWFDClient * client)
2807 {
2808   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2809   g_return_val_if_fail (priv != NULL, 0);
2810
2811   return priv->edid_vres;
2812 }
2813
2814 gboolean
2815 gst_rtsp_wfd_client_get_protection_enabled (GstRTSPWFDClient * client)
2816 {
2817   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2818   g_return_val_if_fail (priv != NULL, 0);
2819
2820   return priv->protection_enabled;
2821 }
2822
2823 void
2824 gst_rtsp_wfd_client_set_audio_freq (GstRTSPWFDClient * client, guint freq)
2825 {
2826   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2827   g_return_if_fail (priv != NULL);
2828
2829   priv->cFreq = freq;
2830 }
2831
2832 void
2833 gst_rtsp_wfd_client_set_edid_supported (GstRTSPWFDClient * client,
2834     gboolean supported)
2835 {
2836   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2837   g_return_if_fail (priv != NULL);
2838
2839   priv->edid_supported = supported;
2840 }
2841
2842 void
2843 gst_rtsp_wfd_client_set_edid_hresolution (GstRTSPWFDClient * client,
2844     guint32 reso)
2845 {
2846   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2847   g_return_if_fail (priv != NULL);
2848
2849   priv->edid_hres = reso;
2850 }
2851
2852 void
2853 gst_rtsp_wfd_client_set_edid_vresolution (GstRTSPWFDClient * client,
2854     guint32 reso)
2855 {
2856   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2857   g_return_if_fail (priv != NULL);
2858
2859   priv->edid_vres = reso;
2860 }
2861
2862 void
2863 gst_rtsp_wfd_client_set_protection_enabled (GstRTSPWFDClient * client,
2864     gboolean enable)
2865 {
2866   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2867   g_return_if_fail (priv != NULL);
2868
2869   priv->protection_enabled = enable;
2870 }
2871
2872 void
2873 gst_rtsp_wfd_client_set_hdcp_version (GstRTSPWFDClient * client,
2874     GstWFDHDCPProtection version)
2875 {
2876   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2877   g_return_if_fail (priv != NULL);
2878
2879   priv->hdcp_version = version;
2880 }
2881
2882 void
2883 gst_rtsp_wfd_client_set_hdcp_port (GstRTSPWFDClient * client, guint32 port)
2884 {
2885   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2886   g_return_if_fail (priv != NULL);
2887
2888   priv->hdcp_tcpport = port;
2889 }
2890
2891 void
2892 gst_rtsp_wfd_client_set_keep_alive_flag (GstRTSPWFDClient * client,
2893     gboolean flag)
2894 {
2895   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2896   g_return_if_fail (priv != NULL);
2897
2898   g_mutex_lock (&priv->keep_alive_lock);
2899   if (priv->keep_alive_flag == !(flag))
2900     priv->keep_alive_flag = flag;
2901   g_mutex_unlock (&priv->keep_alive_lock);
2902 }
2903
2904 void
2905 gst_rtsp_wfd_client_set_aud_codec (GstRTSPWFDClient * client, guint acodec)
2906 {
2907   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2908   g_return_if_fail (priv != NULL);
2909
2910   priv->caCodec = acodec;
2911 }
2912
2913 void
2914 gst_rtsp_wfd_client_set_audio_channels (GstRTSPWFDClient * client,
2915     guint channels)
2916 {
2917   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2918   g_return_if_fail (priv != NULL);
2919
2920   priv->cChanels = channels;
2921 }
2922
2923 void
2924 gst_rtsp_wfd_client_set_audio_bit_width (GstRTSPWFDClient * client,
2925     guint bwidth)
2926 {
2927   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2928   g_return_if_fail (priv != NULL);
2929
2930   priv->cBitwidth = bwidth;
2931 }
2932
2933 void
2934 gst_rtsp_wfd_client_set_audio_latency (GstRTSPWFDClient * client, guint latency)
2935 {
2936   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2937   g_return_if_fail (priv != NULL);
2938
2939   priv->caLatency = latency;
2940 }
2941
2942 void
2943 gst_rtsp_wfd_client_set_video_codec (GstRTSPWFDClient * client, guint vcodec)
2944 {
2945   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2946   g_return_if_fail (priv != NULL);
2947
2948   priv->cvCodec = vcodec;
2949 }
2950
2951 void
2952 gst_rtsp_wfd_client_set_video_native (GstRTSPWFDClient * client, guint native)
2953 {
2954   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2955   g_return_if_fail (priv != NULL);
2956
2957   priv->cNative = native;
2958 }
2959
2960 void
2961 gst_rtsp_wfd_client_set_vid_native_resolution (GstRTSPWFDClient * client,
2962     guint64 res)
2963 {
2964   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2965   g_return_if_fail (priv != NULL);
2966
2967   priv->cNativeResolution = res;
2968 }
2969
2970 void
2971 gst_rtsp_wfd_client_set_video_cea_resolution (GstRTSPWFDClient * client,
2972     guint64 res)
2973 {
2974   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2975   g_return_if_fail (priv != NULL);
2976
2977   priv->cCEAResolution = res;
2978 }
2979
2980 void
2981 gst_rtsp_wfd_client_set_video_vesa_resolution (GstRTSPWFDClient * client,
2982     guint64 res)
2983 {
2984   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2985   g_return_if_fail (priv != NULL);
2986
2987   priv->cVESAResolution = res;
2988 }
2989
2990 void
2991 gst_rtsp_wfd_client_set_video_hh_resolution (GstRTSPWFDClient * client,
2992     guint64 res)
2993 {
2994   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2995   g_return_if_fail (priv != NULL);
2996
2997   priv->cHHResolution = res;
2998 }
2999
3000 void
3001 gst_rtsp_wfd_client_set_video_profile (GstRTSPWFDClient * client, guint profile)
3002 {
3003   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3004   g_return_if_fail (priv != NULL);
3005
3006   priv->cProfile = profile;
3007 }
3008
3009 void
3010 gst_rtsp_wfd_client_set_video_level (GstRTSPWFDClient * client, guint level)
3011 {
3012   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3013   g_return_if_fail (priv != NULL);
3014
3015   priv->cLevel = level;
3016 }
3017
3018 void
3019 gst_rtsp_wfd_client_set_video_latency (GstRTSPWFDClient * client, guint latency)
3020 {
3021   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3022   g_return_if_fail (priv != NULL);
3023
3024   priv->cvLatency = latency;
3025 }
3026
3027 void
3028 gst_rtsp_wfd_client_set_video_max_height (GstRTSPWFDClient * client,
3029     guint32 height)
3030 {
3031   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3032   g_return_if_fail (priv != NULL);
3033
3034   priv->cMaxHeight = height;
3035 }
3036
3037 void
3038 gst_rtsp_wfd_client_set_video_max_width (GstRTSPWFDClient * client,
3039     guint32 width)
3040 {
3041   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3042   g_return_if_fail (priv != NULL);
3043
3044   priv->cMaxWidth = width;
3045 }
3046
3047 void
3048 gst_rtsp_wfd_client_set_video_framerate (GstRTSPWFDClient * client,
3049     guint32 framerate)
3050 {
3051   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3052   g_return_if_fail (priv != NULL);
3053
3054   priv->cFramerate = framerate;
3055 }
3056
3057 void
3058 gst_rtsp_wfd_client_set_video_min_slice_size (GstRTSPWFDClient * client,
3059     guint32 slice_size)
3060 {
3061   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3062   g_return_if_fail (priv != NULL);
3063
3064   priv->cmin_slice_size = slice_size;
3065 }
3066
3067 void
3068 gst_rtsp_wfd_client_set_video_slice_enc_params (GstRTSPWFDClient * client,
3069     guint32 enc_params)
3070 {
3071   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3072   g_return_if_fail (priv != NULL);
3073
3074   priv->cslice_enc_params = enc_params;
3075 }
3076
3077 void
3078 gst_rtsp_wfd_client_set_video_framerate_control (GstRTSPWFDClient * client,
3079     guint framerate)
3080 {
3081   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3082   g_return_if_fail (priv != NULL);
3083
3084   priv->cframe_rate_control = framerate;
3085 }
3086
3087 void
3088 gst_rtsp_wfd_client_set_rtp_port0 (GstRTSPWFDClient * client, guint32 port)
3089 {
3090   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3091   g_return_if_fail (priv != NULL);
3092
3093   priv->crtp_port0 = port;
3094 }
3095
3096 void
3097 gst_rtsp_wfd_client_set_rtp_port1 (GstRTSPWFDClient * client, guint32 port)
3098 {
3099   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3100   g_return_if_fail (priv != NULL);
3101
3102   priv->crtp_port1 = port;
3103 }
3104
3105 gchar *
3106 gst_rtsp_wfd_client_get_sink_user_agent (GstRTSPWFDClient * client)
3107 {
3108   char *str = NULL;
3109   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
3110   g_return_val_if_fail (priv != NULL, NULL);
3111
3112   if (priv->sink_user_agent != NULL)
3113     str = g_strdup (priv->sink_user_agent);
3114
3115   return str;
3116 }