ba7491909cce1d8fd7d2557ebec357498f38a3dd
[platform/upstream/gst-rtsp-server.git] / gst / rtsp-server / rtsp-client-wfd.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.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 /* locking order:
54  * send_lock, lock, tunnels_lock
55  */
56
57 struct _GstRTSPWFDClientPrivate
58 {
59   GstRTSPWFDClientSendFunc send_func;   /* protected by send_lock */
60   gpointer send_data;           /* protected by send_lock */
61   GDestroyNotify send_notify;   /* protected by send_lock */
62
63   /* used to cache the media in the last requested DESCRIBE so that
64    * we can pick it up in the next SETUP immediately */
65   gchar *path;
66   GstRTSPMedia *media;
67
68   GList *transports;
69   GList *sessions;
70
71   guint8 m1_done;
72   guint8 m3_done;
73   guint8 m4_done;
74
75   /* Host's URL info */
76   gchar *host_address;
77
78   /* Parameters for WIFI-DISPLAY */
79   guint caCodec;
80   guint8 audio_codec;
81   guint cFreq;
82   guint cChanels;
83   guint cBitwidth;
84   guint caLatency;
85   guint cvCodec;
86   guint cNative;
87   guint64 cNativeResolution;
88   guint64 video_resolution_supported;
89   gint video_native_resolution;
90   guint cCEAResolution;
91   guint cVESAResolution;
92   guint cHHResolution;
93   guint cProfile;
94   guint cLevel;
95   guint32 cMaxHeight;
96   guint32 cMaxWidth;
97   guint32 cFramerate;
98   guint32 cInterleaved;
99   guint32 cmin_slice_size;
100   guint32 cslice_enc_params;
101   guint cframe_rate_control;
102   guint cvLatency;
103   guint ctrans;
104   guint cprofile;
105   guint clowertrans;
106   guint32 crtp_port0;
107   guint32 crtp_port1;
108
109   gboolean protection_enabled;
110   GstWFDHDCPProtection hdcp_version;
111   guint32 hdcp_tcpport;
112
113   gboolean edid_supported;
114   guint32 edid_hres;
115   guint32 edid_vres;
116
117   guint8 keep_alive_flag;
118   GMutex keep_alive_lock;
119 };
120
121 #define DEFAULT_WFD_TIMEOUT 60
122 #define WFD_MOUNT_POINT "/wfd1.0/streamid=0"
123
124 enum
125 {
126   SIGNAL_WFD_OPTIONS_REQUEST,
127   SIGNAL_WFD_GET_PARAMETER_REQUEST,
128   SIGNAL_WFD_LAST
129 };
130
131 GST_DEBUG_CATEGORY_STATIC (rtsp_wfd_client_debug);
132 #define GST_CAT_DEFAULT rtsp_wfd_client_debug
133
134 static guint gst_rtsp_client_wfd_signals[SIGNAL_WFD_LAST] = { 0 };
135
136 static void gst_rtsp_wfd_client_get_property (GObject * object, guint propid,
137     GValue * value, GParamSpec * pspec);
138 static void gst_rtsp_wfd_client_set_property (GObject * object, guint propid,
139     const GValue * value, GParamSpec * pspec);
140 static void gst_rtsp_wfd_client_finalize (GObject * obj);
141
142 static gboolean handle_wfd_options_request (GstRTSPClient * client,
143     GstRTSPContext * ctx);
144 static gboolean handle_wfd_set_param_request (GstRTSPClient * client,
145     GstRTSPContext * ctx);
146 static gboolean handle_wfd_get_param_request (GstRTSPClient * client,
147     GstRTSPContext * ctx);
148
149 static void send_generic_wfd_response (GstRTSPWFDClient * client,
150     GstRTSPStatusCode code, GstRTSPContext * ctx);
151 static gchar *wfd_make_path_from_uri (GstRTSPClient * client,
152     const GstRTSPUrl * uri);
153 static void wfd_options_request_done (GstRTSPWFDClient * client);
154 static void wfd_get_param_request_done (GstRTSPWFDClient * client);
155 static void handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx);
156 static void handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx);
157 static void wfd_set_keep_alive_condition(GstRTSPClient * client);
158 static gboolean wfd_ckeck_keep_alive_response (gpointer userdata);
159 static gboolean keep_alive_condition(gpointer userdata);
160
161 GstRTSPResult prepare_trigger_request (GstRTSPWFDClient * client,
162     GstRTSPMessage * request, GstWFDTriggerType trigger_type, gchar * url);
163
164 GstRTSPResult prepare_request (GstRTSPWFDClient * client,
165     GstRTSPMessage * request, GstRTSPMethod method, gchar * url);
166
167 void
168 send_request (GstRTSPWFDClient * client, GstRTSPSession * session,
169     GstRTSPMessage * request);
170
171 GstRTSPResult
172 prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request,
173     GstRTSPMessage * response, GstRTSPMethod method);
174
175 static GstRTSPResult handle_M1_message (GstRTSPWFDClient * client);
176 static GstRTSPResult handle_M3_message (GstRTSPWFDClient * client);
177 static GstRTSPResult handle_M4_message (GstRTSPWFDClient * client);
178 static GstRTSPResult handle_M16_message (GstRTSPWFDClient * client);
179
180 G_DEFINE_TYPE (GstRTSPWFDClient, gst_rtsp_wfd_client, GST_TYPE_RTSP_CLIENT);
181
182 static void
183 gst_rtsp_wfd_client_class_init (GstRTSPWFDClientClass * klass)
184 {
185   GObjectClass *gobject_class;
186   GstRTSPClientClass *rtsp_client_class;
187
188   g_type_class_add_private (klass, sizeof (GstRTSPWFDClientPrivate));
189
190   gobject_class = G_OBJECT_CLASS (klass);
191   rtsp_client_class = GST_RTSP_CLIENT_CLASS (klass);
192
193   gobject_class->get_property = gst_rtsp_wfd_client_get_property;
194   gobject_class->set_property = gst_rtsp_wfd_client_set_property;
195   gobject_class->finalize = gst_rtsp_wfd_client_finalize;
196
197   //klass->create_sdp = create_sdp;
198   //klass->configure_client_media = default_configure_client_media;
199   //klass->configure_client_transport = default_configure_client_transport;
200   //klass->params_set = default_params_set;
201   //klass->params_get = default_params_get;
202
203   rtsp_client_class->handle_options_request = handle_wfd_options_request;
204   rtsp_client_class->handle_set_param_request = handle_wfd_set_param_request;
205   rtsp_client_class->handle_get_param_request = handle_wfd_get_param_request;
206   rtsp_client_class->make_path_from_uri = wfd_make_path_from_uri;
207
208   rtsp_client_class->handle_response = handle_wfd_response;
209   rtsp_client_class->play_request = handle_wfd_play;
210
211   gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST] =
212       g_signal_new ("wfd-options-request", G_TYPE_FROM_CLASS (klass),
213       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
214           wfd_options_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER,
215       G_TYPE_NONE, 1, G_TYPE_POINTER);
216
217   gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST] =
218       g_signal_new ("wfd-get-parameter-request", G_TYPE_FROM_CLASS (klass),
219       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
220           wfd_get_param_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER,
221       G_TYPE_NONE, 1, G_TYPE_POINTER);
222
223   klass->wfd_options_request = wfd_options_request_done;
224   klass->wfd_get_param_request = wfd_get_param_request_done;
225
226   GST_DEBUG_CATEGORY_INIT (rtsp_wfd_client_debug, "rtspwfdclient", 0,
227       "GstRTSPWFDClient");
228 }
229
230 static void
231 gst_rtsp_wfd_client_init (GstRTSPWFDClient * client)
232 {
233   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
234
235   g_return_if_fail (priv != NULL);
236
237   client->priv = priv;
238   priv->protection_enabled = FALSE;
239   priv->video_native_resolution = GST_WFD_VIDEO_CEA_RESOLUTION;
240   priv->video_resolution_supported = GST_WFD_CEA_640x480P60;
241   priv->audio_codec = GST_WFD_AUDIO_AAC;
242   priv->keep_alive_flag = FALSE;
243   g_mutex_init (&priv->keep_alive_lock);
244
245   priv->host_address = NULL;
246   GST_INFO_OBJECT (client, "Client is initialized");
247 }
248
249 /* A client is finalized when the connection is broken */
250 static void
251 gst_rtsp_wfd_client_finalize (GObject * obj)
252 {
253   GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (obj);
254   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
255
256   g_return_if_fail (GST_IS_RTSP_WFD_CLIENT (obj));
257   g_return_if_fail (priv != NULL);
258
259   GST_INFO ("finalize client %p", client);
260
261   g_mutex_clear (&priv->keep_alive_lock);
262   G_OBJECT_CLASS (gst_rtsp_wfd_client_parent_class)->finalize (obj);
263 }
264
265 static void
266 gst_rtsp_wfd_client_get_property (GObject * object, guint propid,
267     GValue * value, GParamSpec * pspec)
268 {
269   //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object);
270
271   switch (propid) {
272     default:
273       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
274   }
275 }
276
277 static void
278 gst_rtsp_wfd_client_set_property (GObject * object, guint propid,
279     const GValue * value, GParamSpec * pspec)
280 {
281   //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object);
282
283   switch (propid) {
284     default:
285       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
286   }
287 }
288
289 /**
290  * gst_rtsp_wfd_client_new:
291  *
292  * Create a new #GstRTSPWFDClient instance.
293  *
294  * Returns: a new #GstRTSPWFDClient
295  */
296 GstRTSPWFDClient *
297 gst_rtsp_wfd_client_new (void)
298 {
299   GstRTSPWFDClient *result;
300
301   result = g_object_new (GST_TYPE_RTSP_WFD_CLIENT, NULL);
302
303   return result;
304 }
305
306 void
307 gst_rtsp_wfd_client_start_wfd (GstRTSPWFDClient * client)
308 {
309   GstRTSPResult res = GST_RTSP_OK;
310   GST_INFO_OBJECT (client, "gst_rtsp_wfd_client_start_wfd");
311
312   res = handle_M1_message (client);
313   if (res < GST_RTSP_OK) {
314     GST_ERROR_OBJECT (client, "handle_M1_message failed : %d", res);
315   }
316
317   return;
318 }
319
320 static void
321 wfd_options_request_done (GstRTSPWFDClient * client)
322 {
323   GstRTSPResult res = GST_RTSP_OK;
324   GST_INFO_OBJECT (client, "M2 done..");
325
326   res = handle_M3_message (client);
327   if (res < GST_RTSP_OK) {
328     GST_ERROR_OBJECT (client, "handle_M3_message failed : %d", res);
329   }
330
331   return;
332 }
333
334 static void
335 wfd_get_param_request_done (GstRTSPWFDClient * client)
336 {
337   GstRTSPResult res = GST_RTSP_OK;
338   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
339
340   g_return_if_fail (priv != NULL);
341
342   priv->m3_done = TRUE;
343   GST_INFO_OBJECT (client, "M3 done..");
344
345   res = handle_M4_message (client);
346   if (res < GST_RTSP_OK) {
347     GST_ERROR_OBJECT (client, "handle_M4_message failed : %d", res);
348   }
349
350   return;
351 }
352
353 static guint
354 wfd_get_prefered_audio_codec (guint8 srcAudioCodec,
355     guint sinkAudioCodec)
356 {
357   int i = 0;
358   guint codec = 0;
359   for (i = 0; i < 8; i++) {
360     if (((sinkAudioCodec << i) & 0x80)
361         && ((srcAudioCodec << i) & 0x80)) {
362       codec = (0x01 << (7 - i));
363       break;
364     }
365   }
366   return codec;
367 }
368
369 static guint64
370 wfd_get_prefered_resolution (guint64 srcResolution,
371     guint64 sinkResolution,
372     GstWFDVideoNativeResolution native,
373     guint32 * cMaxWidth,
374     guint32 * cMaxHeight, guint32 * cFramerate, guint32 * interleaved)
375 {
376   int i = 0;
377   guint64 resolution = 0;
378   for (i = 0; i < 32; i++) {
379     if (((sinkResolution << i) & 0x80000000)
380         && ((srcResolution << i) & 0x80000000)) {
381       resolution = (0x00000001 << (31 - i));
382       break;
383     }
384   }
385   switch (native) {
386     case GST_WFD_VIDEO_CEA_RESOLUTION:
387     {
388       switch (resolution) {
389         case GST_WFD_CEA_640x480P60:
390           *cMaxWidth = 640;
391           *cMaxHeight = 480;
392           *cFramerate = 60;
393           *interleaved = 0;
394           break;
395         case GST_WFD_CEA_720x480P60:
396           *cMaxWidth = 720;
397           *cMaxHeight = 480;
398           *cFramerate = 60;
399           *interleaved = 0;
400           break;
401         case GST_WFD_CEA_720x480I60:
402           *cMaxWidth = 720;
403           *cMaxHeight = 480;
404           *cFramerate = 60;
405           *interleaved = 1;
406           break;
407         case GST_WFD_CEA_720x576P50:
408           *cMaxWidth = 720;
409           *cMaxHeight = 576;
410           *cFramerate = 50;
411           *interleaved = 0;
412           break;
413         case GST_WFD_CEA_720x576I50:
414           *cMaxWidth = 720;
415           *cMaxHeight = 576;
416           *cFramerate = 50;
417           *interleaved = 1;
418           break;
419         case GST_WFD_CEA_1280x720P30:
420           *cMaxWidth = 1280;
421           *cMaxHeight = 720;
422           *cFramerate = 30;
423           *interleaved = 0;
424           break;
425         case GST_WFD_CEA_1280x720P60:
426           *cMaxWidth = 1280;
427           *cMaxHeight = 720;
428           *cFramerate = 60;
429           *interleaved = 0;
430           break;
431         case GST_WFD_CEA_1920x1080P30:
432           *cMaxWidth = 1920;
433           *cMaxHeight = 1080;
434           *cFramerate = 30;
435           *interleaved = 0;
436           break;
437         case GST_WFD_CEA_1920x1080P60:
438           *cMaxWidth = 1920;
439           *cMaxHeight = 1080;
440           *cFramerate = 60;
441           *interleaved = 0;
442           break;
443         case GST_WFD_CEA_1920x1080I60:
444           *cMaxWidth = 1920;
445           *cMaxHeight = 1080;
446           *cFramerate = 60;
447           *interleaved = 1;
448           break;
449         case GST_WFD_CEA_1280x720P25:
450           *cMaxWidth = 1280;
451           *cMaxHeight = 720;
452           *cFramerate = 25;
453           *interleaved = 0;
454           break;
455         case GST_WFD_CEA_1280x720P50:
456           *cMaxWidth = 1280;
457           *cMaxHeight = 720;
458           *cFramerate = 50;
459           *interleaved = 0;
460           break;
461         case GST_WFD_CEA_1920x1080P25:
462           *cMaxWidth = 1920;
463           *cMaxHeight = 1080;
464           *cFramerate = 25;
465           *interleaved = 0;
466           break;
467         case GST_WFD_CEA_1920x1080P50:
468           *cMaxWidth = 1920;
469           *cMaxHeight = 1080;
470           *cFramerate = 50;
471           *interleaved = 0;
472           break;
473         case GST_WFD_CEA_1920x1080I50:
474           *cMaxWidth = 1920;
475           *cMaxHeight = 1080;
476           *cFramerate = 50;
477           *interleaved = 1;
478           break;
479         case GST_WFD_CEA_1280x720P24:
480           *cMaxWidth = 1280;
481           *cMaxHeight = 720;
482           *cFramerate = 24;
483           *interleaved = 0;
484           break;
485         case GST_WFD_CEA_1920x1080P24:
486           *cMaxWidth = 1920;
487           *cMaxHeight = 1080;
488           *cFramerate = 24;
489           *interleaved = 0;
490           break;
491         default:
492           *cMaxWidth = 0;
493           *cMaxHeight = 0;
494           *cFramerate = 0;
495           *interleaved = 0;
496           break;
497       }
498     }
499       break;
500     case GST_WFD_VIDEO_VESA_RESOLUTION:
501     {
502       switch (resolution) {
503         case GST_WFD_VESA_800x600P30:
504           *cMaxWidth = 800;
505           *cMaxHeight = 600;
506           *cFramerate = 30;
507           *interleaved = 0;
508           break;
509         case GST_WFD_VESA_800x600P60:
510           *cMaxWidth = 800;
511           *cMaxHeight = 600;
512           *cFramerate = 60;
513           *interleaved = 0;
514           break;
515         case GST_WFD_VESA_1024x768P30:
516           *cMaxWidth = 1024;
517           *cMaxHeight = 768;
518           *cFramerate = 30;
519           *interleaved = 0;
520           break;
521         case GST_WFD_VESA_1024x768P60:
522           *cMaxWidth = 1024;
523           *cMaxHeight = 768;
524           *cFramerate = 60;
525           *interleaved = 0;
526           break;
527         case GST_WFD_VESA_1152x864P30:
528           *cMaxWidth = 1152;
529           *cMaxHeight = 864;
530           *cFramerate = 30;
531           *interleaved = 0;
532           break;
533         case GST_WFD_VESA_1152x864P60:
534           *cMaxWidth = 1152;
535           *cMaxHeight = 864;
536           *cFramerate = 60;
537           *interleaved = 0;
538           break;
539         case GST_WFD_VESA_1280x768P30:
540           *cMaxWidth = 1280;
541           *cMaxHeight = 768;
542           *cFramerate = 30;
543           *interleaved = 0;
544           break;
545         case GST_WFD_VESA_1280x768P60:
546           *cMaxWidth = 1280;
547           *cMaxHeight = 768;
548           *cFramerate = 60;
549           *interleaved = 0;
550           break;
551         case GST_WFD_VESA_1280x800P30:
552           *cMaxWidth = 1280;
553           *cMaxHeight = 800;
554           *cFramerate = 30;
555           *interleaved = 0;
556           break;
557         case GST_WFD_VESA_1280x800P60:
558           *cMaxWidth = 1280;
559           *cMaxHeight = 800;
560           *cFramerate = 60;
561           *interleaved = 0;
562           break;
563         case GST_WFD_VESA_1360x768P30:
564           *cMaxWidth = 1360;
565           *cMaxHeight = 768;
566           *cFramerate = 30;
567           *interleaved = 0;
568           break;
569         case GST_WFD_VESA_1360x768P60:
570           *cMaxWidth = 1360;
571           *cMaxHeight = 768;
572           *cFramerate = 60;
573           *interleaved = 0;
574           break;
575         case GST_WFD_VESA_1366x768P30:
576           *cMaxWidth = 1366;
577           *cMaxHeight = 768;
578           *cFramerate = 30;
579           *interleaved = 0;
580           break;
581         case GST_WFD_VESA_1366x768P60:
582           *cMaxWidth = 1366;
583           *cMaxHeight = 768;
584           *cFramerate = 60;
585           *interleaved = 0;
586           break;
587         case GST_WFD_VESA_1280x1024P30:
588           *cMaxWidth = 1280;
589           *cMaxHeight = 1024;
590           *cFramerate = 30;
591           *interleaved = 0;
592           break;
593         case GST_WFD_VESA_1280x1024P60:
594           *cMaxWidth = 1280;
595           *cMaxHeight = 1024;
596           *cFramerate = 60;
597           *interleaved = 0;
598           break;
599         case GST_WFD_VESA_1400x1050P30:
600           *cMaxWidth = 1400;
601           *cMaxHeight = 1050;
602           *cFramerate = 30;
603           *interleaved = 0;
604           break;
605         case GST_WFD_VESA_1400x1050P60:
606           *cMaxWidth = 1400;
607           *cMaxHeight = 1050;
608           *cFramerate = 60;
609           *interleaved = 0;
610           break;
611         case GST_WFD_VESA_1440x900P30:
612           *cMaxWidth = 1440;
613           *cMaxHeight = 900;
614           *cFramerate = 30;
615           *interleaved = 0;
616           break;
617         case GST_WFD_VESA_1440x900P60:
618           *cMaxWidth = 1440;
619           *cMaxHeight = 900;
620           *cFramerate = 60;
621           *interleaved = 0;
622           break;
623         case GST_WFD_VESA_1600x900P30:
624           *cMaxWidth = 1600;
625           *cMaxHeight = 900;
626           *cFramerate = 30;
627           *interleaved = 0;
628           break;
629         case GST_WFD_VESA_1600x900P60:
630           *cMaxWidth = 1600;
631           *cMaxHeight = 900;
632           *cFramerate = 60;
633           *interleaved = 0;
634           break;
635         case GST_WFD_VESA_1600x1200P30:
636           *cMaxWidth = 1600;
637           *cMaxHeight = 1200;
638           *cFramerate = 30;
639           *interleaved = 0;
640           break;
641         case GST_WFD_VESA_1600x1200P60:
642           *cMaxWidth = 1600;
643           *cMaxHeight = 1200;
644           *cFramerate = 60;
645           *interleaved = 0;
646           break;
647         case GST_WFD_VESA_1680x1024P30:
648           *cMaxWidth = 1680;
649           *cMaxHeight = 1024;
650           *cFramerate = 30;
651           *interleaved = 0;
652           break;
653         case GST_WFD_VESA_1680x1024P60:
654           *cMaxWidth = 1680;
655           *cMaxHeight = 1024;
656           *cFramerate = 60;
657           *interleaved = 0;
658           break;
659         case GST_WFD_VESA_1680x1050P30:
660           *cMaxWidth = 1680;
661           *cMaxHeight = 1050;
662           *cFramerate = 30;
663           *interleaved = 0;
664           break;
665         case GST_WFD_VESA_1680x1050P60:
666           *cMaxWidth = 1680;
667           *cMaxHeight = 1050;
668           *cFramerate = 60;
669           *interleaved = 0;
670           break;
671         case GST_WFD_VESA_1920x1200P30:
672           *cMaxWidth = 1920;
673           *cMaxHeight = 1200;
674           *cFramerate = 30;
675           *interleaved = 0;
676           break;
677         case GST_WFD_VESA_1920x1200P60:
678           *cMaxWidth = 1920;
679           *cMaxHeight = 1200;
680           *cFramerate = 60;
681           *interleaved = 0;
682           break;
683         default:
684           *cMaxWidth = 0;
685           *cMaxHeight = 0;
686           *cFramerate = 0;
687           *interleaved = 0;
688           break;
689       }
690     }
691       break;
692     case GST_WFD_VIDEO_HH_RESOLUTION:
693     {
694       *interleaved = 0;
695       switch (resolution) {
696         case GST_WFD_HH_800x480P30:
697           *cMaxWidth = 800;
698           *cMaxHeight = 480;
699           *cFramerate = 30;
700           break;
701         case GST_WFD_HH_800x480P60:
702           *cMaxWidth = 800;
703           *cMaxHeight = 480;
704           *cFramerate = 60;
705           break;
706         case GST_WFD_HH_854x480P30:
707           *cMaxWidth = 854;
708           *cMaxHeight = 480;
709           *cFramerate = 30;
710           break;
711         case GST_WFD_HH_854x480P60:
712           *cMaxWidth = 854;
713           *cMaxHeight = 480;
714           *cFramerate = 60;
715           break;
716         case GST_WFD_HH_864x480P30:
717           *cMaxWidth = 864;
718           *cMaxHeight = 480;
719           *cFramerate = 30;
720           break;
721         case GST_WFD_HH_864x480P60:
722           *cMaxWidth = 864;
723           *cMaxHeight = 480;
724           *cFramerate = 60;
725           break;
726         case GST_WFD_HH_640x360P30:
727           *cMaxWidth = 640;
728           *cMaxHeight = 360;
729           *cFramerate = 30;
730           break;
731         case GST_WFD_HH_640x360P60:
732           *cMaxWidth = 640;
733           *cMaxHeight = 360;
734           *cFramerate = 60;
735           break;
736         case GST_WFD_HH_960x540P30:
737           *cMaxWidth = 960;
738           *cMaxHeight = 540;
739           *cFramerate = 30;
740           break;
741         case GST_WFD_HH_960x540P60:
742           *cMaxWidth = 960;
743           *cMaxHeight = 540;
744           *cFramerate = 60;
745           break;
746         case GST_WFD_HH_848x480P30:
747           *cMaxWidth = 848;
748           *cMaxHeight = 480;
749           *cFramerate = 30;
750           break;
751         case GST_WFD_HH_848x480P60:
752           *cMaxWidth = 848;
753           *cMaxHeight = 480;
754           *cFramerate = 60;
755           break;
756         default:
757           *cMaxWidth = 0;
758           *cMaxHeight = 0;
759           *cFramerate = 0;
760           *interleaved = 0;
761           break;
762       }
763     }
764     break;
765
766     default:
767       *cMaxWidth = 0;
768       *cMaxHeight = 0;
769       *cFramerate = 0;
770       *interleaved = 0;
771       break;
772   }
773   return resolution;
774 }
775
776 static gchar *
777 wfd_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri)
778 {
779   gchar *path;
780
781   GST_DEBUG_OBJECT (client, "Got URI host : %s", uri->host);
782   GST_DEBUG_OBJECT (client, "Got URI abspath : %s", uri->abspath);
783
784   path = g_strdup ("/wfd1.0/streamid=0");
785
786   return path;
787 }
788
789 static void
790 handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx)
791 {
792   wfd_set_keep_alive_condition(client);
793 }
794
795 static void
796 handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx)
797 {
798   GstRTSPResult res = GST_RTSP_OK;
799   guint8 *data = NULL;
800   guint size = 0;
801
802   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
803   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
804
805   g_return_if_fail (priv != NULL);
806
807   GST_INFO_OBJECT (_client, "Handling response..");
808
809   if (!ctx) {
810     GST_ERROR_OBJECT (_client, "Context is NULL");
811     goto error;
812   }
813
814   if (!ctx->response) {
815     GST_ERROR_OBJECT (_client, "Response is NULL");
816     goto error;
817   }
818
819   /* parsing the GET_PARAMTER response */
820   res = gst_rtsp_message_get_body (ctx->response, (guint8 **) & data, &size);
821   if (res != GST_RTSP_OK) {
822     GST_ERROR_OBJECT (_client, "Failed to get body of response...");
823     return;
824   }
825
826   GST_INFO_OBJECT (_client, "Response body is %d", size);
827   if (size > 0) {
828     if (!priv->m3_done) {
829       GstWFDResult wfd_res;
830       GstWFDMessage *msg = NULL;
831       /* Parse M3 response from sink */
832       wfd_res = gst_wfd_message_new (&msg);
833       if (wfd_res != GST_WFD_OK) {
834         GST_ERROR_OBJECT (client, "Failed to create wfd message...");
835         goto error;
836       }
837
838       wfd_res = gst_wfd_message_init (msg);
839       if (wfd_res != GST_WFD_OK) {
840         GST_ERROR_OBJECT (client, "Failed to init wfd message...");
841         goto error;
842       }
843
844       wfd_res = gst_wfd_message_parse_buffer (data, size, msg);
845
846       GST_DEBUG_OBJECT (client, "M3 response server side message body: %s",
847           gst_wfd_message_as_text (msg));
848
849       /* Get the audio formats supported by WFDSink */
850       if (msg->audio_codecs) {
851         wfd_res =
852             gst_wfd_message_get_supported_audio_format (msg, &priv->caCodec,
853             &priv->cFreq, &priv->cChanels, &priv->cBitwidth, &priv->caLatency);
854         if (wfd_res != GST_WFD_OK) {
855           GST_WARNING_OBJECT (client,
856               "Failed to get wfd support audio formats...");
857           goto error;
858         }
859       }
860
861       /* Get the Video formats supported by WFDSink */
862       wfd_res =
863           gst_wfd_message_get_supported_video_format (msg, &priv->cvCodec,
864           &priv->cNative, &priv->cNativeResolution,
865           (guint64 *) & priv->cCEAResolution,
866           (guint64 *) & priv->cVESAResolution,
867           (guint64 *) & priv->cHHResolution, &priv->cProfile, &priv->cLevel,
868           &priv->cvLatency, &priv->cMaxHeight, &priv->cMaxWidth,
869           &priv->cmin_slice_size, &priv->cslice_enc_params,
870           &priv->cframe_rate_control);
871       if (wfd_res != GST_WFD_OK) {
872         GST_WARNING_OBJECT (client,
873             "Failed to get wfd supported video formats...");
874         goto error;
875       }
876
877       if (msg->client_rtp_ports) {
878         /* Get the RTP ports preferred by WFDSink */
879         wfd_res =
880             gst_wfd_message_get_prefered_rtp_ports (msg, &priv->ctrans,
881             &priv->cprofile, &priv->clowertrans, &priv->crtp_port0,
882             &priv->crtp_port1);
883         if (wfd_res != GST_WFD_OK) {
884           GST_WARNING_OBJECT (client,
885               "Failed to get wfd prefered RTP ports...");
886           goto error;
887         }
888       }
889
890       if (msg->display_edid) {
891         guint32 edid_block_count = 0;
892         gchar *edid_payload = NULL;
893         priv->edid_supported = FALSE;
894         /* Get the display edid preferred by WFDSink */
895         GST_DEBUG_OBJECT (client, "Going to gst_wfd_message_get_display_edid");
896         wfd_res =
897             gst_wfd_message_get_display_edid (msg, &priv->edid_supported,
898             &edid_block_count, &edid_payload);
899         if (wfd_res != GST_WFD_OK) {
900           GST_ERROR_OBJECT (client, "Failed to get wfd display edid...");
901           goto error;
902         }
903         GST_DEBUG_OBJECT (client, " edid supported: %d edid_block_count: %d",
904             priv->edid_supported, edid_block_count);
905         if (priv->edid_supported) {
906           priv->edid_hres = 0;
907           priv->edid_vres = 0;
908           priv->edid_hres =
909               (guint32) (((edid_payload[54 + 4] >> 4) << 8) | edid_payload[54 +
910                   2]);
911           priv->edid_vres =
912               (guint32) (((edid_payload[54 + 7] >> 4) << 8) | edid_payload[54 +
913                   5]);
914           GST_DEBUG_OBJECT (client, " edid supported Hres: %d Wres: %d",
915               priv->edid_hres, priv->edid_vres);
916           if ((priv->edid_hres < 640) || (priv->edid_vres < 480)
917               || (priv->edid_hres > 1920) || (priv->edid_vres > 1080)) {
918             priv->edid_hres = 0;
919             priv->edid_vres = 0;
920             priv->edid_supported = FALSE;
921             GST_WARNING_OBJECT (client, " edid invalid resolutions");
922           }
923         }
924       }
925
926       if (msg->content_protection) {
927 #if 0
928         /*Get the hdcp version and tcp port by WFDSink */
929         wfd_res =
930             gst_wfd_message_get_contentprotection_type (msg,
931             &priv->hdcp_version, &priv->hdcp_tcpport);
932         GST_DEBUG ("hdcp version =%d, tcp port = %d", priv->hdcp_version,
933             priv->hdcp_tcpport);
934         if (priv->hdcp_version > 0 && priv->hdcp_tcpport > 0)
935           priv->protection_enabled = TRUE;
936
937         if (wfd_res != GST_WFD_OK) {
938           GST_WARNING_OBJECT (client,
939               "Failed to get wfd content protection...");
940           goto error;
941         }
942 #else
943         GST_WARNING_OBJECT (client, "Don't use content protection");
944 #endif
945       }
946
947       g_signal_emit (_client,
948           gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST], 0,
949           ctx);
950     } else {
951       /* TODO-WFD: Handle another GET_PARAMETER response with body */
952     }
953   } else if (size == 0) {
954     if (!priv->m1_done) {
955       GST_INFO_OBJECT (_client, "M1 response is done");
956       priv->m1_done = TRUE;
957     } else if (!priv->m4_done) {
958       GST_INFO_OBJECT (_client, "M4 response is done");
959       priv->m4_done = TRUE;
960
961       gst_rtsp_wfd_client_trigger_request (_client, WFD_TRIGGER_SETUP);
962     } else {
963       g_mutex_lock(&priv->keep_alive_lock);
964       if (priv->keep_alive_flag == FALSE) {
965         GST_INFO_OBJECT (_client, "M16 response is done");
966         priv->keep_alive_flag = TRUE;
967       }
968       g_mutex_unlock(&priv->keep_alive_lock);
969     }
970   }
971
972   return;
973
974 error:
975   return;
976 }
977
978 static gboolean
979 handle_wfd_options_request (GstRTSPClient * client, GstRTSPContext * ctx)
980 {
981   GstRTSPResult res = GST_RTSP_OK;
982   GstRTSPMethod options;
983   gchar *tmp = NULL;
984   gchar *str = NULL;
985   gchar *user_agent = NULL;
986
987   options = GST_RTSP_OPTIONS |
988       GST_RTSP_PAUSE |
989       GST_RTSP_PLAY |
990       GST_RTSP_SETUP |
991       GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
992
993   str = gst_rtsp_options_as_text (options);
994
995   /*append WFD specific method */
996   tmp = g_strdup (", org.wfa.wfd1.0");
997   g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
998
999   gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK,
1000       gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request);
1001
1002   gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_PUBLIC, str);
1003   g_free (str);
1004   str = NULL;
1005
1006   res =
1007       gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_USER_AGENT,
1008       &user_agent, 0);
1009   if (res == GST_RTSP_OK) {
1010     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_USER_AGENT,
1011         user_agent);
1012   } else {
1013     return FALSE;
1014   }
1015
1016   res = gst_rtsp_client_send_message (client, NULL, ctx->response);
1017   if (res != GST_RTSP_OK) {
1018     GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
1019     return FALSE;
1020   }
1021
1022   GST_DEBUG_OBJECT (client, "Sent M2 response...");
1023
1024   g_signal_emit (client,
1025       gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST], 0, ctx);
1026
1027   return TRUE;
1028 }
1029
1030 static gboolean
1031 handle_wfd_get_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
1032 {
1033   GstRTSPResult res = GST_RTSP_OK;
1034   guint8 *data = NULL;
1035   guint size = 0;
1036
1037   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
1038
1039   /* parsing the GET_PARAMTER request */
1040   res = gst_rtsp_message_get_body (ctx->request, (guint8 **) & data, &size);
1041   if (res != GST_RTSP_OK) {
1042     GST_ERROR_OBJECT (_client, "Failed to get body of request...");
1043     return FALSE;
1044   }
1045
1046   if (size == 0) {
1047     send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1048   } else {
1049     /* TODO-WFD: Handle other GET_PARAMETER request from sink */
1050   }
1051
1052   return TRUE;
1053 }
1054
1055 static gboolean
1056 handle_wfd_set_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
1057 {
1058   GstRTSPResult res = GST_RTSP_OK;
1059   guint8 *data = NULL;
1060   guint size = 0;
1061
1062   GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
1063
1064   res = gst_rtsp_message_get_body (ctx->request, &data, &size);
1065   if (res != GST_RTSP_OK)
1066     goto bad_request;
1067
1068   if (size == 0) {
1069     /* no body, keep-alive request */
1070     send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1071   } else {
1072     if (data != NULL) {
1073       GST_INFO_OBJECT (_client, "SET_PARAMETER Request : %s(%d)", data, size);
1074       if (g_strcmp0 ((const gchar *) data, "wfd_idr_request"))
1075         send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1076 #if 0
1077       else
1078         /* TODO-WFD : Handle other set param request */
1079         send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1080 #endif
1081     } else {
1082       goto bad_request;
1083     }
1084   }
1085
1086   return TRUE;
1087
1088   /* ERRORS */
1089 bad_request:
1090   {
1091     GST_ERROR ("_client %p: bad request", _client);
1092     send_generic_wfd_response (_client, GST_RTSP_STS_BAD_REQUEST, ctx);
1093     return FALSE;
1094   }
1095 }
1096
1097 #if 0
1098 static gboolean
1099 gst_rtsp_wfd_client_parse_methods (GstRTSPWFDClient * client,
1100     GstRTSPMessage * response)
1101 {
1102   GstRTSPHeaderField field;
1103   gchar *respoptions;
1104   gchar **options;
1105   gint indx = 0;
1106   gint i;
1107   gboolean found_wfd_method = FALSE;
1108
1109   /* reset supported methods */
1110   client->supported_methods = 0;
1111
1112   /* Try Allow Header first */
1113   field = GST_RTSP_HDR_ALLOW;
1114   while (TRUE) {
1115     respoptions = NULL;
1116     gst_rtsp_message_get_header (response, field, &respoptions, indx);
1117     if (indx == 0 && !respoptions) {
1118       /* if no Allow header was found then try the Public header... */
1119       field = GST_RTSP_HDR_PUBLIC;
1120       gst_rtsp_message_get_header (response, field, &respoptions, indx);
1121     }
1122     if (!respoptions)
1123       break;
1124
1125     /* If we get here, the server gave a list of supported methods, parse
1126      * them here. The string is like:
1127      *
1128      * OPTIONS,  PLAY, SETUP, ...
1129      */
1130     options = g_strsplit (respoptions, ",", 0);
1131
1132     for (i = 0; options[i]; i++) {
1133       gchar *stripped;
1134       gint method;
1135
1136       stripped = g_strstrip (options[i]);
1137       method = gst_rtsp_find_method (stripped);
1138
1139       if (!g_ascii_strcasecmp ("org.wfa.wfd1.0", stripped))
1140         found_wfd_method = TRUE;
1141
1142       /* keep bitfield of supported methods */
1143       if (method != GST_RTSP_INVALID)
1144         client->supported_methods |= method;
1145     }
1146     g_strfreev (options);
1147
1148     indx++;
1149   }
1150
1151   if (!found_wfd_method) {
1152     GST_ERROR_OBJECT (client,
1153         "WFD client is not supporting WFD mandatory message : org.wfa.wfd1.0...");
1154     goto no_required_methods;
1155   }
1156
1157   /* Checking mandatory method */
1158   if (!(client->supported_methods & GST_RTSP_SET_PARAMETER)) {
1159     GST_ERROR_OBJECT (client,
1160         "WFD client is not supporting WFD mandatory message : SET_PARAMETER...");
1161     goto no_required_methods;
1162   }
1163
1164   /* Checking mandatory method */
1165   if (!(client->supported_methods & GST_RTSP_GET_PARAMETER)) {
1166     GST_ERROR_OBJECT (client,
1167         "WFD client is not supporting WFD mandatory message : GET_PARAMETER...");
1168     goto no_required_methods;
1169   }
1170
1171   if (!(client->supported_methods & GST_RTSP_OPTIONS)) {
1172     GST_INFO_OBJECT (client, "assuming OPTIONS is supported by client...");
1173     client->supported_methods |= GST_RTSP_OPTIONS;
1174   }
1175
1176   return TRUE;
1177
1178 /* ERRORS */
1179 no_required_methods:
1180   {
1181     GST_ELEMENT_ERROR (client, RESOURCE, OPEN_READ, (NULL),
1182         ("WFD Client does not support mandatory methods."));
1183     return FALSE;
1184   }
1185 }
1186 #endif
1187
1188 typedef enum
1189 {
1190   M1_REQ_MSG,
1191   M1_RES_MSG,
1192   M2_REQ_MSG,
1193   M2_RES_MSG,
1194   M3_REQ_MSG,
1195   M3_RES_MSG,
1196   M4_REQ_MSG,
1197   M4_RES_MSG,
1198   M5_REQ_MSG,
1199   TEARDOWN_TRIGGER,
1200   PLAY_TRIGGER,
1201   PAUSE_TRIGGER,
1202 } GstWFDMessageType;
1203
1204 static gboolean
1205 _set_negotiated_audio_codec (GstRTSPWFDClient *client,
1206     guint audio_codec)
1207 {
1208   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1209
1210   GstRTSPMediaFactory *factory = NULL;
1211   GstRTSPMountPoints *mount_points = NULL;
1212   gchar *path = NULL;
1213   gint matched = 0;
1214   gboolean ret = TRUE;
1215
1216   if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) {
1217     ret = FALSE;
1218     GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no mount points...");
1219     goto no_mount_points;
1220   }
1221
1222   path = g_strdup(WFD_MOUNT_POINT);
1223   if (!path) {
1224     ret = FALSE;
1225     GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no path...");
1226     goto no_path;
1227   }
1228
1229   if (!(factory = gst_rtsp_mount_points_match (mount_points,
1230           path, &matched))) {
1231     GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no factory...");
1232     ret = FALSE;
1233     goto no_factory;
1234   }
1235
1236   gst_rtsp_media_factory_wfd_set_audio_codec (factory,
1237       audio_codec);
1238   ret = TRUE;
1239
1240   g_object_unref(factory);
1241
1242 no_factory:
1243   g_free(path);
1244 no_path:
1245   g_object_unref(mount_points);
1246 no_mount_points:
1247   return ret;
1248 }
1249
1250 static gboolean
1251 _set_negotiated_resolution(GstRTSPWFDClient *client,
1252     guint32 width, guint32 height)
1253 {
1254   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1255
1256   GstRTSPMediaFactory *factory = NULL;
1257   GstRTSPMountPoints *mount_points = NULL;
1258   gchar *path = NULL;
1259   gint matched = 0;
1260   gboolean ret = TRUE;
1261
1262   if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) {
1263     ret = FALSE;
1264     GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no mount points...");
1265     goto no_mount_points;
1266   }
1267
1268   path = g_strdup(WFD_MOUNT_POINT);
1269   if (!path) {
1270     ret = FALSE;
1271     GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no path...");
1272     goto no_path;
1273   }
1274
1275   if (!(factory = gst_rtsp_mount_points_match (mount_points,
1276           path, &matched))) {
1277     GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no factory...");
1278     ret = FALSE;
1279     goto no_factory;
1280   }
1281
1282   gst_rtsp_media_factory_wfd_set_negotiated_resolution(factory,
1283       width, height);
1284   ret = TRUE;
1285
1286   g_object_unref(factory);
1287
1288 no_factory:
1289   g_free(path);
1290 no_path:
1291   g_object_unref(mount_points);
1292 no_mount_points:
1293   return ret;
1294 }
1295
1296 static void
1297 _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type,
1298     gchar ** data, guint * len)
1299 {
1300   GString *buf = NULL;
1301   GstWFDMessage *msg = NULL;
1302   GstWFDResult wfd_res = GST_WFD_EINVAL;
1303   GstRTSPWFDClientPrivate *priv = NULL;
1304   priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
1305
1306   g_return_if_fail (priv != NULL);
1307
1308   buf = g_string_new ("");
1309   g_return_if_fail (buf != NULL);
1310
1311   if (msg_type == M3_REQ_MSG) {
1312     /* create M3 request to be sent */
1313     wfd_res = gst_wfd_message_new (&msg);
1314     if (wfd_res != GST_WFD_OK) {
1315       GST_ERROR_OBJECT (client, "Failed to create wfd message...");
1316       goto error;
1317     }
1318
1319     wfd_res = gst_wfd_message_init (msg);
1320     if (wfd_res != GST_WFD_OK) {
1321       GST_ERROR_OBJECT (client, "Failed to init wfd message...");
1322       goto error;
1323     }
1324
1325     /* set the supported audio formats by the WFD server */
1326     wfd_res =
1327         gst_wfd_message_set_supported_audio_format (msg, GST_WFD_AUDIO_UNKNOWN,
1328         GST_WFD_FREQ_UNKNOWN, GST_WFD_CHANNEL_UNKNOWN, 0, 0);
1329     if (wfd_res != GST_WFD_OK) {
1330       GST_ERROR_OBJECT (client,
1331           "Failed to set supported audio formats on wfd message...");
1332       goto error;
1333     }
1334
1335     /* set the supported Video formats by the WFD server */
1336     wfd_res =
1337         gst_wfd_message_set_supported_video_format (msg, GST_WFD_VIDEO_UNKNOWN,
1338         GST_WFD_VIDEO_CEA_RESOLUTION, GST_WFD_CEA_UNKNOWN, GST_WFD_CEA_UNKNOWN,
1339         GST_WFD_VESA_UNKNOWN, GST_WFD_HH_UNKNOWN, GST_WFD_H264_UNKNOWN_PROFILE,
1340         GST_WFD_H264_LEVEL_UNKNOWN, 0, 0, 0, 0, 0, 0);
1341     if (wfd_res != GST_WFD_OK) {
1342       GST_ERROR_OBJECT (client,
1343           "Failed to set supported video formats on wfd message...");
1344       goto error;
1345     }
1346
1347     wfd_res = gst_wfd_message_set_display_edid (msg, 0, 0, NULL);
1348     if (wfd_res != GST_WFD_OK) {
1349       GST_ERROR_OBJECT (client,
1350           "Failed to set display edid type on wfd message...");
1351       goto error;
1352     }
1353
1354     if (priv->protection_enabled) {
1355       wfd_res =
1356           gst_wfd_message_set_contentprotection_type (msg, GST_WFD_HDCP_NONE,
1357           0);
1358       if (wfd_res != GST_WFD_OK) {
1359         GST_ERROR_OBJECT (client,
1360             "Failed to set supported content protection type on wfd message...");
1361         goto error;
1362       }
1363     }
1364
1365     /* set the preffered RTP ports for the WFD server */
1366     wfd_res =
1367         gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_UNKNOWN,
1368         GST_WFD_RTSP_PROFILE_UNKNOWN, GST_WFD_RTSP_LOWER_TRANS_UNKNOWN, 0, 0);
1369     if (wfd_res != GST_WFD_OK) {
1370       GST_ERROR_OBJECT (client,
1371           "Failed to set supported video formats on wfd message...");
1372       goto error;
1373     }
1374
1375     *data = gst_wfd_message_param_names_as_text (msg);
1376     if (*data == NULL) {
1377       GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
1378       goto error;
1379     } else {
1380       *len = strlen (*data);
1381     }
1382   } else if (msg_type == M4_REQ_MSG) {
1383     GstRTSPUrl *url = NULL;
1384
1385     GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1386     GstRTSPConnection *connection =
1387         gst_rtsp_client_get_connection (parent_client);
1388
1389     /* Parameters for the preffered audio formats */
1390     GstWFDAudioFormats taudiocodec = GST_WFD_AUDIO_UNKNOWN;
1391     GstWFDAudioFreq taudiofreq = GST_WFD_FREQ_UNKNOWN;
1392     GstWFDAudioChannels taudiochannels = GST_WFD_CHANNEL_UNKNOWN;
1393
1394     /* Parameters for the preffered video formats */
1395     GstWFDVideoCEAResolution tcCEAResolution = GST_WFD_CEA_UNKNOWN;
1396     GstWFDVideoVESAResolution tcVESAResolution = GST_WFD_VESA_UNKNOWN;
1397     GstWFDVideoHHResolution tcHHResolution = GST_WFD_HH_UNKNOWN;
1398     GstWFDVideoH264Profile tcProfile;
1399     GstWFDVideoH264Level tcLevel;
1400     guint64 resolution_supported = 0;
1401
1402     url = gst_rtsp_connection_get_url (connection);
1403     if (url == NULL) {
1404       GST_ERROR_OBJECT (client, "Failed to get connection URL");
1405       return;
1406     }
1407
1408     /* Logic to negotiate with information of M3 response */
1409     /* create M4 request to be sent */
1410     wfd_res = gst_wfd_message_new (&msg);
1411     if (wfd_res != GST_WFD_OK) {
1412       GST_ERROR_OBJECT (client, "Failed to create wfd message...");
1413       goto error;
1414     }
1415
1416     wfd_res = gst_wfd_message_init (msg);
1417     if (wfd_res != GST_WFD_OK) {
1418       GST_ERROR_OBJECT (client, "Failed to init wfd message...");
1419       goto error;
1420     }
1421
1422     g_string_append_printf (buf, "rtsp://");
1423
1424     if (priv->host_address) {
1425       g_string_append (buf, priv->host_address);
1426     } else {
1427       GST_ERROR_OBJECT (client, "Failed to get host address");
1428       if (buf) g_string_free (buf, FALSE);
1429       goto error;
1430     }
1431
1432     g_string_append_printf (buf, "/wfd1.0/streamid=0");
1433     wfd_res =
1434         gst_wfd_message_set_presentation_url (msg, g_string_free (buf, FALSE),
1435         NULL);
1436
1437     if (wfd_res != GST_WFD_OK) {
1438       GST_ERROR_OBJECT (client, "Failed to set presentation url");
1439       goto error;
1440     }
1441
1442     taudiocodec = wfd_get_prefered_audio_codec (priv->audio_codec, priv->caCodec);
1443     priv->caCodec = taudiocodec;
1444     if (!_set_negotiated_audio_codec(client, priv->caCodec)) {
1445       GST_ERROR_OBJECT (client, "Failed to set negotiated "
1446           "audio codec to media factory...");
1447     }
1448
1449     if (priv->cFreq & GST_WFD_FREQ_48000)
1450       taudiofreq = GST_WFD_FREQ_48000;
1451     else if (priv->cFreq & GST_WFD_FREQ_44100)
1452       taudiofreq = GST_WFD_FREQ_44100;
1453     priv->cFreq = taudiofreq;
1454
1455     /* TODO-WFD: Currently only 2 channels is present */
1456     if (priv->cChanels & GST_WFD_CHANNEL_8)
1457       taudiochannels = GST_WFD_CHANNEL_2;
1458     else if (priv->cChanels & GST_WFD_CHANNEL_6)
1459       taudiochannels = GST_WFD_CHANNEL_2;
1460     else if (priv->cChanels & GST_WFD_CHANNEL_4)
1461       taudiochannels = GST_WFD_CHANNEL_2;
1462     else if (priv->cChanels & GST_WFD_CHANNEL_2)
1463       taudiochannels = GST_WFD_CHANNEL_2;
1464     priv->cChanels = taudiochannels;
1465
1466     wfd_res =
1467         gst_wfd_message_set_prefered_audio_format (msg, taudiocodec, taudiofreq,
1468         taudiochannels, priv->cBitwidth, priv->caLatency);
1469     if (wfd_res != GST_WFD_OK) {
1470       GST_ERROR_OBJECT (priv, "Failed to set preffered audio formats...");
1471       goto error;
1472     }
1473
1474     /* Set the preffered video formats */
1475     priv->cvCodec = GST_WFD_VIDEO_H264;
1476     priv->cProfile = tcProfile = GST_WFD_H264_BASE_PROFILE;
1477     priv->cLevel = tcLevel = GST_WFD_H264_LEVEL_3_1;
1478
1479     resolution_supported = priv->video_resolution_supported;
1480
1481     /* TODO-WFD: Need to verify this logic
1482        if(priv->edid_supported) {
1483        if (priv->edid_hres < 1920) resolution_supported = resolution_supported & 0x8C7F;
1484        if (priv->edid_hres < 1280) resolution_supported = resolution_supported & 0x1F;
1485        if (priv->edid_hres < 720) resolution_supported = resolution_supported & 0x01;
1486        }
1487      */
1488
1489     if (priv->video_native_resolution == GST_WFD_VIDEO_CEA_RESOLUTION) {
1490       tcCEAResolution =
1491           wfd_get_prefered_resolution (resolution_supported,
1492           priv->cCEAResolution, priv->video_native_resolution, &priv->cMaxWidth,
1493           &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved);
1494       GST_DEBUG
1495           ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1496           tcCEAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1497           priv->cInterleaved);
1498     } else if (priv->video_native_resolution == GST_WFD_VIDEO_VESA_RESOLUTION) {
1499       tcVESAResolution =
1500           wfd_get_prefered_resolution (resolution_supported,
1501           priv->cVESAResolution, priv->video_native_resolution,
1502           &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate,
1503           &priv->cInterleaved);
1504       GST_DEBUG
1505           ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1506           tcVESAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1507           priv->cInterleaved);
1508     } else if (priv->video_native_resolution == GST_WFD_VIDEO_HH_RESOLUTION) {
1509       tcHHResolution =
1510           wfd_get_prefered_resolution (resolution_supported,
1511           priv->cHHResolution, priv->video_native_resolution, &priv->cMaxWidth,
1512           &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved);
1513       GST_DEBUG
1514           ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1515           tcHHResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1516           priv->cInterleaved);
1517     }
1518
1519     if (!_set_negotiated_resolution(client, priv->cMaxWidth,
1520           priv->cMaxHeight)) {
1521       GST_ERROR_OBJECT (client, "Failed to set negotiated "
1522           "resolution to media factory...");
1523     }
1524
1525     wfd_res =
1526         gst_wfd_message_set_prefered_video_format (msg, priv->cvCodec,
1527         priv->video_native_resolution, GST_WFD_CEA_UNKNOWN, tcCEAResolution,
1528         tcVESAResolution, tcHHResolution, tcProfile, tcLevel, priv->cvLatency,
1529         priv->cMaxWidth, priv->cMaxHeight, priv->cmin_slice_size,
1530         priv->cslice_enc_params, priv->cframe_rate_control);
1531
1532     if (wfd_res != GST_WFD_OK) {
1533       GST_ERROR_OBJECT (client, "Failed to set preffered video formats...");
1534       goto error;
1535     }
1536
1537     /* set the preffered RTP ports for the WFD server */
1538     wfd_res =
1539         gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP,
1540         GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1);
1541     if (wfd_res != GST_WFD_OK) {
1542       GST_ERROR_OBJECT (client,
1543           "Failed to set supported video formats on wfd message...");
1544       goto error;
1545     }
1546
1547     *data = gst_wfd_message_as_text (msg);
1548     if (*data == NULL) {
1549       GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
1550       goto error;
1551     } else {
1552       *len = strlen (*data);
1553     }
1554   } else if (msg_type == M5_REQ_MSG) {
1555     g_string_append (buf, "wfd_trigger_method: SETUP");
1556     g_string_append (buf, "\r\n");
1557     *len = buf->len;
1558     *data = g_string_free (buf, FALSE);
1559   } else if (msg_type == TEARDOWN_TRIGGER) {
1560     g_string_append (buf, "wfd_trigger_method: TEARDOWN");
1561     g_string_append (buf, "\r\n");
1562     *len = buf->len;
1563     *data = g_string_free (buf, FALSE);
1564   } else if (msg_type == PLAY_TRIGGER) {
1565     g_string_append (buf, "wfd_trigger_method: PLAY");
1566     g_string_append (buf, "\r\n");
1567     *len = buf->len;
1568     *data = g_string_free (buf, FALSE);
1569   } else if (msg_type == PAUSE_TRIGGER) {
1570     g_string_append (buf, "wfd_trigger_method: PAUSE");
1571     g_string_append (buf, "\r\n");
1572     *len = buf->len;
1573     *data = g_string_free (buf, FALSE);
1574   } else {
1575     return;
1576   }
1577
1578   return;
1579
1580 error:
1581   *data = NULL;
1582   *len = 0;
1583
1584   return;
1585 }
1586
1587 /**
1588 * prepare_request:
1589 * @client: client object
1590 * @request : requst message to be prepared
1591 * @method : RTSP method of the request
1592 * @url : url need to be in the request
1593 * @message_type : WFD message type
1594 * @trigger_type : trigger method to be used for M5 mainly
1595 *
1596 * Prepares request based on @method & @message_type
1597 *
1598 * Returns: a #GstRTSPResult.
1599 */
1600 GstRTSPResult
1601 prepare_request (GstRTSPWFDClient * client, GstRTSPMessage * request,
1602     GstRTSPMethod method, gchar * url)
1603 {
1604   GstRTSPResult res = GST_RTSP_OK;
1605   gchar *str = NULL;
1606
1607   if (method == GST_RTSP_GET_PARAMETER || method == GST_RTSP_SET_PARAMETER) {
1608     g_free (url);
1609     url = g_strdup ("rtsp://localhost/wfd1.0");
1610   }
1611
1612   GST_DEBUG_OBJECT (client, "Preparing request: %d", method);
1613
1614   /* initialize the request */
1615   res = gst_rtsp_message_init_request (request, method, url);
1616   if (res < 0) {
1617     GST_ERROR ("init request failed");
1618     return res;
1619   }
1620
1621   switch (method) {
1622       /* Prepare OPTIONS request to send */
1623     case GST_RTSP_OPTIONS:{
1624       /* add wfd specific require filed "org.wfa.wfd1.0" */
1625       str = g_strdup ("org.wfa.wfd1.0");
1626       res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_REQUIRE, str);
1627       if (res < 0) {
1628         GST_ERROR ("Failed to add header");
1629         g_free (str);
1630         return res;
1631       }
1632
1633       g_free (str);
1634       break;
1635     }
1636
1637       /* Prepare GET_PARAMETER request */
1638     case GST_RTSP_GET_PARAMETER:{
1639       gchar *msg = NULL;
1640       guint msglen = 0;
1641       GString *msglength;
1642
1643       /* add content type */
1644       res =
1645           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1646           "text/parameters");
1647       if (res < 0) {
1648         GST_ERROR ("Failed to add header");
1649         return res;
1650       }
1651
1652       _set_wfd_message_body (client, M3_REQ_MSG, &msg, &msglen);
1653       msglength = g_string_new ("");
1654       g_string_append_printf (msglength, "%d", msglen);
1655       GST_DEBUG ("M3 server side message body: %s", msg);
1656
1657       /* add content-length type */
1658       res =
1659           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1660           g_string_free (msglength, FALSE));
1661       if (res != GST_RTSP_OK) {
1662         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1663         goto error;
1664       }
1665
1666       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1667       if (res != GST_RTSP_OK) {
1668         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1669         goto error;
1670       }
1671
1672       g_free (msg);
1673       break;
1674     }
1675
1676       /* Prepare SET_PARAMETER request */
1677     case GST_RTSP_SET_PARAMETER:{
1678       gchar *msg = NULL;
1679       guint msglen = 0;
1680       GString *msglength;
1681
1682       /* add content type */
1683       res =
1684           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1685           "text/parameters");
1686       if (res != GST_RTSP_OK) {
1687         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1688         goto error;
1689       }
1690
1691       _set_wfd_message_body (client, M4_REQ_MSG, &msg, &msglen);
1692       msglength = g_string_new ("");
1693       g_string_append_printf (msglength, "%d", msglen);
1694       GST_DEBUG ("M4 server side message body: %s", msg);
1695
1696       /* add content-length type */
1697       res =
1698           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1699           g_string_free (msglength, FALSE));
1700       if (res != GST_RTSP_OK) {
1701         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1702         goto error;
1703       }
1704
1705       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1706       if (res != GST_RTSP_OK) {
1707         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1708         goto error;
1709       }
1710
1711       g_free (msg);
1712       break;
1713     }
1714
1715     default:{
1716     }
1717   }
1718
1719   return res;
1720
1721 error:
1722   return GST_RTSP_ERROR;
1723 }
1724
1725 GstRTSPResult
1726 prepare_trigger_request (GstRTSPWFDClient * client, GstRTSPMessage * request,
1727     GstWFDTriggerType trigger_type, gchar * url)
1728 {
1729   GstRTSPResult res = GST_RTSP_OK;
1730
1731   /* initialize the request */
1732   res = gst_rtsp_message_init_request (request, GST_RTSP_SET_PARAMETER, url);
1733   if (res < 0) {
1734     GST_ERROR ("init request failed");
1735     return res;
1736   }
1737
1738   switch (trigger_type) {
1739     case WFD_TRIGGER_SETUP:{
1740       gchar *msg;
1741       guint msglen = 0;
1742       GString *msglength;
1743
1744       /* add content type */
1745       res =
1746           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1747           "text/parameters");
1748       if (res != GST_RTSP_OK) {
1749         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1750         goto error;
1751       }
1752
1753       _set_wfd_message_body (client, M5_REQ_MSG, &msg, &msglen);
1754       msglength = g_string_new ("");
1755       g_string_append_printf (msglength, "%d", msglen);
1756       GST_DEBUG ("M5 server side message body: %s", msg);
1757
1758       /* add content-length type */
1759       res =
1760           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1761           g_string_free (msglength, FALSE));
1762       if (res != GST_RTSP_OK) {
1763         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1764         goto error;
1765       }
1766
1767       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1768       if (res != GST_RTSP_OK) {
1769         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1770         goto error;
1771       }
1772
1773       g_free (msg);
1774       break;
1775     }
1776     case WFD_TRIGGER_TEARDOWN:{
1777       gchar *msg;
1778       guint msglen = 0;
1779       GString *msglength;
1780
1781       /* add content type */
1782       res =
1783           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1784           "text/parameters");
1785       if (res != GST_RTSP_OK) {
1786         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1787         goto error;
1788       }
1789
1790       _set_wfd_message_body (client, TEARDOWN_TRIGGER, &msg, &msglen);
1791       msglength = g_string_new ("");
1792       g_string_append_printf (msglength, "%d", msglen);
1793       GST_DEBUG ("Trigger TEARDOWN server side message body: %s", msg);
1794
1795       /* add content-length type */
1796       res =
1797           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1798           g_string_free (msglength, FALSE));
1799       if (res != GST_RTSP_OK) {
1800         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1801         goto error;
1802       }
1803
1804       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1805       if (res != GST_RTSP_OK) {
1806         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1807         goto error;
1808       }
1809
1810       g_free (msg);
1811       break;
1812     }
1813     case WFD_TRIGGER_PLAY:{
1814       gchar *msg;
1815       guint msglen = 0;
1816       GString *msglength;
1817
1818       /* add content type */
1819       res =
1820           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1821           "text/parameters");
1822       if (res != GST_RTSP_OK) {
1823         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1824         goto error;
1825       }
1826
1827       _set_wfd_message_body (client, PLAY_TRIGGER, &msg, &msglen);
1828       msglength = g_string_new ("");
1829       g_string_append_printf (msglength, "%d", msglen);
1830       GST_DEBUG ("Trigger PLAY server side message body: %s", msg);
1831
1832       /* add content-length type */
1833       res =
1834           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1835           g_string_free (msglength, FALSE));
1836       if (res != GST_RTSP_OK) {
1837         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1838         goto error;
1839       }
1840
1841       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1842       if (res != GST_RTSP_OK) {
1843         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1844         goto error;
1845       }
1846
1847       g_free (msg);
1848       break;
1849     }
1850     case WFD_TRIGGER_PAUSE:{
1851       gchar *msg;
1852       guint msglen = 0;
1853       GString *msglength;
1854
1855       /* add content type */
1856       res =
1857           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1858           "text/parameters");
1859       if (res != GST_RTSP_OK) {
1860         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1861         goto error;
1862       }
1863
1864       _set_wfd_message_body (client, PAUSE_TRIGGER, &msg, &msglen);
1865       msglength = g_string_new ("");
1866       g_string_append_printf (msglength, "%d", msglen);
1867       GST_DEBUG ("Trigger PAUSE server side message body: %s", msg);
1868
1869       /* add content-length type */
1870       res =
1871           gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1872           g_string_free (msglength, FALSE));
1873       if (res != GST_RTSP_OK) {
1874         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1875         goto error;
1876       }
1877
1878       res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1879       if (res != GST_RTSP_OK) {
1880         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1881         goto error;
1882       }
1883
1884       g_free (msg);
1885       break;
1886     }
1887       /* TODO-WFD: implement to handle other trigger type */
1888     default:{
1889     }
1890   }
1891
1892   return res;
1893
1894 error:
1895   return res;
1896 }
1897
1898
1899 void
1900 send_request (GstRTSPWFDClient * client, GstRTSPSession * session,
1901     GstRTSPMessage * request)
1902 {
1903   GstRTSPResult res = GST_RTSP_OK;
1904   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1905
1906   /* remove any previous header */
1907   gst_rtsp_message_remove_header (request, GST_RTSP_HDR_SESSION, -1);
1908
1909   /* add the new session header for new session ids */
1910   if (session) {
1911     guint timeout;
1912     const gchar *sessionid = NULL;
1913     gchar *str;
1914
1915     sessionid = gst_rtsp_session_get_sessionid (session);
1916     GST_INFO_OBJECT (client, "Session id : %s", sessionid);
1917
1918     timeout = gst_rtsp_session_get_timeout (session);
1919     if (timeout != DEFAULT_WFD_TIMEOUT)
1920       str = g_strdup_printf ("%s; timeout=%d", sessionid, timeout);
1921     else
1922       str = g_strdup (sessionid);
1923
1924     gst_rtsp_message_take_header (request, GST_RTSP_HDR_SESSION, str);
1925   }
1926 #if 0
1927   if (gst_debug_category_get_threshold (rtsp_wfd_client_debug) >= GST_LEVEL_LOG) {
1928     gst_rtsp_message_dump (request);
1929   }
1930 #endif
1931   res = gst_rtsp_client_send_message (parent_client, session, request);
1932   if (res != GST_RTSP_OK) {
1933     GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
1934   }
1935
1936   gst_rtsp_message_unset (request);
1937 }
1938
1939 /**
1940 * prepare_response:
1941 * @client: client object
1942 * @request : requst message received
1943 * @response : response to be prepare based on request
1944 * @method : RTSP method
1945 *
1946 * prepare response to the request based on @method & @message_type
1947 *
1948 * Returns: a #GstRTSPResult.
1949 */
1950 GstRTSPResult
1951 prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request,
1952     GstRTSPMessage * response, GstRTSPMethod method)
1953 {
1954   GstRTSPResult res = GST_RTSP_OK;
1955
1956   switch (method) {
1957       /* prepare OPTIONS response */
1958     case GST_RTSP_OPTIONS:{
1959       GstRTSPMethod options;
1960       gchar *tmp = NULL;
1961       gchar *str = NULL;
1962       gchar *user_agent = NULL;
1963
1964       options = GST_RTSP_OPTIONS |
1965           GST_RTSP_PAUSE |
1966           GST_RTSP_PLAY |
1967           GST_RTSP_SETUP |
1968           GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
1969
1970       str = gst_rtsp_options_as_text (options);
1971
1972       /*append WFD specific method */
1973       tmp = g_strdup (", org.wfa.wfd1.0");
1974       g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
1975
1976       gst_rtsp_message_init_response (response, GST_RTSP_STS_OK,
1977           gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
1978
1979       gst_rtsp_message_add_header (response, GST_RTSP_HDR_PUBLIC, str);
1980       g_free (str);
1981       str = NULL;
1982       res =
1983           gst_rtsp_message_get_header (request, GST_RTSP_HDR_USER_AGENT,
1984           &user_agent, 0);
1985       if (res == GST_RTSP_OK) {
1986         gst_rtsp_message_add_header (response, GST_RTSP_HDR_USER_AGENT,
1987             user_agent);
1988       } else
1989         res = GST_RTSP_OK;
1990       break;
1991     }
1992     default:
1993       GST_ERROR_OBJECT (client, "Unhandled method...");
1994       return GST_RTSP_EINVAL;
1995       break;
1996   }
1997
1998   return res;
1999 }
2000
2001 static void
2002 send_generic_wfd_response (GstRTSPWFDClient * client, GstRTSPStatusCode code,
2003     GstRTSPContext * ctx)
2004 {
2005   GstRTSPResult res = GST_RTSP_OK;
2006   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2007
2008   gst_rtsp_message_init_response (ctx->response, code,
2009       gst_rtsp_status_as_text (code), ctx->request);
2010
2011   res = gst_rtsp_client_send_message (parent_client, NULL, ctx->response);
2012   if (res != GST_RTSP_OK) {
2013     GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
2014   }
2015 }
2016
2017
2018 static GstRTSPResult
2019 handle_M1_message (GstRTSPWFDClient * client)
2020 {
2021   GstRTSPResult res = GST_RTSP_OK;
2022   GstRTSPMessage request = { 0 };
2023
2024   res = prepare_request (client, &request, GST_RTSP_OPTIONS, (gchar *) "*");
2025   if (GST_RTSP_OK != res) {
2026     GST_ERROR_OBJECT (client, "Failed to prepare M1 request....\n");
2027     return res;
2028   }
2029
2030   GST_DEBUG_OBJECT (client, "Sending M1 request.. (OPTIONS request)");
2031
2032   send_request (client, NULL, &request);
2033
2034   return res;
2035 }
2036
2037 /**
2038 * handle_M3_message:
2039 * @client: client object
2040 *
2041 * Handles M3 WFD message.
2042 * This API will send M3 message (GET_PARAMETER) to WFDSink to query supported formats by the WFDSink.
2043 * After getting supported formats info, this API will set those values on WFDConfigMessage obj
2044 *
2045 * Returns: a #GstRTSPResult.
2046 */
2047 static GstRTSPResult
2048 handle_M3_message (GstRTSPWFDClient * client)
2049 {
2050   GstRTSPResult res = GST_RTSP_OK;
2051   GstRTSPMessage request = { 0 };
2052   GstRTSPUrl *url = NULL;
2053   gchar *url_str = NULL;
2054
2055   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2056   GstRTSPConnection *connection =
2057       gst_rtsp_client_get_connection (parent_client);
2058
2059   url = gst_rtsp_connection_get_url (connection);
2060   if (url == NULL) {
2061     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2062     res = GST_RTSP_ERROR;
2063     goto error;
2064   }
2065
2066   url_str = gst_rtsp_url_get_request_uri (url);
2067   if (url_str == NULL) {
2068     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2069     res = GST_RTSP_ERROR;
2070     goto error;
2071   }
2072
2073   res = prepare_request (client, &request, GST_RTSP_GET_PARAMETER, url_str);
2074   if (GST_RTSP_OK != res) {
2075     GST_ERROR_OBJECT (client, "Failed to prepare M3 request....\n");
2076     goto error;
2077   }
2078
2079   GST_DEBUG_OBJECT (client, "Sending GET_PARAMETER request message (M3)...");
2080
2081   send_request (client, NULL, &request);
2082
2083   return res;
2084
2085 error:
2086   return res;
2087 }
2088
2089 static GstRTSPResult
2090 handle_M4_message (GstRTSPWFDClient * client)
2091 {
2092   GstRTSPResult res = GST_RTSP_OK;
2093   GstRTSPMessage request = { 0 };
2094   GstRTSPUrl *url = NULL;
2095   gchar *url_str = NULL;
2096
2097   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2098   GstRTSPConnection *connection =
2099       gst_rtsp_client_get_connection (parent_client);
2100
2101   url = gst_rtsp_connection_get_url (connection);
2102   if (url == NULL) {
2103     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2104     res = GST_RTSP_ERROR;
2105     goto error;
2106   }
2107
2108   url_str = gst_rtsp_url_get_request_uri (url);
2109   if (url_str == NULL) {
2110     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2111     res = GST_RTSP_ERROR;
2112     goto error;
2113   }
2114
2115   res = prepare_request (client, &request, GST_RTSP_SET_PARAMETER, url_str);
2116   if (GST_RTSP_OK != res) {
2117     GST_ERROR_OBJECT (client, "Failed to prepare M4 request....\n");
2118     goto error;
2119   }
2120
2121   GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message (M4)...");
2122
2123   send_request (client, NULL, &request);
2124
2125   return res;
2126
2127 error:
2128   return res;
2129 }
2130
2131 GstRTSPResult
2132 gst_rtsp_wfd_client_trigger_request (GstRTSPWFDClient * client,
2133     GstWFDTriggerType type)
2134 {
2135   GstRTSPResult res = GST_RTSP_OK;
2136   GstRTSPMessage request = { 0 };
2137   GstRTSPUrl *url = NULL;
2138   gchar *url_str = NULL;
2139
2140   GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
2141   GstRTSPConnection *connection =
2142       gst_rtsp_client_get_connection (parent_client);
2143
2144   url = gst_rtsp_connection_get_url (connection);
2145   if (url == NULL) {
2146     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2147     res = GST_RTSP_ERROR;
2148     goto error;
2149   }
2150
2151   url_str = gst_rtsp_url_get_request_uri (url);
2152   if (url_str == NULL) {
2153     GST_ERROR_OBJECT (client, "Failed to get connection URL");
2154     res = GST_RTSP_ERROR;
2155     goto error;
2156   }
2157
2158   res = prepare_trigger_request (client, &request, type, url_str);
2159   if (GST_RTSP_OK != res) {
2160     GST_ERROR_OBJECT (client, "Failed to prepare M5 request....\n");
2161     goto error;
2162   }
2163
2164   GST_DEBUG_OBJECT (client, "Sending trigger request message...: %d", type);
2165
2166   send_request (client, NULL, &request);
2167
2168   return res;
2169
2170 error:
2171   return res;
2172 }
2173
2174 GstRTSPResult
2175 gst_rtsp_wfd_client_set_video_supported_resolution (GstRTSPWFDClient * client,
2176     guint64 supported_reso)
2177 {
2178   GstRTSPResult res = GST_RTSP_OK;
2179   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2180
2181   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2182
2183   priv->video_resolution_supported = supported_reso;
2184   GST_DEBUG ("Resolution : %"G_GUINT64_FORMAT, supported_reso);
2185
2186   return res;
2187 }
2188
2189 GstRTSPResult
2190 gst_rtsp_wfd_client_set_video_native_resolution (GstRTSPWFDClient * client,
2191     guint64 native_reso)
2192 {
2193   GstRTSPResult res = GST_RTSP_OK;
2194   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2195
2196   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2197
2198   priv->video_native_resolution = native_reso;
2199   GST_DEBUG ("Native Resolution : %"G_GUINT64_FORMAT, native_reso);
2200
2201   return res;
2202 }
2203
2204 GstRTSPResult
2205 gst_rtsp_wfd_client_set_audio_codec (GstRTSPWFDClient * client,
2206     guint8 audio_codec)
2207 {
2208   GstRTSPResult res = GST_RTSP_OK;
2209   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2210
2211   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2212
2213   priv->audio_codec = audio_codec;
2214   GST_DEBUG ("Audio codec : %d", audio_codec);
2215
2216   return res;
2217 }
2218
2219 static gboolean
2220 wfd_ckeck_keep_alive_response (gpointer userdata)
2221 {
2222   GstRTSPWFDClient *client = (GstRTSPWFDClient *)userdata;
2223   GstRTSPWFDClientPrivate *priv = NULL;
2224   if (!client) {
2225     return FALSE;
2226   }
2227
2228   priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2229   g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL);
2230
2231   if (priv->keep_alive_flag) {
2232     return FALSE;
2233   }
2234   else {
2235     GST_INFO ("%p: source error notification", client);
2236     // FIXME Do something here. Maybe emit some signal?
2237     return FALSE;
2238   }
2239 }
2240
2241 /*Sending keep_alive (M16) message.
2242   Without calling prepare_request function.*/
2243 static GstRTSPResult
2244 handle_M16_message (GstRTSPWFDClient * client)
2245 {
2246   GstRTSPResult res = GST_RTSP_OK;
2247   GstRTSPMessage request = { 0 };
2248   gchar *url_str = NULL;
2249
2250   url_str = g_strdup("rtsp://localhost/wfd1.0");
2251
2252   res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str);
2253   if (res < 0) {
2254     GST_ERROR ("init request failed");
2255     return FALSE;
2256   }
2257
2258   send_request (client, NULL, &request);
2259   return GST_RTSP_OK;
2260 }
2261
2262 /*CHecking whether source has got response of any request.
2263  * If yes, keep alive message is sent otherwise error message
2264  * will be displayed.*/
2265 static gboolean
2266 keep_alive_condition(gpointer userdata)
2267 {
2268   GstRTSPWFDClient *client;
2269   GstRTSPWFDClientPrivate *priv;
2270   GstRTSPResult res;
2271   client = (GstRTSPWFDClient *)userdata;
2272   if (!client) {
2273     return FALSE;
2274   }
2275   priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2276
2277   g_return_val_if_fail (priv != NULL, FALSE);
2278
2279   g_mutex_lock(&priv->keep_alive_lock);
2280   if(!priv->keep_alive_flag) {
2281     g_timeout_add(5000, wfd_ckeck_keep_alive_response, client);
2282   }
2283   else {
2284     GST_DEBUG_OBJECT (client, "have received last keep alive message response");
2285   }
2286
2287   GST_DEBUG("sending keep alive message");
2288   res = handle_M16_message(client);
2289   if(res == GST_RTSP_OK) {
2290     priv->keep_alive_flag = FALSE;
2291   } else {
2292     GST_ERROR_OBJECT (client, "Failed to send Keep Alive Message");
2293     g_mutex_unlock(&priv->keep_alive_lock);
2294     return FALSE;
2295   }
2296
2297   g_mutex_unlock(&priv->keep_alive_lock);
2298   return TRUE;
2299 }
2300
2301 static
2302 void wfd_set_keep_alive_condition(GstRTSPClient * client)
2303 {
2304   GstRTSPWFDClient *wfd_client;
2305   wfd_client = GST_RTSP_WFD_CLIENT(client);
2306
2307   g_timeout_add((DEFAULT_WFD_TIMEOUT-5)*1000, keep_alive_condition, wfd_client);
2308 }
2309
2310 void
2311 gst_rtsp_wfd_client_set_host_address (GstRTSPWFDClient *client, const gchar * address)
2312 {
2313   GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2314
2315   g_return_if_fail (priv != NULL);
2316
2317   if (priv->host_address) {
2318     g_free (priv->host_address);
2319   }
2320
2321   priv->host_address = g_strdup (address);
2322 }