Add AL-FEC feature
[platform/upstream/gst-rtsp-server.git] / gst / rtsp-server / gstwfdmessage.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  * Unless otherwise indicated, Source Code is licensed under MIT license.
21  * See further explanation attached in License Statement (distributed in the file
22  * LICENSE).
23  *
24  * Permission is hereby granted, free of charge, to any person obtaining a copy of
25  * this software and associated documentation files (the "Software"), to deal in
26  * the Software without restriction, including without limitation the rights to
27  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
28  * of the Software, and to permit persons to whom the Software is furnished to do
29  * so, subject to the following conditions:
30  *
31  * The above copyright notice and this permission notice shall be included in all
32  * copies or substantial portions of the Software.
33  *
34  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40  * SOFTWARE.
41  */
42
43 /**
44  * SECTION:gstwfdmessage
45  * @short_description: Helper methods for dealing with WFD messages
46  *
47  * <refsect2>
48  * <para>
49  * The GstWFDMessage helper functions makes it easy to parse and create WFD
50  * messages.
51  * </para>
52  * </refsect2>
53  */
54
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62
63 #include <gio/gio.h>
64
65 #include "gstwfdmessage.h"
66
67 #define EDID_BLOCK_SIZE 128
68 #define EDID_BLOCK_COUNT_MAX_SIZE 256
69 #define MAX_PORT_SIZE 65535
70
71 #define FREE_STRING(field)              g_free (field); (field) = NULL
72 #define REPLACE_STRING(field, val)      FREE_STRING(field); (field) = g_strdup (val)
73
74 #define INIT_ARRAY(field, type, init_func)              \
75 G_STMT_START {                                          \
76   if (field) {                                          \
77     guint i;                                            \
78     for(i = 0; i < (field)->len; i++)                   \
79       init_func (&g_array_index ((field), type, i));    \
80     g_array_set_size ((field), 0);                      \
81   }                                                     \
82   else                                                  \
83     (field) = g_array_new (FALSE, TRUE, sizeof (type)); \
84 } G_STMT_END
85
86 #define FREE_ARRAY(field)         \
87 G_STMT_START {                    \
88   if (field)                      \
89     g_array_free ((field), TRUE); \
90   (field) = NULL;                 \
91 } G_STMT_END
92
93 #define DEFINE_STRING_SETTER(field)                                     \
94 GstWFDResult gst_wfd_message_set_##field (GstWFDMessage *msg, const gchar *val) { \
95   g_free (msg->field);                                                  \
96   msg->field = g_strdup (val);                                          \
97   return GST_WFD_OK;                                                    \
98 }
99 #define DEFINE_STRING_GETTER(field)                                     \
100 const gchar* gst_wfd_message_get_##field (const GstWFDMessage *msg) {   \
101   return msg->field;                                                    \
102 }
103
104 #define DEFINE_ARRAY_LEN(field)                                         \
105 guint gst_wfd_message_##field##_len (const GstWFDMessage *msg) {        \
106   return msg->field->len;                                               \
107 }
108 #define DEFINE_ARRAY_GETTER(method, field, type)                        \
109 const type * gst_wfd_message_get_##method (const GstWFDMessage *msg, guint idx) {  \
110   return &g_array_index (msg->field, type, idx);                        \
111 }
112 #define DEFINE_PTR_ARRAY_GETTER(method, field, type)                    \
113 const type gst_wfd_message_get_##method (const GstWFDMessage *msg, guint idx) {    \
114   return g_array_index (msg->field, type, idx);                         \
115 }
116 #define DEFINE_ARRAY_INSERT(method, field, intype, dup_method, type)         \
117 GstWFDResult gst_wfd_message_insert_##method (GstWFDMessage *msg, gint idx, intype val) {   \
118   type vt;                                                              \
119   type* v = &vt;                                                         \
120   dup_method (v, val);                                                  \
121   if (idx == -1)                                                        \
122     g_array_append_val (msg->field, vt);                                \
123   else                                                                  \
124     g_array_insert_val (msg->field, idx, vt);                           \
125   return GST_WFD_OK;                                                    \
126 }
127
128 #define DEFINE_ARRAY_REPLACE(method, field, intype, free_method, dup_method, type)         \
129 GstWFDResult gst_wfd_message_replace_##method (GstWFDMessage *msg, guint idx, intype val) {   \
130   type *v = &g_array_index (msg->field, type, idx);                   \
131   free_method (v);                                                    \
132   dup_method (v, val);                                                  \
133   return GST_WFD_OK;                                                    \
134 }
135 #define DEFINE_ARRAY_REMOVE(method, field, type, free_method)                        \
136 GstWFDResult gst_wfd_message_remove_##method (GstWFDMessage *msg, guint idx) {  \
137   type *v = &g_array_index (msg->field, type, idx);                     \
138   free_method (v);                                                      \
139   g_array_remove_index (msg->field, idx);                               \
140   return GST_WFD_OK;                                                    \
141 }
142 #define DEFINE_ARRAY_ADDER(method, type)                                \
143 GstWFDResult gst_wfd_message_add_##method (GstWFDMessage *msg, const type val) {   \
144   return gst_wfd_message_insert_##method (msg, -1, val);                \
145 }
146
147 #define dup_string(v,val) ((*v) = g_strdup (val))
148 #define INIT_STR_ARRAY(field) \
149     INIT_ARRAY (field, gchar *, free_string)
150 #define DEFINE_STR_ARRAY_GETTER(method, field) \
151     DEFINE_PTR_ARRAY_GETTER(method, field, gchar *)
152 #define DEFINE_STR_ARRAY_INSERT(method, field) \
153     DEFINE_ARRAY_INSERT (method, field, const gchar *, dup_string, gchar *)
154 #define DEFINE_STR_ARRAY_ADDER(method, field) \
155     DEFINE_ARRAY_ADDER (method, gchar *)
156 #define DEFINE_STR_ARRAY_REPLACE(method, field) \
157     DEFINE_ARRAY_REPLACE (method, field, const gchar *, free_string, dup_string, gchar *)
158 #define DEFINE_STR_ARRAY_REMOVE(method, field) \
159     DEFINE_ARRAY_REMOVE (method, field, gchar *, free_string)
160
161 static GstWFDMessage *gst_wfd_message_boxed_copy (GstWFDMessage * orig);
162 static void gst_wfd_message_boxed_free (GstWFDMessage * msg);
163
164 G_DEFINE_BOXED_TYPE (GstWFDMessage, gst_wfd_message, gst_wfd_message_boxed_copy,
165     gst_wfd_message_boxed_free);
166
167 static GstWFDMessage *
168 gst_wfd_message_boxed_copy (GstWFDMessage * orig)
169 {
170   GstWFDMessage *copy;
171
172   if (gst_wfd_message_copy (orig, &copy) == GST_WFD_OK)
173     return copy;
174
175   return NULL;
176 }
177
178 static void
179 gst_wfd_message_boxed_free (GstWFDMessage * msg)
180 {
181   gst_wfd_message_free (msg);
182 }
183
184 /**
185  * gst_wfd_message_new:
186  * @msg: (out) (transfer full): pointer to new #GstWFDMessage
187  *
188  * Allocate a new GstWFDMessage and store the result in @msg.
189  *
190  * Returns: a #GstWFDResult.
191  */
192 GstWFDResult
193 gst_wfd_message_new (GstWFDMessage ** msg)
194 {
195   GstWFDMessage *newmsg;
196
197   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
198
199   newmsg = g_new0 (GstWFDMessage, 1);
200
201   *msg = newmsg;
202
203   return gst_wfd_message_init (newmsg);
204 }
205
206 /**
207  * gst_wfd_message_init:
208  * @msg: a #GstWFDMessage
209  *
210  * Initialize @msg so that its contents are as if it was freshly allocated
211  * with gst_wfd_message_new(). This function is mostly used to initialize a message
212  * allocated on the stack. gst_wfd_message_uninit() undoes this operation.
213  *
214  * When this function is invoked on newly allocated data (with malloc or on the
215  * stack), its contents should be set to 0 before calling this function.
216  *
217  * Returns: a #GstWFDResult.
218  */
219 GstWFDResult
220 gst_wfd_message_init (GstWFDMessage * msg)
221 {
222   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
223
224   return GST_WFD_OK;
225 }
226
227 /**
228  * gst_wfd_message_uninit:
229  * @msg: a #GstWFDMessage
230  *
231  * Free all resources allocated in @msg. @msg should not be used anymore after
232  * this function. This function should be used when @msg was allocated on the
233  * stack and initialized with gst_wfd_message_init().
234  *
235  * Returns: a #GstWFDResult.
236  */
237 GstWFDResult
238 gst_wfd_message_uninit (GstWFDMessage * msg)
239 {
240   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
241
242   if (msg->audio_codecs) {
243     guint i = 0;
244     if (msg->audio_codecs->list) {
245       for (; i < msg->audio_codecs->count; i++) {
246         FREE_STRING (msg->audio_codecs->list[i].audio_format);
247         msg->audio_codecs->list[i].modes = 0;
248         msg->audio_codecs->list[i].latency = 0;
249       }
250       FREE_STRING (msg->audio_codecs->list);
251     }
252     FREE_STRING (msg->audio_codecs);
253   }
254
255   if (msg->video_formats) {
256     FREE_STRING (msg->video_formats->list);
257     FREE_STRING (msg->video_formats);
258   }
259
260   if (msg->video_3d_formats) {
261     FREE_STRING (msg->video_3d_formats->list);
262     FREE_STRING (msg->video_3d_formats);
263   }
264
265   if (msg->content_protection) {
266     if (msg->content_protection->hdcp2_spec) {
267       FREE_STRING (msg->content_protection->hdcp2_spec->hdcpversion);
268       FREE_STRING (msg->content_protection->hdcp2_spec->TCPPort);
269       FREE_STRING (msg->content_protection->hdcp2_spec);
270     }
271     FREE_STRING (msg->content_protection);
272   }
273
274   if (msg->display_edid) {
275     if (msg->display_edid->edid_payload)
276       FREE_STRING (msg->display_edid->edid_payload);
277     FREE_STRING (msg->display_edid);
278   }
279
280   if (msg->coupled_sink) {
281     if (msg->coupled_sink->coupled_sink_cap) {
282       FREE_STRING (msg->coupled_sink->coupled_sink_cap->sink_address);
283       FREE_STRING (msg->coupled_sink->coupled_sink_cap);
284     }
285     FREE_STRING (msg->coupled_sink);
286   }
287
288   if (msg->trigger_method) {
289     FREE_STRING (msg->trigger_method->wfd_trigger_method);
290     FREE_STRING (msg->trigger_method);
291   }
292
293   if (msg->presentation_url) {
294     FREE_STRING (msg->presentation_url->wfd_url0);
295     FREE_STRING (msg->presentation_url->wfd_url1);
296     FREE_STRING (msg->presentation_url);
297   }
298
299   if (msg->client_rtp_ports) {
300     FREE_STRING (msg->client_rtp_ports->profile);
301     FREE_STRING (msg->client_rtp_ports->mode);
302     FREE_STRING (msg->client_rtp_ports);
303   }
304
305   if (msg->route) {
306     FREE_STRING (msg->route->destination);
307     FREE_STRING (msg->route);
308   }
309
310   if (msg->I2C) {
311     FREE_STRING (msg->I2C);
312   }
313
314   if (msg->av_format_change_timing) {
315     FREE_STRING (msg->av_format_change_timing);
316   }
317
318   if (msg->preferred_display_mode) {
319     FREE_STRING (msg->preferred_display_mode);
320   }
321
322   if (msg->standby_resume_capability) {
323     FREE_STRING (msg->standby_resume_capability);
324   }
325
326   if (msg->standby) {
327     FREE_STRING (msg->standby);
328   }
329
330   if (msg->connector_type) {
331     FREE_STRING (msg->connector_type);
332   }
333
334   if (msg->idr_request) {
335     FREE_STRING (msg->idr_request);
336   }
337
338   return GST_WFD_OK;
339 }
340
341 /**
342  * gst_wfd_message_copy:
343  * @msg: a #GstWFDMessage
344  * @copy: (out) (transfer full): pointer to new #GstWFDMessage
345  *
346  * Allocate a new copy of @msg and store the result in @copy. The value in
347  * @copy should be release with gst_wfd_message_free function.
348  *
349  * Returns: a #GstWFDResult
350  *
351  * Since: 1.6
352  */
353 GstWFDResult
354 gst_wfd_message_copy (const GstWFDMessage * msg, GstWFDMessage ** copy)
355 {
356   GstWFDResult ret;
357   GstWFDMessage *cp;
358
359   if (msg == NULL)
360     return GST_WFD_EINVAL;
361
362   ret = gst_wfd_message_new (copy);
363   if (ret != GST_WFD_OK)
364     return ret;
365
366   cp = *copy;
367
368   /* TODO-WFD */
369   if (msg->client_rtp_ports) {
370     cp->client_rtp_ports = g_malloc (sizeof (GstWFDClientRtpPorts));
371     if (cp->client_rtp_ports) {
372       cp->client_rtp_ports->profile = g_strdup (msg->client_rtp_ports->profile);
373       cp->client_rtp_ports->rtp_port0 = msg->client_rtp_ports->rtp_port0;
374       cp->client_rtp_ports->rtp_port1 = msg->client_rtp_ports->rtp_port1;
375       cp->client_rtp_ports->mode = g_strdup (msg->client_rtp_ports->mode);
376     }
377   }
378
379   return GST_WFD_OK;
380 }
381
382
383 static void
384 _read_string_space_ended (gchar * dest, guint size, gchar * src)
385 {
386   guint idx = 0;
387
388   while (!g_ascii_isspace (*src) && *src != '\0') {
389     if (idx < size - 1)
390       dest[idx++] = *src;
391     src++;
392   }
393
394   if (size > 0)
395     dest[idx] = '\0';
396
397   return;
398 }
399
400 static void
401 _read_string_attr_and_value (gchar * attr, gchar * value, guint tsize,
402     guint vsize, gchar del, gchar * src)
403 {
404   guint idx;
405
406   idx = 0;
407
408   while (*src != del && *src != '\0') {
409     if (idx < tsize - 1)
410       attr[idx++] = *src;
411     src++;
412   }
413
414   if (tsize > 0)
415     attr[idx] = '\0';
416
417   src++;
418   idx = 0;
419
420   while (*src != '\0') {
421     if (idx < vsize - 1)
422       value[idx++] = *src;
423     src++;
424   }
425
426   if (vsize > 0)
427     value[idx] = '\0';
428
429   return;
430 }
431
432 static void
433 gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg)
434 {
435   gchar attr[8192] = { 0 };
436   gchar value[8192] = { 0 };
437   gchar temp[8192] = { 0 };
438   gchar *p = buffer;
439   gchar *v = value;
440
441 #define WFD_SKIP_SPACE(q) if (*q && g_ascii_isspace (*q)) q++
442 #define WFD_SKIP_EQUAL(q) if (*q && *q == '=') q++
443 #define WFD_SKIP_COMMA(q) if (*q && g_ascii_ispunct (*q)) q++
444 #define WFD_READ_STRING(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); REPLACE_STRING (field, temp)
445 #define WFD_READ_UINT32(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 16)
446 #define WFD_READ_UINT32_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 10)
447
448   _read_string_attr_and_value (attr, value, sizeof (attr), sizeof (value), ':',
449       p);
450
451   if (!g_strcmp0 (attr, GST_STRING_WFD_AUDIO_CODECS)) {
452     msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1);
453     if (strlen (v)) {
454       guint i = 0;
455       msg->audio_codecs->count = strlen (v) / 16;
456       msg->audio_codecs->list =
457           g_new0 (GstWFDAudioCodec, msg->audio_codecs->count);
458       for (; i < msg->audio_codecs->count; i++) {
459         WFD_SKIP_SPACE (v);
460         WFD_READ_STRING (msg->audio_codecs->list[i].audio_format);
461         WFD_SKIP_SPACE (v);
462         WFD_READ_UINT32 (msg->audio_codecs->list[i].modes);
463         WFD_SKIP_SPACE (v);
464         WFD_READ_UINT32 (msg->audio_codecs->list[i].latency);
465         WFD_SKIP_COMMA (v);
466       }
467     }
468   } else if (!g_strcmp0 (attr, GST_STRING_WFD_VIDEO_FORMATS)) {
469     msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1);
470     if (strlen (v)) {
471       msg->video_formats->count = 1;
472       msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1);
473       WFD_SKIP_SPACE (v);
474       WFD_READ_UINT32 (msg->video_formats->list->native);
475       WFD_SKIP_SPACE (v);
476       WFD_READ_UINT32 (msg->video_formats->list->
477           preferred_display_mode_supported);
478       WFD_SKIP_SPACE (v);
479       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.profile);
480       WFD_SKIP_SPACE (v);
481       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.level);
482       WFD_SKIP_SPACE (v);
483       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params.
484           CEA_Support);
485       WFD_SKIP_SPACE (v);
486       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params.
487           VESA_Support);
488       WFD_SKIP_SPACE (v);
489       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params.
490           HH_Support);
491       WFD_SKIP_SPACE (v);
492       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params.
493           latency);
494       WFD_SKIP_SPACE (v);
495       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params.
496           min_slice_size);
497       WFD_SKIP_SPACE (v);
498       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params.
499           slice_enc_params);
500       WFD_SKIP_SPACE (v);
501       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params.
502           frame_rate_control_support);
503       WFD_SKIP_SPACE (v);
504       if (msg->video_formats->list->preferred_display_mode_supported == 1) {
505         WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres);
506         WFD_SKIP_SPACE (v);
507         WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_vres);
508         WFD_SKIP_SPACE (v);
509       }
510     }
511   } else if (!g_strcmp0 (attr, GST_STRING_WFD_3D_VIDEO_FORMATS)) {
512     msg->video_3d_formats = g_new0 (GstWFD3DFormats, 1);
513     if (strlen (v)) {
514       msg->video_3d_formats->count = 1;
515       msg->video_3d_formats->list = g_new0 (GstWFD3dCapList, 1);
516       WFD_SKIP_SPACE (v);
517       WFD_READ_UINT32 (msg->video_3d_formats->list->native);
518       WFD_SKIP_SPACE (v);
519       WFD_READ_UINT32 (msg->video_3d_formats->list->
520           preferred_display_mode_supported);
521       WFD_SKIP_SPACE (v);
522       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.profile);
523       WFD_SKIP_SPACE (v);
524       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.level);
525       WFD_SKIP_SPACE (v);
526       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params.
527           video_3d_capability);
528       WFD_SKIP_SPACE (v);
529       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params.
530           latency);
531       WFD_SKIP_SPACE (v);
532       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params.
533           min_slice_size);
534       WFD_SKIP_SPACE (v);
535       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params.
536           slice_enc_params);
537       WFD_SKIP_SPACE (v);
538       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params.
539           frame_rate_control_support);
540       WFD_SKIP_SPACE (v);
541       if (msg->video_formats->list->preferred_display_mode_supported == 1) {
542         WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres);
543         WFD_SKIP_SPACE (v);
544         WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_vres);
545         WFD_SKIP_SPACE (v);
546       }
547     }
548   } else if (!g_strcmp0 (attr, GST_STRING_WFD_CONTENT_PROTECTION)) {
549     msg->content_protection = g_new0 (GstWFDContentProtection, 1);
550     if (strlen (v)) {
551       WFD_SKIP_SPACE (v);
552       msg->content_protection->hdcp2_spec = g_new0 (GstWFDHdcp2Spec, 1);
553       if (strstr (v, "none")) {
554         msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("none");
555       } else {
556         WFD_READ_STRING (msg->content_protection->hdcp2_spec->hdcpversion);
557         WFD_SKIP_SPACE (v);
558         WFD_READ_STRING (msg->content_protection->hdcp2_spec->TCPPort);
559       }
560     }
561   } else if (!g_strcmp0 (attr, GST_STRING_WFD_DISPLAY_EDID)) {
562     msg->display_edid = g_new0 (GstWFDDisplayEdid, 1);
563     if (strlen (v)) {
564       WFD_SKIP_SPACE (v);
565       if (strstr (v, "none")) {
566         msg->display_edid->edid_supported = 0;
567       } else {
568         msg->display_edid->edid_supported = 1;
569         WFD_READ_UINT32 (msg->display_edid->edid_block_count);
570         WFD_SKIP_SPACE (v);
571         if (msg->display_edid->edid_block_count) {
572           gchar *edid_string = v;
573           int i = 0, j = 0;
574           guint32 payload_size =
575               EDID_BLOCK_SIZE * msg->display_edid->edid_block_count;
576           msg->display_edid->edid_payload = g_malloc (payload_size);
577           for (;
578               i < (EDID_BLOCK_SIZE * msg->display_edid->edid_block_count * 2);
579               j++) {
580             int k = 0, kk = 0;
581             if (edid_string[i] > 0x29 && edid_string[i] < 0x40)
582               k = edid_string[i] - 48;
583             else if (edid_string[i] > 0x60 && edid_string[i] < 0x67)
584               k = edid_string[i] - 87;
585             else if (edid_string[i] > 0x40 && edid_string[i] < 0x47)
586               k = edid_string[i] - 55;
587
588             if (edid_string[i + 1] > 0x29 && edid_string[i + 1] < 0x40)
589               kk = edid_string[i + 1] - 48;
590             else if (edid_string[i + 1] > 0x60 && edid_string[i + 1] < 0x67)
591               kk = edid_string[i + 1] - 87;
592             else if (edid_string[i + 1] > 0x40 && edid_string[i + 1] < 0x47)
593               kk = edid_string[i + 1] - 55;
594
595             msg->display_edid->edid_payload[j] = (k << 4) | kk;
596             i += 2;
597           }
598           //memcpy(msg->display_edid->edid_payload, v, payload_size);
599           v += (payload_size * 2);
600         } else
601           v += strlen (v);
602       }
603     }
604   } else if (!g_strcmp0 (attr, GST_STRING_WFD_COUPLED_SINK)) {
605     msg->coupled_sink = g_new0 (GstWFDCoupledSink, 1);
606     if (strlen (v)) {
607       msg->coupled_sink->coupled_sink_cap = g_new0 (GstWFDCoupled_sink_cap, 1);
608       WFD_SKIP_SPACE (v);
609       WFD_READ_UINT32 (msg->coupled_sink->coupled_sink_cap->status);
610       WFD_SKIP_SPACE (v);
611       WFD_READ_STRING (msg->coupled_sink->coupled_sink_cap->sink_address);
612     }
613   } else if (!g_strcmp0 (attr, GST_STRING_WFD_TRIGGER_METHOD)) {
614     msg->trigger_method = g_new0 (GstWFDTriggerMethod, 1);
615     if (strlen (v)) {
616       WFD_SKIP_SPACE (v);
617       WFD_READ_STRING (msg->trigger_method->wfd_trigger_method);
618     }
619   } else if (!g_strcmp0 (attr, GST_STRING_WFD_PRESENTATION_URL)) {
620     msg->presentation_url = g_new0 (GstWFDPresentationUrl, 1);
621     if (strlen (v)) {
622       WFD_SKIP_SPACE (v);
623       WFD_READ_STRING (msg->presentation_url->wfd_url0);
624       WFD_SKIP_SPACE (v);
625       WFD_READ_STRING (msg->presentation_url->wfd_url1);
626     }
627   } else if (!g_strcmp0 (attr, GST_STRING_WFD_CLIENT_RTP_PORTS)) {
628     msg->client_rtp_ports = g_new0 (GstWFDClientRtpPorts, 1);
629     if (strlen (v)) {
630       WFD_SKIP_SPACE (v);
631       WFD_READ_STRING (msg->client_rtp_ports->profile);
632       WFD_SKIP_SPACE (v);
633       WFD_READ_UINT32_DIGIT (msg->client_rtp_ports->rtp_port0);
634       WFD_SKIP_SPACE (v);
635       WFD_READ_UINT32_DIGIT (msg->client_rtp_ports->rtp_port1);
636       WFD_SKIP_SPACE (v);
637       WFD_READ_STRING (msg->client_rtp_ports->mode);
638     }
639   } else if (!g_strcmp0 (attr, GST_STRING_WFD_ROUTE)) {
640     msg->route = g_new0 (GstWFDRoute, 1);
641     if (strlen (v)) {
642       WFD_SKIP_SPACE (v);
643       WFD_READ_STRING (msg->route->destination);
644     }
645   } else if (!g_strcmp0 (attr, GST_STRING_WFD_I2C)) {
646     msg->I2C = g_new0 (GstWFDI2C, 1);
647     if (strlen (v)) {
648       msg->I2C->I2CPresent = TRUE;
649       WFD_SKIP_SPACE (v);
650       WFD_READ_UINT32_DIGIT (msg->I2C->I2C_port);
651       if (msg->I2C->I2C_port)
652         msg->I2C->I2CPresent = TRUE;
653     }
654   } else if (!g_strcmp0 (attr, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING)) {
655     msg->av_format_change_timing = g_new0 (GstWFDAVFormatChangeTiming, 1);
656     if (strlen (v)) {
657       WFD_SKIP_SPACE (v);
658       WFD_READ_UINT32 (msg->av_format_change_timing->PTS);
659       WFD_SKIP_SPACE (v);
660       WFD_READ_UINT32 (msg->av_format_change_timing->DTS);
661     }
662   } else if (!g_strcmp0 (attr, GST_STRING_WFD_PREFERRED_DISPLAY_MODE)) {
663     msg->preferred_display_mode = g_new0 (GstWFDPreferredDisplayMode, 1);
664     if (strlen (v)) {
665       WFD_SKIP_SPACE (v);
666       if (!strstr (v, "none")) {
667         msg->preferred_display_mode->displaymodesupported = FALSE;
668       } else {
669         WFD_READ_UINT32 (msg->preferred_display_mode->p_clock);
670         WFD_SKIP_SPACE (v);
671         WFD_READ_UINT32 (msg->preferred_display_mode->H);
672         WFD_SKIP_SPACE (v);
673         WFD_READ_UINT32 (msg->preferred_display_mode->HB);
674         WFD_SKIP_SPACE (v);
675         WFD_READ_UINT32 (msg->preferred_display_mode->HSPOL_HSOFF);
676         WFD_SKIP_SPACE (v);
677         WFD_READ_UINT32 (msg->preferred_display_mode->HSW);
678         WFD_SKIP_SPACE (v);
679         WFD_READ_UINT32 (msg->preferred_display_mode->V);
680         WFD_SKIP_SPACE (v);
681         WFD_READ_UINT32 (msg->preferred_display_mode->VB);
682         WFD_SKIP_SPACE (v);
683         WFD_READ_UINT32 (msg->preferred_display_mode->VSPOL_VSOFF);
684         WFD_SKIP_SPACE (v);
685         WFD_READ_UINT32 (msg->preferred_display_mode->VSW);
686         WFD_SKIP_SPACE (v);
687         WFD_READ_UINT32 (msg->preferred_display_mode->VBS3D);
688         WFD_SKIP_SPACE (v);
689         WFD_READ_UINT32 (msg->preferred_display_mode->V2d_s3d_modes);
690         WFD_SKIP_SPACE (v);
691         WFD_READ_UINT32 (msg->preferred_display_mode->P_depth);
692         WFD_SKIP_SPACE (v);
693         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.profile);
694         WFD_SKIP_SPACE (v);
695         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.level);
696         WFD_SKIP_SPACE (v);
697         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params.
698             CEA_Support);
699         WFD_SKIP_SPACE (v);
700         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params.
701             VESA_Support);
702         WFD_SKIP_SPACE (v);
703         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params.
704             HH_Support);
705         WFD_SKIP_SPACE (v);
706         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params.
707             latency);
708         WFD_SKIP_SPACE (v);
709         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params.
710             min_slice_size);
711         WFD_SKIP_SPACE (v);
712         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params.
713             slice_enc_params);
714         WFD_SKIP_SPACE (v);
715         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params.
716             frame_rate_control_support);
717         WFD_SKIP_SPACE (v);
718         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.max_hres);
719         WFD_SKIP_SPACE (v);
720         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.max_vres);
721         WFD_SKIP_SPACE (v);
722       }
723     }
724   } else if (!g_strcmp0 (attr, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY)) {
725     msg->standby_resume_capability = g_new0 (GstWFDStandbyResumeCapability, 1);
726     if (strlen (v)) {
727       WFD_SKIP_SPACE (v);
728       if (!g_strcmp0 (v, "supported"))
729         msg->standby_resume_capability->standby_resume_cap = TRUE;
730       else
731         msg->standby_resume_capability->standby_resume_cap = FALSE;
732     }
733   } else if (!g_strcmp0 (attr, GST_STRING_WFD_STANDBY)) {
734     msg->standby = g_new0 (GstWFDStandby, 1);
735     msg->standby->wfd_standby = TRUE;
736   } else if (!g_strcmp0 (attr, GST_STRING_WFD_CONNECTOR_TYPE)) {
737     msg->connector_type = g_new0 (GstWFDConnectorType, 1);
738     if (strlen (v)) {
739       msg->connector_type->supported = TRUE;
740       WFD_SKIP_SPACE (v);
741       WFD_READ_UINT32 (msg->connector_type->connector_type);
742     }
743   } else if (!g_strcmp0 (attr, GST_STRING_WFD_IDR_REQUEST)) {
744     msg->idr_request = g_new0 (GstWFDIdrRequest, 1);
745     msg->idr_request->idr_request = TRUE;
746   }
747   return;
748 }
749
750 /**
751  * gst_wfd_message_parse_buffer:
752  * @data: the start of the buffer
753  * @size: the size of the buffer
754  * @msg: the result #GstSDPMessage
755  *
756  * Parse the contents of @size bytes pointed to by @data and store the result in
757  * @msg.
758  *
759  * Returns: #GST_SDP_OK on success.
760  */
761 GstWFDResult
762 gst_wfd_message_parse_buffer (const guint8 * data, guint size,
763     GstWFDMessage * msg)
764 {
765   gchar *p;
766   gchar buffer[255] = { 0 };
767   guint idx = 0;
768
769   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
770   g_return_val_if_fail (data != NULL, GST_WFD_EINVAL);
771   g_return_val_if_fail (size != 0, GST_WFD_EINVAL);
772
773   p = (gchar *) data;
774   while (TRUE) {
775
776     if (*p == '\0')
777       break;
778
779     idx = 0;
780     while (*p != '\n' && *p != '\r' && *p != '\0') {
781       if (idx < sizeof (buffer) - 1)
782         buffer[idx++] = *p;
783       p++;
784     }
785     buffer[idx] = '\0';
786     gst_wfd_parse_attribute (buffer, msg);
787
788     if (*p == '\0')
789       break;
790     p += 2;
791   }
792   return GST_WFD_OK;
793 }
794
795 /**
796  * gst_wfd_message_free:
797  * @msg: a #GstWFDMessage
798  *
799  * Free all resources allocated by @msg. @msg should not be used anymore after
800  * this function. This function should be used when @msg was dynamically
801  * allocated with gst_wfd_message_new().
802  *
803  * Returns: a #GstWFDResult.
804  */
805 GstWFDResult
806 gst_wfd_message_free (GstWFDMessage * msg)
807 {
808   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
809
810   gst_wfd_message_uninit (msg);
811   g_free (msg);
812
813   return GST_WFD_OK;
814 }
815
816 /**
817  * gst_wfd_message_as_text:
818  * @msg: a #GstWFDMessage
819  *
820  * Convert the contents of @msg to a text string.
821  *
822  * Returns: A dynamically allocated string representing the WFD description.
823  */
824 gchar *
825 gst_wfd_message_as_text (const GstWFDMessage * msg)
826 {
827   /* change all vars so they match rfc? */
828   GString *lines;
829   guint i;
830
831   g_return_val_if_fail (msg != NULL, NULL);
832
833   lines = g_string_new ("");
834
835   /* list of audio codecs */
836   if (msg->audio_codecs) {
837     g_string_append_printf (lines, GST_STRING_WFD_AUDIO_CODECS);
838     if (msg->audio_codecs->list) {
839       g_string_append_printf (lines, ":");
840       for (i = 0; i < msg->audio_codecs->count; i++) {
841         g_string_append_printf (lines, " %s",
842             msg->audio_codecs->list[i].audio_format);
843         g_string_append_printf (lines, " %08x",
844             msg->audio_codecs->list[i].modes);
845         g_string_append_printf (lines, " %02x",
846             msg->audio_codecs->list[i].latency);
847         if ((i + 1) < msg->audio_codecs->count)
848           g_string_append_printf (lines, ",");
849       }
850     }
851     g_string_append_printf (lines, "\r\n");
852   }
853
854   /* list of video codecs */
855   if (msg->video_formats) {
856     g_string_append_printf (lines, GST_STRING_WFD_VIDEO_FORMATS);
857     if (msg->video_formats->list) {
858       g_string_append_printf (lines, ":");
859       g_string_append_printf (lines, " %02x", msg->video_formats->list->native);
860       g_string_append_printf (lines, " %02x",
861           msg->video_formats->list->preferred_display_mode_supported);
862       g_string_append_printf (lines, " %02x",
863           msg->video_formats->list->H264_codec.profile);
864       g_string_append_printf (lines, " %02x",
865           msg->video_formats->list->H264_codec.level);
866       g_string_append_printf (lines, " %08x",
867           msg->video_formats->list->H264_codec.misc_params.CEA_Support);
868       g_string_append_printf (lines, " %08x",
869           msg->video_formats->list->H264_codec.misc_params.VESA_Support);
870       g_string_append_printf (lines, " %08x",
871           msg->video_formats->list->H264_codec.misc_params.HH_Support);
872       g_string_append_printf (lines, " %02x",
873           msg->video_formats->list->H264_codec.misc_params.latency);
874       g_string_append_printf (lines, " %04x",
875           msg->video_formats->list->H264_codec.misc_params.min_slice_size);
876       g_string_append_printf (lines, " %04x",
877           msg->video_formats->list->H264_codec.misc_params.slice_enc_params);
878       g_string_append_printf (lines, " %02x",
879           msg->video_formats->list->H264_codec.misc_params.
880           frame_rate_control_support);
881
882       if (msg->video_formats->list->H264_codec.max_hres)
883         g_string_append_printf (lines, " %04x",
884             msg->video_formats->list->H264_codec.max_hres);
885       else
886         g_string_append_printf (lines, " none");
887
888       if (msg->video_formats->list->H264_codec.max_vres)
889         g_string_append_printf (lines, " %04x",
890             msg->video_formats->list->H264_codec.max_vres);
891       else
892         g_string_append_printf (lines, " none");
893     }
894     g_string_append_printf (lines, "\r\n");
895   }
896
897   /* list of video 3D codecs */
898   if (msg->video_3d_formats) {
899     g_string_append_printf (lines, GST_STRING_WFD_3D_VIDEO_FORMATS);
900     g_string_append_printf (lines, ":");
901     if (msg->video_3d_formats->list) {
902       g_string_append_printf (lines, " %02x",
903           msg->video_3d_formats->list->native);
904       g_string_append_printf (lines, " %02x",
905           msg->video_3d_formats->list->preferred_display_mode_supported);
906       g_string_append_printf (lines, " %02x",
907           msg->video_3d_formats->list->H264_codec.profile);
908       g_string_append_printf (lines, " %02x",
909           msg->video_3d_formats->list->H264_codec.level);
910       g_string_append_printf (lines, " %16x",
911           msg->video_3d_formats->list->H264_codec.misc_params.
912           video_3d_capability);
913       g_string_append_printf (lines, " %02x",
914           msg->video_3d_formats->list->H264_codec.misc_params.latency);
915       g_string_append_printf (lines, " %04x",
916           msg->video_3d_formats->list->H264_codec.misc_params.min_slice_size);
917       g_string_append_printf (lines, " %04x",
918           msg->video_3d_formats->list->H264_codec.misc_params.slice_enc_params);
919       g_string_append_printf (lines, " %02x",
920           msg->video_3d_formats->list->H264_codec.misc_params.
921           frame_rate_control_support);
922       if (msg->video_3d_formats->list->H264_codec.max_hres)
923         g_string_append_printf (lines, " %04x",
924             msg->video_3d_formats->list->H264_codec.max_hres);
925       else
926         g_string_append_printf (lines, " none");
927       if (msg->video_3d_formats->list->H264_codec.max_vres)
928         g_string_append_printf (lines, " %04x",
929             msg->video_3d_formats->list->H264_codec.max_vres);
930       else
931         g_string_append_printf (lines, " none");
932     } else {
933       g_string_append_printf (lines, " none");
934     }
935     g_string_append_printf (lines, "\r\n");
936   }
937
938   if (msg->content_protection) {
939     g_string_append_printf (lines, GST_STRING_WFD_CONTENT_PROTECTION);
940     g_string_append_printf (lines, ":");
941     if (msg->content_protection->hdcp2_spec) {
942       if (msg->content_protection->hdcp2_spec->hdcpversion) {
943         g_string_append_printf (lines, " %s",
944             msg->content_protection->hdcp2_spec->hdcpversion);
945         g_string_append_printf (lines, " %s",
946             msg->content_protection->hdcp2_spec->TCPPort);
947       } else {
948         g_string_append_printf (lines, " none");
949       }
950     } else {
951       g_string_append_printf (lines, " none");
952     }
953     g_string_append_printf (lines, "\r\n");
954   }
955
956   if (msg->display_edid) {
957     g_string_append_printf (lines, GST_STRING_WFD_DISPLAY_EDID);
958     g_string_append_printf (lines, ":");
959     if (msg->display_edid->edid_supported) {
960       if (msg->display_edid->edid_block_count > 0 &&
961           msg->display_edid->edid_block_count <= EDID_BLOCK_COUNT_MAX_SIZE) {
962         g_string_append_printf (lines, " %04x",
963             msg->display_edid->edid_block_count);
964         g_string_append_printf (lines, " %s", msg->display_edid->edid_payload);
965       } else
966         g_string_append_printf (lines, " none");
967     } else {
968       g_string_append_printf (lines, " none");
969     }
970     g_string_append_printf (lines, "\r\n");
971   }
972
973   if (msg->coupled_sink) {
974     g_string_append_printf (lines, GST_STRING_WFD_COUPLED_SINK);
975     g_string_append_printf (lines, ":");
976     if (msg->coupled_sink->coupled_sink_cap) {
977       g_string_append_printf (lines, " %02x",
978           msg->coupled_sink->coupled_sink_cap->status);
979       if (msg->coupled_sink->coupled_sink_cap->sink_address)
980         g_string_append_printf (lines, " %s",
981             msg->coupled_sink->coupled_sink_cap->sink_address);
982       else
983         g_string_append_printf (lines, " none");
984     } else {
985       g_string_append_printf (lines, " none");
986     }
987     g_string_append_printf (lines, "\r\n");
988   }
989
990   if (msg->trigger_method) {
991     g_string_append_printf (lines, GST_STRING_WFD_TRIGGER_METHOD);
992     g_string_append_printf (lines, ":");
993     g_string_append_printf (lines, " %s",
994         msg->trigger_method->wfd_trigger_method);
995     g_string_append_printf (lines, "\r\n");
996   }
997
998   if (msg->presentation_url) {
999     g_string_append_printf (lines, GST_STRING_WFD_PRESENTATION_URL);
1000     g_string_append_printf (lines, ":");
1001     if (msg->presentation_url->wfd_url0)
1002       g_string_append_printf (lines, " %s", msg->presentation_url->wfd_url0);
1003     else
1004       g_string_append_printf (lines, " none");
1005     if (msg->presentation_url->wfd_url1)
1006       g_string_append_printf (lines, " %s", msg->presentation_url->wfd_url1);
1007     else
1008       g_string_append_printf (lines, " none");
1009     g_string_append_printf (lines, "\r\n");
1010   }
1011
1012   if (msg->client_rtp_ports) {
1013     g_string_append_printf (lines, GST_STRING_WFD_CLIENT_RTP_PORTS);
1014     if (msg->client_rtp_ports->profile) {
1015       g_string_append_printf (lines, ":");
1016       g_string_append_printf (lines, " %s", msg->client_rtp_ports->profile);
1017       g_string_append_printf (lines, " %d", msg->client_rtp_ports->rtp_port0);
1018       g_string_append_printf (lines, " %d", msg->client_rtp_ports->rtp_port1);
1019       g_string_append_printf (lines, " %s", msg->client_rtp_ports->mode);
1020     }
1021     g_string_append_printf (lines, "\r\n");
1022   }
1023
1024   if (msg->route) {
1025     g_string_append_printf (lines, GST_STRING_WFD_ROUTE);
1026     g_string_append_printf (lines, ":");
1027     g_string_append_printf (lines, " %s", msg->route->destination);
1028     g_string_append_printf (lines, "\r\n");
1029   }
1030
1031   if (msg->I2C) {
1032     g_string_append_printf (lines, GST_STRING_WFD_I2C);
1033     g_string_append_printf (lines, ":");
1034     if (msg->I2C->I2CPresent)
1035       g_string_append_printf (lines, " %x", msg->I2C->I2C_port);
1036     else
1037       g_string_append_printf (lines, " none");
1038     g_string_append_printf (lines, "\r\n");
1039   }
1040
1041   if (msg->av_format_change_timing) {
1042     g_string_append_printf (lines, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING);
1043     g_string_append_printf (lines, ":");
1044     g_string_append_printf (lines, " %010llx",
1045         msg->av_format_change_timing->PTS);
1046     g_string_append_printf (lines, " %010llx",
1047         msg->av_format_change_timing->DTS);
1048     g_string_append_printf (lines, "\r\n");
1049   }
1050
1051   if (msg->preferred_display_mode) {
1052     g_string_append_printf (lines, GST_STRING_WFD_PREFERRED_DISPLAY_MODE);
1053     g_string_append_printf (lines, ":");
1054     if (msg->preferred_display_mode->displaymodesupported) {
1055       g_string_append_printf (lines, " %06llx",
1056           msg->preferred_display_mode->p_clock);
1057       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->H);
1058       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->HB);
1059       g_string_append_printf (lines, " %04x",
1060           msg->preferred_display_mode->HSPOL_HSOFF);
1061       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->HSW);
1062       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->V);
1063       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->VB);
1064       g_string_append_printf (lines, " %04x",
1065           msg->preferred_display_mode->VSPOL_VSOFF);
1066       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->VSW);
1067       g_string_append_printf (lines, " %02x",
1068           msg->preferred_display_mode->VBS3D);
1069       g_string_append_printf (lines, " %02x",
1070           msg->preferred_display_mode->V2d_s3d_modes);
1071       g_string_append_printf (lines, " %02x",
1072           msg->preferred_display_mode->P_depth);
1073     } else
1074       g_string_append_printf (lines, " none");
1075     g_string_append_printf (lines, "\r\n");
1076   }
1077
1078   if (msg->standby_resume_capability) {
1079     g_string_append_printf (lines, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY);
1080     g_string_append_printf (lines, ":");
1081     if (msg->standby_resume_capability->standby_resume_cap)
1082       g_string_append_printf (lines, " supported");
1083     else
1084       g_string_append_printf (lines, " none");
1085     g_string_append_printf (lines, "\r\n");
1086   }
1087
1088   if (msg->standby) {
1089     g_string_append_printf (lines, GST_STRING_WFD_STANDBY);
1090     g_string_append_printf (lines, "\r\n");
1091   }
1092
1093   if (msg->connector_type) {
1094     g_string_append_printf (lines, GST_STRING_WFD_CONNECTOR_TYPE);
1095     g_string_append_printf (lines, ":");
1096     if (msg->connector_type->connector_type)
1097       g_string_append_printf (lines, " %02x",
1098           msg->connector_type->connector_type);
1099     else
1100       g_string_append_printf (lines, " none");
1101     g_string_append_printf (lines, "\r\n");
1102   }
1103
1104   if (msg->idr_request) {
1105     g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST);
1106     g_string_append_printf (lines, "\r\n");
1107   }
1108
1109   return g_string_free (lines, FALSE);
1110 }
1111
1112 gchar *
1113 gst_wfd_message_param_names_as_text (const GstWFDMessage * msg)
1114 {
1115   /* change all vars so they match rfc? */
1116   GString *lines;
1117   g_return_val_if_fail (msg != NULL, NULL);
1118
1119   lines = g_string_new ("");
1120
1121   /* list of audio codecs */
1122   if (msg->audio_codecs) {
1123     g_string_append_printf (lines, GST_STRING_WFD_AUDIO_CODECS);
1124     g_string_append_printf (lines, "\r\n");
1125   }
1126   /* list of video codecs */
1127   if (msg->video_formats) {
1128     g_string_append_printf (lines, GST_STRING_WFD_VIDEO_FORMATS);
1129     g_string_append_printf (lines, "\r\n");
1130   }
1131   /* list of video 3D codecs */
1132   if (msg->video_3d_formats) {
1133     g_string_append_printf (lines, GST_STRING_WFD_3D_VIDEO_FORMATS);
1134     g_string_append_printf (lines, "\r\n");
1135   }
1136   if (msg->content_protection) {
1137     g_string_append_printf (lines, GST_STRING_WFD_CONTENT_PROTECTION);
1138     g_string_append_printf (lines, "\r\n");
1139   }
1140   if (msg->display_edid) {
1141     g_string_append_printf (lines, GST_STRING_WFD_DISPLAY_EDID);
1142     g_string_append_printf (lines, "\r\n");
1143   }
1144   if (msg->coupled_sink) {
1145     g_string_append_printf (lines, GST_STRING_WFD_COUPLED_SINK);
1146     g_string_append_printf (lines, "\r\n");
1147   }
1148   if (msg->trigger_method) {
1149     g_string_append_printf (lines, GST_STRING_WFD_TRIGGER_METHOD);
1150     g_string_append_printf (lines, "\r\n");
1151   }
1152   if (msg->presentation_url) {
1153     g_string_append_printf (lines, GST_STRING_WFD_PRESENTATION_URL);
1154     g_string_append_printf (lines, "\r\n");
1155   }
1156   if (msg->client_rtp_ports) {
1157     g_string_append_printf (lines, GST_STRING_WFD_CLIENT_RTP_PORTS);
1158     g_string_append_printf (lines, "\r\n");
1159   }
1160   if (msg->route) {
1161     g_string_append_printf (lines, GST_STRING_WFD_ROUTE);
1162     g_string_append_printf (lines, "\r\n");
1163   }
1164   if (msg->I2C) {
1165     g_string_append_printf (lines, GST_STRING_WFD_I2C);
1166     g_string_append_printf (lines, "\r\n");
1167   }
1168   if (msg->av_format_change_timing) {
1169     g_string_append_printf (lines, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING);
1170     g_string_append_printf (lines, "\r\n");
1171   }
1172   if (msg->preferred_display_mode) {
1173     g_string_append_printf (lines, GST_STRING_WFD_PREFERRED_DISPLAY_MODE);
1174     g_string_append_printf (lines, "\r\n");
1175   }
1176   if (msg->standby_resume_capability) {
1177     g_string_append_printf (lines, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY);
1178     g_string_append_printf (lines, "\r\n");
1179   }
1180   if (msg->standby) {
1181     g_string_append_printf (lines, GST_STRING_WFD_STANDBY);
1182     g_string_append_printf (lines, "\r\n");
1183   }
1184   if (msg->connector_type) {
1185     g_string_append_printf (lines, GST_STRING_WFD_CONNECTOR_TYPE);
1186     g_string_append_printf (lines, "\r\n");
1187   }
1188   if (msg->idr_request) {
1189     g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST);
1190     g_string_append_printf (lines, "\r\n");
1191   }
1192
1193   return g_string_free (lines, FALSE);
1194 }
1195
1196 /**
1197  * gst_wfd_message_dump:
1198  * @msg: a #GstWFDMessage
1199  *
1200  * Dump the parsed contents of @msg to stdout.
1201  *
1202  * Returns: a #GstWFDResult.
1203  */
1204 GstWFDResult
1205 gst_wfd_message_dump (const GstWFDMessage * msg)
1206 {
1207   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1208
1209   if (msg->audio_codecs) {
1210     guint i = 0;
1211     g_print ("Audio supported formats : \n");
1212     for (; i < msg->audio_codecs->count; i++) {
1213       g_print ("Codec: %s\n", msg->audio_codecs->list[i].audio_format);
1214       if (!strcmp (msg->audio_codecs->list[i].audio_format, "LPCM")) {
1215         if (msg->audio_codecs->list[i].modes & GST_WFD_FREQ_44100)
1216           g_print ("    Freq: %d\n", 44100);
1217         if (msg->audio_codecs->list[i].modes & GST_WFD_FREQ_48000)
1218           g_print ("    Freq: %d\n", 48000);
1219         g_print ("      Channels: %d\n", 2);
1220       }
1221       if (!strcmp (msg->audio_codecs->list[i].audio_format, "AAC")) {
1222         g_print ("      Freq: %d\n", 48000);
1223         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_2)
1224           g_print ("    Channels: %d\n", 2);
1225         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_4)
1226           g_print ("    Channels: %d\n", 4);
1227         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_6)
1228           g_print ("    Channels: %d\n", 6);
1229         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_8)
1230           g_print ("    Channels: %d\n", 8);
1231       }
1232       if (!strcmp (msg->audio_codecs->list[i].audio_format, "AC3")) {
1233         g_print ("      Freq: %d\n", 48000);
1234         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_2)
1235           g_print ("    Channels: %d\n", 2);
1236         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_4)
1237           g_print ("    Channels: %d\n", 4);
1238         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_6)
1239           g_print ("    Channels: %d\n", 6);
1240       }
1241       g_print ("        Bitwidth: %d\n", 16);
1242       g_print ("        Latency: %d\n", msg->audio_codecs->list[i].latency);
1243     }
1244   }
1245
1246
1247   if (msg->video_formats) {
1248     g_print ("Video supported formats : \n");
1249     if (msg->video_formats->list) {
1250       guint nativeindex = 0;
1251       g_print ("Codec: H264\n");
1252       if ((msg->video_formats->list->native & 0x7) ==
1253           GST_WFD_VIDEO_CEA_RESOLUTION) {
1254         g_print ("      Native type: CEA\n");
1255       } else if ((msg->video_formats->list->native & 0x7) ==
1256           GST_WFD_VIDEO_VESA_RESOLUTION) {
1257         g_print ("      Native type: VESA\n");
1258       } else if ((msg->video_formats->list->native & 0x7) ==
1259           GST_WFD_VIDEO_HH_RESOLUTION) {
1260         g_print ("      Native type: HH\n");
1261       }
1262       nativeindex = msg->video_formats->list->native >> 3;
1263       g_print ("        Resolution: %d\n", (1 << nativeindex));
1264
1265       if (msg->video_formats->list->H264_codec.
1266           profile & GST_WFD_H264_BASE_PROFILE) {
1267         g_print ("      Profile: BASE\n");
1268       } else if (msg->video_formats->list->H264_codec.
1269           profile & GST_WFD_H264_HIGH_PROFILE) {
1270         g_print ("      Profile: HIGH\n");
1271       }
1272       if (msg->video_formats->list->H264_codec.level & GST_WFD_H264_LEVEL_3_1) {
1273         g_print ("      Level: 3.1\n");
1274       } else if (msg->video_formats->list->H264_codec.
1275           level & GST_WFD_H264_LEVEL_3_2) {
1276         g_print ("      Level: 3.2\n");
1277       } else if (msg->video_formats->list->H264_codec.
1278           level & GST_WFD_H264_LEVEL_4) {
1279         g_print ("      Level: 4\n");
1280       } else if (msg->video_formats->list->H264_codec.
1281           level & GST_WFD_H264_LEVEL_4_1) {
1282         g_print ("      Level: 4.1\n");
1283       } else if (msg->video_formats->list->H264_codec.
1284           level & GST_WFD_H264_LEVEL_4_2) {
1285         g_print ("      Level: 4.2\n");
1286       }
1287       g_print ("        Latency: %d\n",
1288           msg->video_formats->list->H264_codec.misc_params.latency);
1289       g_print ("        min_slice_size: %x\n",
1290           msg->video_formats->list->H264_codec.misc_params.min_slice_size);
1291       g_print ("        slice_enc_params: %x\n",
1292           msg->video_formats->list->H264_codec.misc_params.slice_enc_params);
1293       g_print ("        frame_rate_control_support: %x\n",
1294           msg->video_formats->list->H264_codec.misc_params.
1295           frame_rate_control_support);
1296       if (msg->video_formats->list->H264_codec.max_hres) {
1297         g_print ("      Max Height: %04d\n",
1298             msg->video_formats->list->H264_codec.max_hres);
1299       }
1300       if (msg->video_formats->list->H264_codec.max_vres) {
1301         g_print ("      Max Width: %04d\n",
1302             msg->video_formats->list->H264_codec.max_vres);
1303       }
1304     }
1305   }
1306
1307   if (msg->video_3d_formats) {
1308     g_print ("wfd_3d_formats");
1309     g_print ("\r\n");
1310   }
1311
1312   if (msg->content_protection) {
1313     g_print (GST_STRING_WFD_CONTENT_PROTECTION);
1314     g_print ("\r\n");
1315   }
1316
1317   if (msg->display_edid) {
1318     g_print (GST_STRING_WFD_DISPLAY_EDID);
1319     g_print ("\r\n");
1320   }
1321
1322   if (msg->coupled_sink) {
1323     g_print (GST_STRING_WFD_COUPLED_SINK);
1324     g_print ("\r\n");
1325   }
1326
1327   if (msg->trigger_method) {
1328     g_print ("  Trigger type: %s\n", msg->trigger_method->wfd_trigger_method);
1329   }
1330
1331   if (msg->presentation_url) {
1332     g_print (GST_STRING_WFD_PRESENTATION_URL);
1333     g_print ("\r\n");
1334   }
1335
1336   if (msg->client_rtp_ports) {
1337     g_print (" Client RTP Ports : \n");
1338     if (msg->client_rtp_ports->profile) {
1339       g_print ("%s\n", msg->client_rtp_ports->profile);
1340       g_print ("        %d\n", msg->client_rtp_ports->rtp_port0);
1341       g_print ("        %d\n", msg->client_rtp_ports->rtp_port1);
1342       g_print ("        %s\n", msg->client_rtp_ports->mode);
1343     }
1344     g_print ("\r\n");
1345   }
1346
1347   if (msg->route) {
1348     g_print (GST_STRING_WFD_ROUTE);
1349     g_print ("\r\n");
1350   }
1351
1352   if (msg->I2C) {
1353     g_print (GST_STRING_WFD_I2C);
1354     g_print ("\r\n");
1355   }
1356
1357   if (msg->av_format_change_timing) {
1358     g_print (GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING);
1359     g_print ("\r\n");
1360   }
1361
1362   if (msg->preferred_display_mode) {
1363     g_print (GST_STRING_WFD_PREFERRED_DISPLAY_MODE);
1364     g_print ("\r\n");
1365   }
1366
1367   if (msg->standby_resume_capability) {
1368     g_print (GST_STRING_WFD_STANDBY_RESUME_CAPABILITY);
1369     g_print ("\r\n");
1370   }
1371
1372   if (msg->standby) {
1373     g_print (GST_STRING_WFD_STANDBY);
1374     g_print ("\r\n");
1375   }
1376
1377   if (msg->connector_type) {
1378     g_print (GST_STRING_WFD_CONNECTOR_TYPE);
1379     g_print ("\r\n");
1380   }
1381
1382   if (msg->idr_request) {
1383     g_print (GST_STRING_WFD_IDR_REQUEST);
1384     g_print ("\r\n");
1385   }
1386
1387   return GST_WFD_OK;
1388 }
1389
1390 GstWFDResult
1391 gst_wfd_message_set_supported_audio_format (GstWFDMessage * msg,
1392     GstWFDAudioFormats a_codec,
1393     guint a_freq, guint a_channels, guint a_bitwidth, guint32 a_latency)
1394 {
1395   guint i = 0;
1396   guint pcm = 0, aac = 0, ac3 = 0;
1397
1398   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1399
1400   if (!msg->audio_codecs)
1401     msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1);
1402
1403   if (a_codec != GST_WFD_AUDIO_UNKNOWN) {
1404
1405     if (a_codec & GST_WFD_AUDIO_LPCM)
1406       msg->audio_codecs->count++;
1407     if (a_codec & GST_WFD_AUDIO_AAC)
1408       msg->audio_codecs->count++;
1409     if (a_codec & GST_WFD_AUDIO_AC3)
1410       msg->audio_codecs->count++;
1411
1412     msg->audio_codecs->list =
1413         g_new0 (GstWFDAudioCodec, msg->audio_codecs->count);
1414     for (; i < msg->audio_codecs->count; i++) {
1415       if ((a_codec & GST_WFD_AUDIO_LPCM) && (!pcm)) {
1416         msg->audio_codecs->list[i].audio_format = g_strdup ("LPCM");
1417         msg->audio_codecs->list[i].modes = a_freq;
1418         msg->audio_codecs->list[i].latency = a_latency;
1419         pcm = 1;
1420       } else if ((a_codec & GST_WFD_AUDIO_AAC) && (!aac)) {
1421         msg->audio_codecs->list[i].audio_format = g_strdup ("AAC");
1422         msg->audio_codecs->list[i].modes = a_channels;
1423         msg->audio_codecs->list[i].latency = a_latency;
1424         aac = 1;
1425       } else if ((a_codec & GST_WFD_AUDIO_AC3) && (!ac3)) {
1426         msg->audio_codecs->list[i].audio_format = g_strdup ("AC3");
1427         msg->audio_codecs->list[i].modes = a_channels;
1428         msg->audio_codecs->list[i].latency = a_latency;
1429         ac3 = 1;
1430       }
1431     }
1432   }
1433   return GST_WFD_OK;
1434 }
1435
1436 GstWFDResult
1437 gst_wfd_message_set_prefered_audio_format (GstWFDMessage * msg,
1438     GstWFDAudioFormats a_codec,
1439     GstWFDAudioFreq a_freq,
1440     GstWFDAudioChannels a_channels, guint a_bitwidth, guint32 a_latency)
1441 {
1442   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1443
1444   if (!msg->audio_codecs)
1445     msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1);
1446
1447   msg->audio_codecs->list = g_new0 (GstWFDAudioCodec, 1);
1448   msg->audio_codecs->count = 1;
1449   if (a_codec == GST_WFD_AUDIO_LPCM) {
1450     msg->audio_codecs->list->audio_format = g_strdup ("LPCM");
1451     msg->audio_codecs->list->modes = a_freq;
1452     msg->audio_codecs->list->latency = a_latency;
1453   } else if (a_codec == GST_WFD_AUDIO_AAC) {
1454     msg->audio_codecs->list->audio_format = g_strdup ("AAC");
1455     msg->audio_codecs->list->modes = a_channels;
1456     msg->audio_codecs->list->latency = a_latency;
1457   } else if (a_codec == GST_WFD_AUDIO_AC3) {
1458     msg->audio_codecs->list->audio_format = g_strdup ("AC3");
1459     msg->audio_codecs->list->modes = a_channels;
1460     msg->audio_codecs->list->latency = a_latency;
1461   }
1462   return GST_WFD_OK;
1463 }
1464
1465 GstWFDResult
1466 gst_wfd_message_get_supported_audio_format (GstWFDMessage * msg,
1467     guint * a_codec,
1468     guint * a_freq, guint * a_channels, guint * a_bitwidth, guint32 * a_latency)
1469 {
1470   guint i = 0;
1471   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1472   g_return_val_if_fail (msg->audio_codecs != NULL, GST_WFD_EINVAL);
1473
1474   for (; i < msg->audio_codecs->count; i++) {
1475     if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "LPCM")) {
1476       *a_codec |= GST_WFD_AUDIO_LPCM;
1477       *a_freq |= msg->audio_codecs->list[i].modes;
1478       *a_channels |= GST_WFD_CHANNEL_2;
1479       *a_bitwidth = 16;
1480       *a_latency = msg->audio_codecs->list[i].latency;
1481     } else if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "AAC")) {
1482       *a_codec |= GST_WFD_AUDIO_AAC;
1483       *a_freq |= GST_WFD_FREQ_48000;
1484       *a_channels |= msg->audio_codecs->list[i].modes;
1485       *a_bitwidth = 16;
1486       *a_latency = msg->audio_codecs->list[i].latency;
1487     } else if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "AC3")) {
1488       *a_codec |= GST_WFD_AUDIO_AC3;
1489       *a_freq |= GST_WFD_FREQ_48000;
1490       *a_channels |= msg->audio_codecs->list[i].modes;
1491       *a_bitwidth = 16;
1492       *a_latency = msg->audio_codecs->list[i].latency;
1493     }
1494   }
1495   return GST_WFD_OK;
1496 }
1497
1498 GstWFDResult
1499 gst_wfd_message_get_prefered_audio_format (GstWFDMessage * msg,
1500     GstWFDAudioFormats * a_codec,
1501     GstWFDAudioFreq * a_freq,
1502     GstWFDAudioChannels * a_channels, guint * a_bitwidth, guint32 * a_latency)
1503 {
1504   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1505
1506   if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "LPCM")) {
1507     *a_codec = GST_WFD_AUDIO_LPCM;
1508     *a_freq = msg->audio_codecs->list->modes;
1509     *a_channels = GST_WFD_CHANNEL_2;
1510     *a_bitwidth = 16;
1511     *a_latency = msg->audio_codecs->list->latency;
1512   } else if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "AAC")) {
1513     *a_codec = GST_WFD_AUDIO_AAC;
1514     *a_freq = GST_WFD_FREQ_48000;
1515     *a_channels = msg->audio_codecs->list->modes;
1516     *a_bitwidth = 16;
1517     *a_latency = msg->audio_codecs->list->latency;
1518   } else if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "AC3")) {
1519     *a_codec = GST_WFD_AUDIO_AC3;
1520     *a_freq = GST_WFD_FREQ_48000;
1521     *a_channels = msg->audio_codecs->list->modes;
1522     *a_bitwidth = 16;
1523     *a_latency = msg->audio_codecs->list->latency;
1524   }
1525   return GST_WFD_OK;
1526 }
1527
1528 GstWFDResult
1529 gst_wfd_message_set_supported_video_format (GstWFDMessage * msg,
1530     GstWFDVideoCodecs v_codec,
1531     GstWFDVideoNativeResolution v_native,
1532     guint64 v_native_resolution,
1533     guint64 v_cea_resolution,
1534     guint64 v_vesa_resolution,
1535     guint64 v_hh_resolution,
1536     guint v_profile,
1537     guint v_level,
1538     guint32 v_latency,
1539     guint32 v_max_height,
1540     guint32 v_max_width,
1541     guint32 min_slice_size, guint32 slice_enc_params, guint frame_rate_control)
1542 {
1543   guint nativeindex = 0;
1544   guint64 temp = v_native_resolution;
1545
1546   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1547
1548   if (!msg->video_formats)
1549     msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1);
1550
1551   if (v_codec != GST_WFD_VIDEO_UNKNOWN) {
1552     msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1);
1553     while (temp) {
1554       nativeindex++;
1555       temp >>= 1;
1556     }
1557
1558     msg->video_formats->list->native = nativeindex - 1;
1559     msg->video_formats->list->native <<= 3;
1560
1561     if (v_native == GST_WFD_VIDEO_VESA_RESOLUTION)
1562       msg->video_formats->list->native |= 1;
1563     else if (v_native == GST_WFD_VIDEO_HH_RESOLUTION)
1564       msg->video_formats->list->native |= 2;
1565
1566     msg->video_formats->list->preferred_display_mode_supported = 1;
1567     msg->video_formats->list->H264_codec.profile = v_profile;
1568     msg->video_formats->list->H264_codec.level = v_level;
1569     msg->video_formats->list->H264_codec.max_hres = v_max_height;
1570     msg->video_formats->list->H264_codec.max_vres = v_max_width;
1571     msg->video_formats->list->H264_codec.misc_params.CEA_Support =
1572         v_cea_resolution;
1573     msg->video_formats->list->H264_codec.misc_params.VESA_Support =
1574         v_vesa_resolution;
1575     msg->video_formats->list->H264_codec.misc_params.HH_Support =
1576         v_hh_resolution;
1577     msg->video_formats->list->H264_codec.misc_params.latency = v_latency;
1578     msg->video_formats->list->H264_codec.misc_params.min_slice_size =
1579         min_slice_size;
1580     msg->video_formats->list->H264_codec.misc_params.slice_enc_params =
1581         slice_enc_params;
1582     msg->video_formats->list->H264_codec.misc_params.
1583         frame_rate_control_support = frame_rate_control;
1584   }
1585   return GST_WFD_OK;
1586 }
1587
1588 GstWFDResult
1589 gst_wfd_message_set_prefered_video_format (GstWFDMessage * msg,
1590     GstWFDVideoCodecs v_codec,
1591     GstWFDVideoNativeResolution v_native,
1592     guint64 v_native_resolution,
1593     GstWFDVideoCEAResolution v_cea_resolution,
1594     GstWFDVideoVESAResolution v_vesa_resolution,
1595     GstWFDVideoHHResolution v_hh_resolution,
1596     GstWFDVideoH264Profile v_profile,
1597     GstWFDVideoH264Level v_level,
1598     guint32 v_latency,
1599     guint32 v_max_height,
1600     guint32 v_max_width,
1601     guint32 min_slice_size, guint32 slice_enc_params, guint frame_rate_control)
1602 {
1603   guint nativeindex = 0;
1604   guint64 temp = v_native_resolution;
1605
1606   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1607
1608   if (!msg->video_formats)
1609     msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1);
1610   msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1);
1611
1612   while (temp) {
1613     nativeindex++;
1614     temp >>= 1;
1615   }
1616
1617   if (nativeindex)
1618     msg->video_formats->list->native = nativeindex - 1;
1619   msg->video_formats->list->native <<= 3;
1620
1621   if (v_native == GST_WFD_VIDEO_VESA_RESOLUTION)
1622     msg->video_formats->list->native |= 1;
1623   else if (v_native == GST_WFD_VIDEO_HH_RESOLUTION)
1624     msg->video_formats->list->native |= 2;
1625
1626   msg->video_formats->list->preferred_display_mode_supported = 0;
1627   msg->video_formats->list->H264_codec.profile = v_profile;
1628   msg->video_formats->list->H264_codec.level = v_level;
1629   msg->video_formats->list->H264_codec.max_hres = v_max_height;
1630   msg->video_formats->list->H264_codec.max_vres = v_max_width;
1631   msg->video_formats->list->H264_codec.misc_params.CEA_Support =
1632       v_cea_resolution;
1633   msg->video_formats->list->H264_codec.misc_params.VESA_Support =
1634       v_vesa_resolution;
1635   msg->video_formats->list->H264_codec.misc_params.HH_Support = v_hh_resolution;
1636   msg->video_formats->list->H264_codec.misc_params.latency = v_latency;
1637   msg->video_formats->list->H264_codec.misc_params.min_slice_size =
1638       min_slice_size;
1639   msg->video_formats->list->H264_codec.misc_params.slice_enc_params =
1640       slice_enc_params;
1641   msg->video_formats->list->H264_codec.misc_params.frame_rate_control_support =
1642       frame_rate_control;
1643   return GST_WFD_OK;
1644 }
1645
1646 GstWFDResult
1647 gst_wfd_message_get_supported_video_format (GstWFDMessage * msg,
1648     GstWFDVideoCodecs * v_codec,
1649     GstWFDVideoNativeResolution * v_native,
1650     guint64 * v_native_resolution,
1651     guint64 * v_cea_resolution,
1652     guint64 * v_vesa_resolution,
1653     guint64 * v_hh_resolution,
1654     guint * v_profile,
1655     guint * v_level,
1656     guint32 * v_latency,
1657     guint32 * v_max_height,
1658     guint32 * v_max_width,
1659     guint32 * min_slice_size,
1660     guint32 * slice_enc_params, guint * frame_rate_control)
1661 {
1662   guint nativeindex = 0;
1663
1664   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1665   *v_codec = GST_WFD_VIDEO_H264;
1666   *v_native = msg->video_formats->list->native & 0x7;
1667   nativeindex = msg->video_formats->list->native >> 3;
1668   *v_native_resolution = ((guint64) 1) << nativeindex;
1669   *v_profile = msg->video_formats->list->H264_codec.profile;
1670   *v_level = msg->video_formats->list->H264_codec.level;
1671   *v_max_height = msg->video_formats->list->H264_codec.max_hres;
1672   *v_max_width = msg->video_formats->list->H264_codec.max_vres;
1673   *v_cea_resolution =
1674       msg->video_formats->list->H264_codec.misc_params.CEA_Support;
1675   *v_vesa_resolution =
1676       msg->video_formats->list->H264_codec.misc_params.VESA_Support;
1677   *v_hh_resolution =
1678       msg->video_formats->list->H264_codec.misc_params.HH_Support;
1679   *v_latency = msg->video_formats->list->H264_codec.misc_params.latency;
1680   *min_slice_size =
1681       msg->video_formats->list->H264_codec.misc_params.min_slice_size;
1682   *slice_enc_params =
1683       msg->video_formats->list->H264_codec.misc_params.slice_enc_params;
1684   *frame_rate_control =
1685       msg->video_formats->list->H264_codec.misc_params.
1686       frame_rate_control_support;
1687   return GST_WFD_OK;
1688 }
1689
1690 GstWFDResult
1691 gst_wfd_message_get_prefered_video_format (GstWFDMessage * msg,
1692     GstWFDVideoCodecs * v_codec,
1693     GstWFDVideoNativeResolution * v_native,
1694     guint64 * v_native_resolution,
1695     GstWFDVideoCEAResolution * v_cea_resolution,
1696     GstWFDVideoVESAResolution * v_vesa_resolution,
1697     GstWFDVideoHHResolution * v_hh_resolution,
1698     GstWFDVideoH264Profile * v_profile,
1699     GstWFDVideoH264Level * v_level,
1700     guint32 * v_latency,
1701     guint32 * v_max_height,
1702     guint32 * v_max_width,
1703     guint32 * min_slice_size,
1704     guint32 * slice_enc_params, guint * frame_rate_control)
1705 {
1706   guint nativeindex = 0;
1707   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1708
1709   *v_codec = GST_WFD_VIDEO_H264;
1710   *v_native = msg->video_formats->list->native & 0x7;
1711   nativeindex = msg->video_formats->list->native >> 3;
1712   *v_native_resolution = ((guint64) 1) << nativeindex;
1713   *v_profile = msg->video_formats->list->H264_codec.profile;
1714   *v_level = msg->video_formats->list->H264_codec.level;
1715   *v_max_height = msg->video_formats->list->H264_codec.max_hres;
1716   *v_max_width = msg->video_formats->list->H264_codec.max_vres;
1717   *v_cea_resolution =
1718       msg->video_formats->list->H264_codec.misc_params.CEA_Support;
1719   *v_vesa_resolution =
1720       msg->video_formats->list->H264_codec.misc_params.VESA_Support;
1721   *v_hh_resolution =
1722       msg->video_formats->list->H264_codec.misc_params.HH_Support;
1723   *v_latency = msg->video_formats->list->H264_codec.misc_params.latency;
1724   *min_slice_size =
1725       msg->video_formats->list->H264_codec.misc_params.min_slice_size;
1726   *slice_enc_params =
1727       msg->video_formats->list->H264_codec.misc_params.slice_enc_params;
1728   *frame_rate_control =
1729       msg->video_formats->list->H264_codec.misc_params.
1730       frame_rate_control_support;
1731   return GST_WFD_OK;
1732 }
1733
1734 GstWFDResult
1735 gst_wfd_message_set_display_edid (GstWFDMessage * msg,
1736     gboolean edid_supported, guint32 edid_blockcount, gchar * edid_playload)
1737 {
1738   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1739   if (!msg->display_edid)
1740     msg->display_edid = g_new0 (GstWFDDisplayEdid, 1);
1741   msg->display_edid->edid_supported = edid_supported;
1742   if (!edid_supported)
1743     return GST_WFD_OK;
1744   if (edid_blockcount > 0 && edid_blockcount <= EDID_BLOCK_COUNT_MAX_SIZE) {
1745     msg->display_edid->edid_block_count = edid_blockcount;
1746     msg->display_edid->edid_payload =
1747         g_malloc (EDID_BLOCK_SIZE * edid_blockcount);
1748     if (msg->display_edid->edid_payload)
1749       memcpy (msg->display_edid->edid_payload, edid_playload,
1750           EDID_BLOCK_SIZE * edid_blockcount);
1751     else
1752       msg->display_edid->edid_supported = FALSE;
1753   } else
1754     msg->display_edid->edid_supported = FALSE;
1755
1756   return GST_WFD_OK;
1757 }
1758
1759 GstWFDResult
1760 gst_wfd_message_get_display_edid (GstWFDMessage * msg,
1761     gboolean * edid_supported,
1762     guint32 * edid_blockcount, gchar ** edid_playload)
1763 {
1764   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1765   g_return_val_if_fail (edid_supported != NULL, GST_WFD_EINVAL);
1766   g_return_val_if_fail (edid_blockcount != NULL, GST_WFD_EINVAL);
1767   g_return_val_if_fail (edid_playload != NULL, GST_WFD_EINVAL);
1768
1769   *edid_supported = FALSE;
1770   if (msg->display_edid) {
1771     if (msg->display_edid->edid_supported) {
1772       *edid_blockcount = msg->display_edid->edid_block_count;
1773       if (msg->display_edid->edid_block_count > 0
1774           && msg->display_edid->edid_block_count <= EDID_BLOCK_COUNT_MAX_SIZE) {
1775         char *temp;
1776         temp =
1777             g_malloc0 (EDID_BLOCK_SIZE * msg->display_edid->edid_block_count);
1778         if (temp) {
1779           memcpy (temp, msg->display_edid->edid_payload,
1780               EDID_BLOCK_SIZE * msg->display_edid->edid_block_count);
1781           *edid_playload = temp;
1782           *edid_supported = TRUE;
1783         }
1784       }
1785     }
1786   }
1787   return GST_WFD_OK;
1788 }
1789
1790
1791 GstWFDResult
1792 gst_wfd_message_set_contentprotection_type (GstWFDMessage * msg,
1793     GstWFDHDCPProtection hdcpversion, guint32 TCPPort)
1794 {
1795   char str[11] = { 0, };
1796   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1797   g_return_val_if_fail (TCPPort <= MAX_PORT_SIZE, GST_WFD_EINVAL);
1798
1799   if (!msg->content_protection)
1800     msg->content_protection = g_new0 (GstWFDContentProtection, 1);
1801   if (hdcpversion == GST_WFD_HDCP_NONE)
1802     return GST_WFD_OK;
1803   msg->content_protection->hdcp2_spec = g_new0 (GstWFDHdcp2Spec, 1);
1804   if (hdcpversion == GST_WFD_HDCP_2_0)
1805     msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("HDCP2.0");
1806   else if (hdcpversion == GST_WFD_HDCP_2_1)
1807     msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("HDCP2.1");
1808   snprintf (str, sizeof (str), "port=%d", TCPPort);
1809   msg->content_protection->hdcp2_spec->TCPPort = g_strdup (str);
1810   return GST_WFD_OK;
1811 }
1812
1813 GstWFDResult
1814 gst_wfd_message_get_contentprotection_type (GstWFDMessage * msg,
1815     GstWFDHDCPProtection * hdcpversion, guint32 * TCPPort)
1816 {
1817   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1818   if (msg->content_protection && msg->content_protection->hdcp2_spec) {
1819     char *result = NULL;
1820     char *ptr = NULL;
1821     if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion, "none")) {
1822       *hdcpversion = GST_WFD_HDCP_NONE;
1823       *TCPPort = 0;
1824       return GST_WFD_OK;
1825     }
1826     if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion,
1827             "HDCP2.0"))
1828       *hdcpversion = GST_WFD_HDCP_2_0;
1829     else if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion,
1830             "HDCP2.1"))
1831       *hdcpversion = GST_WFD_HDCP_2_1;
1832     else {
1833       *hdcpversion = GST_WFD_HDCP_NONE;
1834       *TCPPort = 0;
1835       return GST_WFD_OK;
1836     }
1837
1838     if (msg->content_protection->hdcp2_spec->TCPPort) {
1839       result =
1840           strtok_r (msg->content_protection->hdcp2_spec->TCPPort, "=", &ptr);
1841       while (result != NULL && ptr != NULL) {
1842         result = strtok_r (NULL, "=", &ptr);
1843         *TCPPort = atoi (result);
1844         break;
1845       }
1846     } else {
1847       *TCPPort = 0;
1848     }
1849   } else
1850     *hdcpversion = GST_WFD_HDCP_NONE;
1851   return GST_WFD_OK;
1852 }
1853
1854
1855 GstWFDResult
1856 gst_wfd_messge_set_prefered_rtp_ports (GstWFDMessage * msg,
1857     GstWFDRTSPTransMode trans,
1858     GstWFDRTSPProfile profile,
1859     GstWFDRTSPLowerTrans lowertrans, guint32 rtp_port0, guint32 rtp_port1)
1860 {
1861   GString *lines;
1862   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1863
1864   if (!msg->client_rtp_ports)
1865     msg->client_rtp_ports = g_new0 (GstWFDClientRtpPorts, 1);
1866
1867   if (trans != GST_WFD_RTSP_TRANS_UNKNOWN) {
1868     lines = g_string_new ("");
1869     if (trans == GST_WFD_RTSP_TRANS_RTP)
1870       g_string_append_printf (lines, "RTP");
1871     else if (trans == GST_WFD_RTSP_TRANS_RDT)
1872       g_string_append_printf (lines, "RDT");
1873
1874     if (profile == GST_WFD_RTSP_PROFILE_AVP)
1875       g_string_append_printf (lines, "/AVP");
1876     else if (profile == GST_WFD_RTSP_PROFILE_SAVP)
1877       g_string_append_printf (lines, "/SAVP");
1878
1879     if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP)
1880       g_string_append_printf (lines, "/UDP;unicast");
1881     else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST)
1882       g_string_append_printf (lines, "/UDP;multicast");
1883     else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_TCP)
1884       g_string_append_printf (lines, "/TCP;unicast");
1885     else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_HTTP)
1886       g_string_append_printf (lines, "/HTTP");
1887
1888     msg->client_rtp_ports->profile = g_string_free (lines, FALSE);
1889     msg->client_rtp_ports->rtp_port0 = rtp_port0;
1890     msg->client_rtp_ports->rtp_port1 = rtp_port1;
1891     msg->client_rtp_ports->mode = g_strdup ("mode=play");
1892   }
1893   return GST_WFD_OK;
1894 }
1895
1896 GstWFDResult
1897 gst_wfd_message_get_prefered_rtp_ports (GstWFDMessage * msg,
1898     GstWFDRTSPTransMode * trans,
1899     GstWFDRTSPProfile * profile,
1900     GstWFDRTSPLowerTrans * lowertrans, guint32 * rtp_port0, guint32 * rtp_port1)
1901 {
1902   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1903   g_return_val_if_fail (msg->client_rtp_ports != NULL, GST_WFD_EINVAL);
1904
1905   if (g_strrstr (msg->client_rtp_ports->profile, "RTP"))
1906     *trans = GST_WFD_RTSP_TRANS_RTP;
1907   if (g_strrstr (msg->client_rtp_ports->profile, "RDT"))
1908     *trans = GST_WFD_RTSP_TRANS_RDT;
1909   if (g_strrstr (msg->client_rtp_ports->profile, "AVP"))
1910     *profile = GST_WFD_RTSP_PROFILE_AVP;
1911   if (g_strrstr (msg->client_rtp_ports->profile, "SAVP"))
1912     *profile = GST_WFD_RTSP_PROFILE_SAVP;
1913   if (g_strrstr (msg->client_rtp_ports->profile, "UDP;unicast"))
1914     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP;
1915   if (g_strrstr (msg->client_rtp_ports->profile, "UDP;multicast"))
1916     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST;
1917   if (g_strrstr (msg->client_rtp_ports->profile, "TCP;unicast"))
1918     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_TCP;
1919   if (g_strrstr (msg->client_rtp_ports->profile, "HTTP"))
1920     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_HTTP;
1921
1922   *rtp_port0 = msg->client_rtp_ports->rtp_port0;
1923   *rtp_port1 = msg->client_rtp_ports->rtp_port1;
1924
1925   return GST_WFD_OK;
1926 }
1927
1928 GstWFDResult
1929 gst_wfd_message_set_presentation_url (GstWFDMessage * msg, gchar * wfd_url0,
1930     gchar * wfd_url1)
1931 {
1932   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1933
1934   if (!msg->presentation_url)
1935     msg->presentation_url = g_new0 (GstWFDPresentationUrl, 1);
1936   if (wfd_url0)
1937     msg->presentation_url->wfd_url0 = g_strdup (wfd_url0);
1938   if (wfd_url1)
1939     msg->presentation_url->wfd_url1 = g_strdup (wfd_url1);
1940   return GST_WFD_OK;
1941 }
1942
1943 GstWFDResult
1944 gst_wfd_message_get_presentation_url (GstWFDMessage * msg, gchar ** wfd_url0,
1945     gchar ** wfd_url1)
1946 {
1947   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1948
1949   if (msg->presentation_url) {
1950     *wfd_url0 = g_strdup (msg->presentation_url->wfd_url0);
1951     *wfd_url1 = g_strdup (msg->presentation_url->wfd_url1);
1952   }
1953   return GST_WFD_OK;
1954 }
1955
1956 GstWFDResult
1957 gst_wfd_message_set_av_format_change_timing (GstWFDMessage * msg, guint64 PTS,
1958     guint64 DTS)
1959 {
1960   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1961
1962   if (!msg->av_format_change_timing)
1963     msg->av_format_change_timing = g_new0 (GstWFDAVFormatChangeTiming, 1);
1964
1965   msg->av_format_change_timing->PTS = PTS;
1966   msg->av_format_change_timing->DTS = DTS;
1967   return GST_WFD_OK;
1968 }
1969
1970 GstWFDResult
1971 gst_wfd_message_get_av_format_change_timing (GstWFDMessage * msg, guint64 * PTS,
1972     guint64 * DTS)
1973 {
1974   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1975   g_return_val_if_fail (PTS != NULL, GST_WFD_EINVAL);
1976   g_return_val_if_fail (DTS != NULL, GST_WFD_EINVAL);
1977
1978   if (msg->av_format_change_timing) {
1979     *PTS = msg->av_format_change_timing->PTS;
1980     *DTS = msg->av_format_change_timing->DTS;
1981   }
1982
1983   return GST_WFD_OK;
1984 }