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