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