fc81a9ce57a266fb80e7a217edca3acc9f830e47
[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->
477           list->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.
484           misc_params.CEA_Support);
485       WFD_SKIP_SPACE (v);
486       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.
487           misc_params.VESA_Support);
488       WFD_SKIP_SPACE (v);
489       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.
490           misc_params.HH_Support);
491       WFD_SKIP_SPACE (v);
492       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.
493           misc_params.latency);
494       WFD_SKIP_SPACE (v);
495       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.
496           misc_params.min_slice_size);
497       WFD_SKIP_SPACE (v);
498       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.
499           misc_params.slice_enc_params);
500       WFD_SKIP_SPACE (v);
501       WFD_READ_UINT32 (msg->video_formats->list->H264_codec.
502           misc_params.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->
520           list->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.
527           misc_params.video_3d_capability);
528       WFD_SKIP_SPACE (v);
529       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.
530           misc_params.latency);
531       WFD_SKIP_SPACE (v);
532       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.
533           misc_params.min_slice_size);
534       WFD_SKIP_SPACE (v);
535       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.
536           misc_params.slice_enc_params);
537       WFD_SKIP_SPACE (v);
538       WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.
539           misc_params.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.
698             misc_params.CEA_Support);
699         WFD_SKIP_SPACE (v);
700         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.
701             misc_params.VESA_Support);
702         WFD_SKIP_SPACE (v);
703         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.
704             misc_params.HH_Support);
705         WFD_SKIP_SPACE (v);
706         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.
707             misc_params.latency);
708         WFD_SKIP_SPACE (v);
709         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.
710             misc_params.min_slice_size);
711         WFD_SKIP_SPACE (v);
712         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.
713             misc_params.slice_enc_params);
714         WFD_SKIP_SPACE (v);
715         WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.
716             misc_params.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.
880           misc_params.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.
912           misc_params.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.
921           misc_params.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", msg->display_edid->edid_block_count);
963         g_string_append_printf(lines, " %s", msg->display_edid->edid_payload);
964       } else
965         g_string_append_printf (lines, " none");
966     } else {
967       g_string_append_printf (lines, " none");
968     }
969     g_string_append_printf (lines, "\r\n");
970   }
971
972   if (msg->coupled_sink) {
973     g_string_append_printf (lines, GST_STRING_WFD_COUPLED_SINK);
974     g_string_append_printf (lines, ":");
975     if (msg->coupled_sink->coupled_sink_cap) {
976       g_string_append_printf (lines, " %02x",
977           msg->coupled_sink->coupled_sink_cap->status);
978       if (msg->coupled_sink->coupled_sink_cap->sink_address)
979         g_string_append_printf (lines, " %s",
980             msg->coupled_sink->coupled_sink_cap->sink_address);
981       else
982         g_string_append_printf (lines, " none");
983     } else {
984       g_string_append_printf (lines, " none");
985     }
986     g_string_append_printf (lines, "\r\n");
987   }
988
989   if (msg->trigger_method) {
990     g_string_append_printf (lines, GST_STRING_WFD_TRIGGER_METHOD);
991     g_string_append_printf (lines, ":");
992     g_string_append_printf (lines, " %s",
993         msg->trigger_method->wfd_trigger_method);
994     g_string_append_printf (lines, "\r\n");
995   }
996
997   if (msg->presentation_url) {
998     g_string_append_printf (lines, GST_STRING_WFD_PRESENTATION_URL);
999     g_string_append_printf (lines, ":");
1000     if (msg->presentation_url->wfd_url0)
1001       g_string_append_printf (lines, " %s", msg->presentation_url->wfd_url0);
1002     else
1003       g_string_append_printf (lines, " none");
1004     if (msg->presentation_url->wfd_url1)
1005       g_string_append_printf (lines, " %s", msg->presentation_url->wfd_url1);
1006     else
1007       g_string_append_printf (lines, " none");
1008     g_string_append_printf (lines, "\r\n");
1009   }
1010
1011   if (msg->client_rtp_ports) {
1012     g_string_append_printf (lines, GST_STRING_WFD_CLIENT_RTP_PORTS);
1013     if (msg->client_rtp_ports->profile) {
1014       g_string_append_printf (lines, ":");
1015       g_string_append_printf (lines, " %s", msg->client_rtp_ports->profile);
1016       g_string_append_printf (lines, " %d", msg->client_rtp_ports->rtp_port0);
1017       g_string_append_printf (lines, " %d", msg->client_rtp_ports->rtp_port1);
1018       g_string_append_printf (lines, " %s", msg->client_rtp_ports->mode);
1019     }
1020     g_string_append_printf (lines, "\r\n");
1021   }
1022
1023   if (msg->route) {
1024     g_string_append_printf (lines, GST_STRING_WFD_ROUTE);
1025     g_string_append_printf (lines, ":");
1026     g_string_append_printf (lines, " %s", msg->route->destination);
1027     g_string_append_printf (lines, "\r\n");
1028   }
1029
1030   if (msg->I2C) {
1031     g_string_append_printf (lines, GST_STRING_WFD_I2C);
1032     g_string_append_printf (lines, ":");
1033     if (msg->I2C->I2CPresent)
1034       g_string_append_printf (lines, " %x", msg->I2C->I2C_port);
1035     else
1036       g_string_append_printf (lines, " none");
1037     g_string_append_printf (lines, "\r\n");
1038   }
1039
1040   if (msg->av_format_change_timing) {
1041     g_string_append_printf (lines, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING);
1042     g_string_append_printf (lines, ":");
1043     g_string_append_printf (lines, " %010llx",
1044         msg->av_format_change_timing->PTS);
1045     g_string_append_printf (lines, " %010llx",
1046         msg->av_format_change_timing->DTS);
1047     g_string_append_printf (lines, "\r\n");
1048   }
1049
1050   if (msg->preferred_display_mode) {
1051     g_string_append_printf (lines, GST_STRING_WFD_PREFERRED_DISPLAY_MODE);
1052     g_string_append_printf (lines, ":");
1053     if (msg->preferred_display_mode->displaymodesupported) {
1054       g_string_append_printf (lines, " %06llx",
1055           msg->preferred_display_mode->p_clock);
1056       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->H);
1057       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->HB);
1058       g_string_append_printf (lines, " %04x",
1059           msg->preferred_display_mode->HSPOL_HSOFF);
1060       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->HSW);
1061       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->V);
1062       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->VB);
1063       g_string_append_printf (lines, " %04x",
1064           msg->preferred_display_mode->VSPOL_VSOFF);
1065       g_string_append_printf (lines, " %04x", msg->preferred_display_mode->VSW);
1066       g_string_append_printf (lines, " %02x",
1067           msg->preferred_display_mode->VBS3D);
1068       g_string_append_printf (lines, " %02x",
1069           msg->preferred_display_mode->V2d_s3d_modes);
1070       g_string_append_printf (lines, " %02x",
1071           msg->preferred_display_mode->P_depth);
1072     } else
1073       g_string_append_printf (lines, " none");
1074     g_string_append_printf (lines, "\r\n");
1075   }
1076
1077   if (msg->standby_resume_capability) {
1078     g_string_append_printf (lines, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY);
1079     g_string_append_printf (lines, ":");
1080     if (msg->standby_resume_capability->standby_resume_cap)
1081       g_string_append_printf (lines, " supported");
1082     else
1083       g_string_append_printf (lines, " none");
1084     g_string_append_printf (lines, "\r\n");
1085   }
1086
1087   if (msg->standby) {
1088     g_string_append_printf (lines, GST_STRING_WFD_STANDBY);
1089     g_string_append_printf (lines, "\r\n");
1090   }
1091
1092   if (msg->connector_type) {
1093     g_string_append_printf (lines, GST_STRING_WFD_CONNECTOR_TYPE);
1094     g_string_append_printf (lines, ":");
1095     if (msg->connector_type->connector_type)
1096       g_string_append_printf (lines, " %02x",
1097           msg->connector_type->connector_type);
1098     else
1099       g_string_append_printf (lines, " none");
1100     g_string_append_printf (lines, "\r\n");
1101   }
1102
1103   if (msg->idr_request) {
1104     g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST);
1105     g_string_append_printf (lines, "\r\n");
1106   }
1107
1108   return g_string_free (lines, FALSE);
1109 }
1110
1111 gchar *
1112 gst_wfd_message_param_names_as_text (const GstWFDMessage * msg)
1113 {
1114   /* change all vars so they match rfc? */
1115   GString *lines;
1116   g_return_val_if_fail (msg != NULL, NULL);
1117
1118   lines = g_string_new ("");
1119
1120   /* list of audio codecs */
1121   if (msg->audio_codecs) {
1122     g_string_append_printf (lines, GST_STRING_WFD_AUDIO_CODECS);
1123     g_string_append_printf (lines, "\r\n");
1124   }
1125   /* list of video codecs */
1126   if (msg->video_formats) {
1127     g_string_append_printf (lines, GST_STRING_WFD_VIDEO_FORMATS);
1128     g_string_append_printf (lines, "\r\n");
1129   }
1130   /* list of video 3D codecs */
1131   if (msg->video_3d_formats) {
1132     g_string_append_printf (lines, GST_STRING_WFD_3D_VIDEO_FORMATS);
1133     g_string_append_printf (lines, "\r\n");
1134   }
1135   if (msg->content_protection) {
1136     g_string_append_printf (lines, GST_STRING_WFD_CONTENT_PROTECTION);
1137     g_string_append_printf (lines, "\r\n");
1138   }
1139   if (msg->display_edid) {
1140     g_string_append_printf (lines, GST_STRING_WFD_DISPLAY_EDID);
1141     g_string_append_printf (lines, "\r\n");
1142   }
1143   if (msg->coupled_sink) {
1144     g_string_append_printf (lines, GST_STRING_WFD_COUPLED_SINK);
1145     g_string_append_printf (lines, "\r\n");
1146   }
1147   if (msg->trigger_method) {
1148     g_string_append_printf (lines, GST_STRING_WFD_TRIGGER_METHOD);
1149     g_string_append_printf (lines, "\r\n");
1150   }
1151   if (msg->presentation_url) {
1152     g_string_append_printf (lines, GST_STRING_WFD_PRESENTATION_URL);
1153     g_string_append_printf (lines, "\r\n");
1154   }
1155   if (msg->client_rtp_ports) {
1156     g_string_append_printf (lines, GST_STRING_WFD_CLIENT_RTP_PORTS);
1157     g_string_append_printf (lines, "\r\n");
1158   }
1159   if (msg->route) {
1160     g_string_append_printf (lines, GST_STRING_WFD_ROUTE);
1161     g_string_append_printf (lines, "\r\n");
1162   }
1163   if (msg->I2C) {
1164     g_string_append_printf (lines, GST_STRING_WFD_I2C);
1165     g_string_append_printf (lines, "\r\n");
1166   }
1167   if (msg->av_format_change_timing) {
1168     g_string_append_printf (lines, GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING);
1169     g_string_append_printf (lines, "\r\n");
1170   }
1171   if (msg->preferred_display_mode) {
1172     g_string_append_printf (lines, GST_STRING_WFD_PREFERRED_DISPLAY_MODE);
1173     g_string_append_printf (lines, "\r\n");
1174   }
1175   if (msg->standby_resume_capability) {
1176     g_string_append_printf (lines, GST_STRING_WFD_STANDBY_RESUME_CAPABILITY);
1177     g_string_append_printf (lines, "\r\n");
1178   }
1179   if (msg->standby) {
1180     g_string_append_printf (lines, GST_STRING_WFD_STANDBY);
1181     g_string_append_printf (lines, "\r\n");
1182   }
1183   if (msg->connector_type) {
1184     g_string_append_printf (lines, GST_STRING_WFD_CONNECTOR_TYPE);
1185     g_string_append_printf (lines, "\r\n");
1186   }
1187   if (msg->idr_request) {
1188     g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST);
1189     g_string_append_printf (lines, "\r\n");
1190   }
1191
1192   return g_string_free (lines, FALSE);
1193 }
1194
1195 /**
1196  * gst_wfd_message_dump:
1197  * @msg: a #GstWFDMessage
1198  *
1199  * Dump the parsed contents of @msg to stdout.
1200  *
1201  * Returns: a #GstWFDResult.
1202  */
1203 GstWFDResult
1204 gst_wfd_message_dump (const GstWFDMessage * msg)
1205 {
1206   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1207
1208   if (msg->audio_codecs) {
1209     guint i = 0;
1210     g_print ("Audio supported formats : \n");
1211     for (; i < msg->audio_codecs->count; i++) {
1212       g_print ("Codec: %s\n", msg->audio_codecs->list[i].audio_format);
1213       if (!strcmp (msg->audio_codecs->list[i].audio_format, "LPCM")) {
1214         if (msg->audio_codecs->list[i].modes & GST_WFD_FREQ_44100)
1215           g_print ("    Freq: %d\n", 44100);
1216         if (msg->audio_codecs->list[i].modes & GST_WFD_FREQ_48000)
1217           g_print ("    Freq: %d\n", 48000);
1218         g_print ("      Channels: %d\n", 2);
1219       }
1220       if (!strcmp (msg->audio_codecs->list[i].audio_format, "AAC")) {
1221         g_print ("      Freq: %d\n", 48000);
1222         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_2)
1223           g_print ("    Channels: %d\n", 2);
1224         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_4)
1225           g_print ("    Channels: %d\n", 4);
1226         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_6)
1227           g_print ("    Channels: %d\n", 6);
1228         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_8)
1229           g_print ("    Channels: %d\n", 8);
1230       }
1231       if (!strcmp (msg->audio_codecs->list[i].audio_format, "AC3")) {
1232         g_print ("      Freq: %d\n", 48000);
1233         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_2)
1234           g_print ("    Channels: %d\n", 2);
1235         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_4)
1236           g_print ("    Channels: %d\n", 4);
1237         if (msg->audio_codecs->list[i].modes & GST_WFD_CHANNEL_6)
1238           g_print ("    Channels: %d\n", 6);
1239       }
1240       g_print ("        Bitwidth: %d\n", 16);
1241       g_print ("        Latency: %d\n", msg->audio_codecs->list[i].latency);
1242     }
1243   }
1244
1245
1246   if (msg->video_formats) {
1247     g_print ("Video supported formats : \n");
1248     if (msg->video_formats->list) {
1249       guint nativeindex = 0;
1250       g_print ("Codec: H264\n");
1251       if ((msg->video_formats->list->native & 0x7) ==
1252           GST_WFD_VIDEO_CEA_RESOLUTION) {
1253         g_print ("      Native type: CEA\n");
1254       } else if ((msg->video_formats->list->native & 0x7) ==
1255           GST_WFD_VIDEO_VESA_RESOLUTION) {
1256         g_print ("      Native type: VESA\n");
1257       } else if ((msg->video_formats->list->native & 0x7) ==
1258           GST_WFD_VIDEO_HH_RESOLUTION) {
1259         g_print ("      Native type: HH\n");
1260       }
1261       nativeindex = msg->video_formats->list->native >> 3;
1262       g_print ("        Resolution: %d\n", (1 << nativeindex));
1263
1264       if (msg->video_formats->list->
1265           H264_codec.profile & GST_WFD_H264_BASE_PROFILE) {
1266         g_print ("      Profile: BASE\n");
1267       } else if (msg->video_formats->list->
1268           H264_codec.profile & GST_WFD_H264_HIGH_PROFILE) {
1269         g_print ("      Profile: HIGH\n");
1270       }
1271       if (msg->video_formats->list->H264_codec.level & GST_WFD_H264_LEVEL_3_1) {
1272         g_print ("      Level: 3.1\n");
1273       } else if (msg->video_formats->list->
1274           H264_codec.level & GST_WFD_H264_LEVEL_3_2) {
1275         g_print ("      Level: 3.2\n");
1276       } else if (msg->video_formats->list->
1277           H264_codec.level & GST_WFD_H264_LEVEL_4) {
1278         g_print ("      Level: 4\n");
1279       } else if (msg->video_formats->list->
1280           H264_codec.level & GST_WFD_H264_LEVEL_4_1) {
1281         g_print ("      Level: 4.1\n");
1282       } else if (msg->video_formats->list->
1283           H264_codec.level & GST_WFD_H264_LEVEL_4_2) {
1284         g_print ("      Level: 4.2\n");
1285       }
1286       g_print ("        Latency: %d\n",
1287           msg->video_formats->list->H264_codec.misc_params.latency);
1288       g_print ("        min_slice_size: %x\n",
1289           msg->video_formats->list->H264_codec.misc_params.min_slice_size);
1290       g_print ("        slice_enc_params: %x\n",
1291           msg->video_formats->list->H264_codec.misc_params.slice_enc_params);
1292       g_print ("        frame_rate_control_support: %x\n",
1293           msg->video_formats->list->H264_codec.
1294           misc_params.frame_rate_control_support);
1295       if (msg->video_formats->list->H264_codec.max_hres) {
1296         g_print ("      Max Height: %04d\n",
1297             msg->video_formats->list->H264_codec.max_hres);
1298       }
1299       if (msg->video_formats->list->H264_codec.max_vres) {
1300         g_print ("      Max Width: %04d\n",
1301             msg->video_formats->list->H264_codec.max_vres);
1302       }
1303     }
1304   }
1305
1306   if (msg->video_3d_formats) {
1307     g_print ("wfd_3d_formats");
1308     g_print ("\r\n");
1309   }
1310
1311   if (msg->content_protection) {
1312     g_print (GST_STRING_WFD_CONTENT_PROTECTION);
1313     g_print ("\r\n");
1314   }
1315
1316   if (msg->display_edid) {
1317     g_print (GST_STRING_WFD_DISPLAY_EDID);
1318     g_print ("\r\n");
1319   }
1320
1321   if (msg->coupled_sink) {
1322     g_print (GST_STRING_WFD_COUPLED_SINK);
1323     g_print ("\r\n");
1324   }
1325
1326   if (msg->trigger_method) {
1327     g_print ("  Trigger type: %s\n", msg->trigger_method->wfd_trigger_method);
1328   }
1329
1330   if (msg->presentation_url) {
1331     g_print (GST_STRING_WFD_PRESENTATION_URL);
1332     g_print ("\r\n");
1333   }
1334
1335   if (msg->client_rtp_ports) {
1336     g_print (" Client RTP Ports : \n");
1337     if (msg->client_rtp_ports->profile) {
1338       g_print ("%s\n", msg->client_rtp_ports->profile);
1339       g_print ("        %d\n", msg->client_rtp_ports->rtp_port0);
1340       g_print ("        %d\n", msg->client_rtp_ports->rtp_port1);
1341       g_print ("        %s\n", msg->client_rtp_ports->mode);
1342     }
1343     g_print ("\r\n");
1344   }
1345
1346   if (msg->route) {
1347     g_print (GST_STRING_WFD_ROUTE);
1348     g_print ("\r\n");
1349   }
1350
1351   if (msg->I2C) {
1352     g_print (GST_STRING_WFD_I2C);
1353     g_print ("\r\n");
1354   }
1355
1356   if (msg->av_format_change_timing) {
1357     g_print (GST_STRING_WFD_AV_FORMAT_CHANGE_TIMING);
1358     g_print ("\r\n");
1359   }
1360
1361   if (msg->preferred_display_mode) {
1362     g_print (GST_STRING_WFD_PREFERRED_DISPLAY_MODE);
1363     g_print ("\r\n");
1364   }
1365
1366   if (msg->standby_resume_capability) {
1367     g_print (GST_STRING_WFD_STANDBY_RESUME_CAPABILITY);
1368     g_print ("\r\n");
1369   }
1370
1371   if (msg->standby) {
1372     g_print (GST_STRING_WFD_STANDBY);
1373     g_print ("\r\n");
1374   }
1375
1376   if (msg->connector_type) {
1377     g_print (GST_STRING_WFD_CONNECTOR_TYPE);
1378     g_print ("\r\n");
1379   }
1380
1381   if (msg->idr_request) {
1382     g_print (GST_STRING_WFD_IDR_REQUEST);
1383     g_print ("\r\n");
1384   }
1385
1386   return GST_WFD_OK;
1387 }
1388
1389 GstWFDResult
1390 gst_wfd_message_set_supported_audio_format (GstWFDMessage * msg,
1391     GstWFDAudioFormats a_codec,
1392     guint a_freq, guint a_channels, guint a_bitwidth, guint32 a_latency)
1393 {
1394   guint i = 0;
1395   guint pcm = 0, aac = 0, ac3 = 0;
1396
1397   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1398
1399   if (!msg->audio_codecs)
1400     msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1);
1401
1402   if (a_codec != GST_WFD_AUDIO_UNKNOWN) {
1403
1404     if (a_codec & GST_WFD_AUDIO_LPCM)
1405       msg->audio_codecs->count++;
1406     if (a_codec & GST_WFD_AUDIO_AAC)
1407       msg->audio_codecs->count++;
1408     if (a_codec & GST_WFD_AUDIO_AC3)
1409       msg->audio_codecs->count++;
1410
1411     msg->audio_codecs->list =
1412         g_new0 (GstWFDAudioCodec, msg->audio_codecs->count);
1413     for (; i < msg->audio_codecs->count; i++) {
1414       if ((a_codec & GST_WFD_AUDIO_LPCM) && (!pcm)) {
1415         msg->audio_codecs->list[i].audio_format = g_strdup ("LPCM");
1416         msg->audio_codecs->list[i].modes = a_freq;
1417         msg->audio_codecs->list[i].latency = a_latency;
1418         pcm = 1;
1419       } else if ((a_codec & GST_WFD_AUDIO_AAC) && (!aac)) {
1420         msg->audio_codecs->list[i].audio_format = g_strdup ("AAC");
1421         msg->audio_codecs->list[i].modes = a_channels;
1422         msg->audio_codecs->list[i].latency = a_latency;
1423         aac = 1;
1424       } else if ((a_codec & GST_WFD_AUDIO_AC3) && (!ac3)) {
1425         msg->audio_codecs->list[i].audio_format = g_strdup ("AC3");
1426         msg->audio_codecs->list[i].modes = a_channels;
1427         msg->audio_codecs->list[i].latency = a_latency;
1428         ac3 = 1;
1429       }
1430     }
1431   }
1432   return GST_WFD_OK;
1433 }
1434
1435 GstWFDResult
1436 gst_wfd_message_set_prefered_audio_format (GstWFDMessage * msg,
1437     GstWFDAudioFormats a_codec,
1438     GstWFDAudioFreq a_freq,
1439     GstWFDAudioChannels a_channels, guint a_bitwidth, guint32 a_latency)
1440 {
1441   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1442
1443   if (!msg->audio_codecs)
1444     msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1);
1445
1446   msg->audio_codecs->list = g_new0 (GstWFDAudioCodec, 1);
1447   msg->audio_codecs->count = 1;
1448   if (a_codec == GST_WFD_AUDIO_LPCM) {
1449     msg->audio_codecs->list->audio_format = g_strdup ("LPCM");
1450     msg->audio_codecs->list->modes = a_freq;
1451     msg->audio_codecs->list->latency = a_latency;
1452   } else if (a_codec == GST_WFD_AUDIO_AAC) {
1453     msg->audio_codecs->list->audio_format = g_strdup ("AAC");
1454     msg->audio_codecs->list->modes = a_channels;
1455     msg->audio_codecs->list->latency = a_latency;
1456   } else if (a_codec == GST_WFD_AUDIO_AC3) {
1457     msg->audio_codecs->list->audio_format = g_strdup ("AC3");
1458     msg->audio_codecs->list->modes = a_channels;
1459     msg->audio_codecs->list->latency = a_latency;
1460   }
1461   return GST_WFD_OK;
1462 }
1463
1464 GstWFDResult
1465 gst_wfd_message_get_supported_audio_format (GstWFDMessage * msg,
1466     guint * a_codec,
1467     guint * a_freq, guint * a_channels, guint * a_bitwidth, guint32 * a_latency)
1468 {
1469   guint i = 0;
1470   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1471   g_return_val_if_fail (msg->audio_codecs != NULL, GST_WFD_EINVAL);
1472
1473   for (; i < msg->audio_codecs->count; i++) {
1474     if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "LPCM")) {
1475       *a_codec |= GST_WFD_AUDIO_LPCM;
1476       *a_freq |= msg->audio_codecs->list[i].modes;
1477       *a_channels |= GST_WFD_CHANNEL_2;
1478       *a_bitwidth = 16;
1479       *a_latency = msg->audio_codecs->list[i].latency;
1480     } else if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "AAC")) {
1481       *a_codec |= GST_WFD_AUDIO_AAC;
1482       *a_freq |= GST_WFD_FREQ_48000;
1483       *a_channels |= msg->audio_codecs->list[i].modes;
1484       *a_bitwidth = 16;
1485       *a_latency = msg->audio_codecs->list[i].latency;
1486     } else if (!g_strcmp0 (msg->audio_codecs->list[i].audio_format, "AC3")) {
1487       *a_codec |= GST_WFD_AUDIO_AC3;
1488       *a_freq |= GST_WFD_FREQ_48000;
1489       *a_channels |= msg->audio_codecs->list[i].modes;
1490       *a_bitwidth = 16;
1491       *a_latency = msg->audio_codecs->list[i].latency;
1492     }
1493   }
1494   return GST_WFD_OK;
1495 }
1496
1497 GstWFDResult
1498 gst_wfd_message_get_prefered_audio_format (GstWFDMessage * msg,
1499     GstWFDAudioFormats * a_codec,
1500     GstWFDAudioFreq * a_freq,
1501     GstWFDAudioChannels * a_channels, guint * a_bitwidth, guint32 * a_latency)
1502 {
1503   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1504
1505   if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "LPCM")) {
1506     *a_codec = GST_WFD_AUDIO_LPCM;
1507     *a_freq = msg->audio_codecs->list->modes;
1508     *a_channels = GST_WFD_CHANNEL_2;
1509     *a_bitwidth = 16;
1510     *a_latency = msg->audio_codecs->list->latency;
1511   } else if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "AAC")) {
1512     *a_codec = GST_WFD_AUDIO_AAC;
1513     *a_freq = GST_WFD_FREQ_48000;
1514     *a_channels = msg->audio_codecs->list->modes;
1515     *a_bitwidth = 16;
1516     *a_latency = msg->audio_codecs->list->latency;
1517   } else if (!g_strcmp0 (msg->audio_codecs->list->audio_format, "AC3")) {
1518     *a_codec = GST_WFD_AUDIO_AC3;
1519     *a_freq = GST_WFD_FREQ_48000;
1520     *a_channels = msg->audio_codecs->list->modes;
1521     *a_bitwidth = 16;
1522     *a_latency = msg->audio_codecs->list->latency;
1523   }
1524   return GST_WFD_OK;
1525 }
1526
1527 GstWFDResult
1528 gst_wfd_message_set_supported_video_format (GstWFDMessage * msg,
1529     GstWFDVideoCodecs v_codec,
1530     GstWFDVideoNativeResolution v_native,
1531     guint64 v_native_resolution,
1532     guint64 v_cea_resolution,
1533     guint64 v_vesa_resolution,
1534     guint64 v_hh_resolution,
1535     guint v_profile,
1536     guint v_level,
1537     guint32 v_latency,
1538     guint32 v_max_height,
1539     guint32 v_max_width,
1540     guint32 min_slice_size, guint32 slice_enc_params, guint frame_rate_control)
1541 {
1542   guint nativeindex = 0;
1543   guint64 temp = v_native_resolution;
1544
1545   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1546
1547   if (!msg->video_formats)
1548     msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1);
1549
1550   if (v_codec != GST_WFD_VIDEO_UNKNOWN) {
1551     msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1);
1552     while (temp) {
1553       nativeindex++;
1554       temp >>= 1;
1555     }
1556
1557     msg->video_formats->list->native = nativeindex - 1;
1558     msg->video_formats->list->native <<= 3;
1559
1560     if (v_native == GST_WFD_VIDEO_VESA_RESOLUTION)
1561       msg->video_formats->list->native |= 1;
1562     else if (v_native == GST_WFD_VIDEO_HH_RESOLUTION)
1563       msg->video_formats->list->native |= 2;
1564
1565     msg->video_formats->list->preferred_display_mode_supported = 1;
1566     msg->video_formats->list->H264_codec.profile = v_profile;
1567     msg->video_formats->list->H264_codec.level = v_level;
1568     msg->video_formats->list->H264_codec.max_hres = v_max_height;
1569     msg->video_formats->list->H264_codec.max_vres = v_max_width;
1570     msg->video_formats->list->H264_codec.misc_params.CEA_Support =
1571         v_cea_resolution;
1572     msg->video_formats->list->H264_codec.misc_params.VESA_Support =
1573         v_vesa_resolution;
1574     msg->video_formats->list->H264_codec.misc_params.HH_Support =
1575         v_hh_resolution;
1576     msg->video_formats->list->H264_codec.misc_params.latency = v_latency;
1577     msg->video_formats->list->H264_codec.misc_params.min_slice_size =
1578         min_slice_size;
1579     msg->video_formats->list->H264_codec.misc_params.slice_enc_params =
1580         slice_enc_params;
1581     msg->video_formats->list->H264_codec.
1582         misc_params.frame_rate_control_support = frame_rate_control;
1583   }
1584   return GST_WFD_OK;
1585 }
1586
1587 GstWFDResult
1588 gst_wfd_message_set_prefered_video_format (GstWFDMessage * msg,
1589     GstWFDVideoCodecs v_codec,
1590     GstWFDVideoNativeResolution v_native,
1591     guint64 v_native_resolution,
1592     GstWFDVideoCEAResolution v_cea_resolution,
1593     GstWFDVideoVESAResolution v_vesa_resolution,
1594     GstWFDVideoHHResolution v_hh_resolution,
1595     GstWFDVideoH264Profile v_profile,
1596     GstWFDVideoH264Level v_level,
1597     guint32 v_latency,
1598     guint32 v_max_height,
1599     guint32 v_max_width,
1600     guint32 min_slice_size, guint32 slice_enc_params, guint frame_rate_control)
1601 {
1602   guint nativeindex = 0;
1603   guint64 temp = v_native_resolution;
1604
1605   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1606
1607   if (!msg->video_formats)
1608     msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1);
1609   msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1);
1610
1611   while (temp) {
1612     nativeindex++;
1613     temp >>= 1;
1614   }
1615
1616   if (nativeindex)
1617     msg->video_formats->list->native = nativeindex - 1;
1618   msg->video_formats->list->native <<= 3;
1619
1620   if (v_native == GST_WFD_VIDEO_VESA_RESOLUTION)
1621     msg->video_formats->list->native |= 1;
1622   else if (v_native == GST_WFD_VIDEO_HH_RESOLUTION)
1623     msg->video_formats->list->native |= 2;
1624
1625   msg->video_formats->list->preferred_display_mode_supported = 0;
1626   msg->video_formats->list->H264_codec.profile = v_profile;
1627   msg->video_formats->list->H264_codec.level = v_level;
1628   msg->video_formats->list->H264_codec.max_hres = v_max_height;
1629   msg->video_formats->list->H264_codec.max_vres = v_max_width;
1630   msg->video_formats->list->H264_codec.misc_params.CEA_Support =
1631       v_cea_resolution;
1632   msg->video_formats->list->H264_codec.misc_params.VESA_Support =
1633       v_vesa_resolution;
1634   msg->video_formats->list->H264_codec.misc_params.HH_Support = v_hh_resolution;
1635   msg->video_formats->list->H264_codec.misc_params.latency = v_latency;
1636   msg->video_formats->list->H264_codec.misc_params.min_slice_size =
1637       min_slice_size;
1638   msg->video_formats->list->H264_codec.misc_params.slice_enc_params =
1639       slice_enc_params;
1640   msg->video_formats->list->H264_codec.misc_params.frame_rate_control_support =
1641       frame_rate_control;
1642   return GST_WFD_OK;
1643 }
1644
1645 GstWFDResult
1646 gst_wfd_message_get_supported_video_format (GstWFDMessage * msg,
1647     GstWFDVideoCodecs * v_codec,
1648     GstWFDVideoNativeResolution * v_native,
1649     guint64 * v_native_resolution,
1650     guint64 * v_cea_resolution,
1651     guint64 * v_vesa_resolution,
1652     guint64 * v_hh_resolution,
1653     guint * v_profile,
1654     guint * v_level,
1655     guint32 * v_latency,
1656     guint32 * v_max_height,
1657     guint32 * v_max_width,
1658     guint32 * min_slice_size,
1659     guint32 * slice_enc_params, guint * frame_rate_control)
1660 {
1661   guint nativeindex = 0;
1662
1663   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1664   *v_codec = GST_WFD_VIDEO_H264;
1665   *v_native = msg->video_formats->list->native & 0x7;
1666   nativeindex = msg->video_formats->list->native >> 3;
1667   *v_native_resolution = ((guint64) 1) << nativeindex;
1668   *v_profile = msg->video_formats->list->H264_codec.profile;
1669   *v_level = msg->video_formats->list->H264_codec.level;
1670   *v_max_height = msg->video_formats->list->H264_codec.max_hres;
1671   *v_max_width = msg->video_formats->list->H264_codec.max_vres;
1672   *v_cea_resolution =
1673       msg->video_formats->list->H264_codec.misc_params.CEA_Support;
1674   *v_vesa_resolution =
1675       msg->video_formats->list->H264_codec.misc_params.VESA_Support;
1676   *v_hh_resolution =
1677       msg->video_formats->list->H264_codec.misc_params.HH_Support;
1678   *v_latency = msg->video_formats->list->H264_codec.misc_params.latency;
1679   *min_slice_size =
1680       msg->video_formats->list->H264_codec.misc_params.min_slice_size;
1681   *slice_enc_params =
1682       msg->video_formats->list->H264_codec.misc_params.slice_enc_params;
1683   *frame_rate_control =
1684       msg->video_formats->list->H264_codec.
1685       misc_params.frame_rate_control_support;
1686   return GST_WFD_OK;
1687 }
1688
1689 GstWFDResult
1690 gst_wfd_message_get_prefered_video_format (GstWFDMessage * msg,
1691     GstWFDVideoCodecs * v_codec,
1692     GstWFDVideoNativeResolution * v_native,
1693     guint64 * v_native_resolution,
1694     GstWFDVideoCEAResolution * v_cea_resolution,
1695     GstWFDVideoVESAResolution * v_vesa_resolution,
1696     GstWFDVideoHHResolution * v_hh_resolution,
1697     GstWFDVideoH264Profile * v_profile,
1698     GstWFDVideoH264Level * v_level,
1699     guint32 * v_latency,
1700     guint32 * v_max_height,
1701     guint32 * v_max_width,
1702     guint32 * min_slice_size,
1703     guint32 * slice_enc_params, guint * frame_rate_control)
1704 {
1705   guint nativeindex = 0;
1706   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1707
1708   *v_codec = GST_WFD_VIDEO_H264;
1709   *v_native = msg->video_formats->list->native & 0x7;
1710   nativeindex = msg->video_formats->list->native >> 3;
1711   *v_native_resolution = ((guint64) 1) << nativeindex;
1712   *v_profile = msg->video_formats->list->H264_codec.profile;
1713   *v_level = msg->video_formats->list->H264_codec.level;
1714   *v_max_height = msg->video_formats->list->H264_codec.max_hres;
1715   *v_max_width = msg->video_formats->list->H264_codec.max_vres;
1716   *v_cea_resolution =
1717       msg->video_formats->list->H264_codec.misc_params.CEA_Support;
1718   *v_vesa_resolution =
1719       msg->video_formats->list->H264_codec.misc_params.VESA_Support;
1720   *v_hh_resolution =
1721       msg->video_formats->list->H264_codec.misc_params.HH_Support;
1722   *v_latency = msg->video_formats->list->H264_codec.misc_params.latency;
1723   *min_slice_size =
1724       msg->video_formats->list->H264_codec.misc_params.min_slice_size;
1725   *slice_enc_params =
1726       msg->video_formats->list->H264_codec.misc_params.slice_enc_params;
1727   *frame_rate_control =
1728       msg->video_formats->list->H264_codec.
1729       misc_params.frame_rate_control_support;
1730   return GST_WFD_OK;
1731 }
1732
1733 GstWFDResult
1734 gst_wfd_message_set_display_edid (GstWFDMessage * msg,
1735     gboolean edid_supported, guint32 edid_blockcount, gchar * edid_playload)
1736 {
1737   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1738   if (!msg->display_edid)
1739     msg->display_edid = g_new0 (GstWFDDisplayEdid, 1);
1740   msg->display_edid->edid_supported = edid_supported;
1741   if (!edid_supported)
1742     return GST_WFD_OK;
1743   if (edid_blockcount > 0 && edid_blockcount <= EDID_BLOCK_COUNT_MAX_SIZE) {
1744     msg->display_edid->edid_block_count = edid_blockcount;
1745     msg->display_edid->edid_payload = g_malloc(EDID_BLOCK_SIZE * edid_blockcount);
1746     if (msg->display_edid->edid_payload)
1747       memcpy(msg->display_edid->edid_payload, edid_playload, EDID_BLOCK_SIZE * edid_blockcount);
1748     else
1749       msg->display_edid->edid_supported = FALSE;
1750   } else
1751     msg->display_edid->edid_supported = FALSE;
1752
1753   return GST_WFD_OK;
1754 }
1755
1756 GstWFDResult
1757 gst_wfd_message_get_display_edid (GstWFDMessage * msg,
1758     gboolean * edid_supported,
1759     guint32 * edid_blockcount, gchar ** edid_playload)
1760 {
1761   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1762   g_return_val_if_fail (edid_supported != NULL, GST_WFD_EINVAL);
1763   g_return_val_if_fail (edid_blockcount != NULL, GST_WFD_EINVAL);
1764   g_return_val_if_fail (edid_playload != NULL, GST_WFD_EINVAL);
1765
1766   *edid_supported = FALSE;
1767   if (msg->display_edid) {
1768     if (msg->display_edid->edid_supported) {
1769       *edid_blockcount = msg->display_edid->edid_block_count;
1770       if (msg->display_edid->edid_block_count > 0 && msg->display_edid->edid_block_count <= EDID_BLOCK_COUNT_MAX_SIZE) {
1771         char *temp;
1772         temp = g_malloc0(EDID_BLOCK_SIZE * msg->display_edid->edid_block_count);
1773         if (temp) {
1774           memcpy(temp, msg->display_edid->edid_payload, EDID_BLOCK_SIZE * msg->display_edid->edid_block_count);
1775           *edid_playload = temp;
1776           *edid_supported = TRUE;
1777         }
1778       }
1779     }
1780   }
1781   return GST_WFD_OK;
1782 }
1783
1784
1785 GstWFDResult
1786 gst_wfd_message_set_contentprotection_type (GstWFDMessage * msg,
1787     GstWFDHDCPProtection hdcpversion, guint32 TCPPort)
1788 {
1789   char str[11] = { 0, };
1790   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1791   g_return_val_if_fail (TCPPort <= MAX_PORT_SIZE, GST_WFD_EINVAL);
1792
1793   if (!msg->content_protection)
1794     msg->content_protection = g_new0 (GstWFDContentProtection, 1);
1795   if (hdcpversion == GST_WFD_HDCP_NONE)
1796     return GST_WFD_OK;
1797   msg->content_protection->hdcp2_spec = g_new0 (GstWFDHdcp2Spec, 1);
1798   if (hdcpversion == GST_WFD_HDCP_2_0)
1799     msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("HDCP2.0");
1800   else if (hdcpversion == GST_WFD_HDCP_2_1)
1801     msg->content_protection->hdcp2_spec->hdcpversion = g_strdup ("HDCP2.1");
1802   snprintf (str, sizeof (str), "port=%d", TCPPort);
1803   msg->content_protection->hdcp2_spec->TCPPort = g_strdup (str);
1804   return GST_WFD_OK;
1805 }
1806
1807 GstWFDResult
1808 gst_wfd_message_get_contentprotection_type (GstWFDMessage * msg,
1809     GstWFDHDCPProtection * hdcpversion, guint32 * TCPPort)
1810 {
1811   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1812   if (msg->content_protection && msg->content_protection->hdcp2_spec) {
1813     char *result = NULL;
1814     char *ptr = NULL;
1815     if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion, "none")) {
1816       *hdcpversion = GST_WFD_HDCP_NONE;
1817       *TCPPort = 0;
1818       return GST_WFD_OK;
1819     }
1820     if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion,
1821             "HDCP2.0"))
1822       *hdcpversion = GST_WFD_HDCP_2_0;
1823     else if (!g_strcmp0 (msg->content_protection->hdcp2_spec->hdcpversion,
1824             "HDCP2.1"))
1825       *hdcpversion = GST_WFD_HDCP_2_1;
1826     else {
1827       *hdcpversion = GST_WFD_HDCP_NONE;
1828       *TCPPort = 0;
1829       return GST_WFD_OK;
1830     }
1831
1832     if (msg->content_protection->hdcp2_spec->TCPPort) {
1833       result = strtok_r (msg->content_protection->hdcp2_spec->TCPPort, "=", &ptr);
1834       while (result != NULL && ptr != NULL) {
1835         result = strtok_r (NULL, "=", &ptr);
1836         *TCPPort = atoi (result);
1837         break;
1838       }
1839     } else {
1840       *TCPPort = 0;
1841     }
1842   } else
1843     *hdcpversion = GST_WFD_HDCP_NONE;
1844   return GST_WFD_OK;
1845 }
1846
1847
1848 GstWFDResult
1849 gst_wfd_messge_set_prefered_rtp_ports (GstWFDMessage * msg,
1850     GstWFDRTSPTransMode trans,
1851     GstWFDRTSPProfile profile,
1852     GstWFDRTSPLowerTrans lowertrans, guint32 rtp_port0, guint32 rtp_port1)
1853 {
1854   GString *lines;
1855   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1856
1857   if (!msg->client_rtp_ports)
1858     msg->client_rtp_ports = g_new0 (GstWFDClientRtpPorts, 1);
1859
1860   if (trans != GST_WFD_RTSP_TRANS_UNKNOWN) {
1861     lines = g_string_new ("");
1862     if (trans == GST_WFD_RTSP_TRANS_RTP)
1863       g_string_append_printf (lines, "RTP");
1864     else if (trans == GST_WFD_RTSP_TRANS_RDT)
1865       g_string_append_printf (lines, "RDT");
1866
1867     if (profile == GST_WFD_RTSP_PROFILE_AVP)
1868       g_string_append_printf (lines, "/AVP");
1869     else if (profile == GST_WFD_RTSP_PROFILE_SAVP)
1870       g_string_append_printf (lines, "/SAVP");
1871
1872     if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP)
1873       g_string_append_printf (lines, "/UDP;unicast");
1874     else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST)
1875       g_string_append_printf (lines, "/UDP;multicast");
1876     else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_TCP)
1877       g_string_append_printf (lines, "/TCP;unicast");
1878     else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_HTTP)
1879       g_string_append_printf (lines, "/HTTP");
1880
1881     msg->client_rtp_ports->profile = g_string_free (lines, FALSE);
1882     msg->client_rtp_ports->rtp_port0 = rtp_port0;
1883     msg->client_rtp_ports->rtp_port1 = rtp_port1;
1884     msg->client_rtp_ports->mode = g_strdup ("mode=play");
1885   }
1886   return GST_WFD_OK;
1887 }
1888
1889 GstWFDResult
1890 gst_wfd_message_get_prefered_rtp_ports (GstWFDMessage * msg,
1891     GstWFDRTSPTransMode * trans,
1892     GstWFDRTSPProfile * profile,
1893     GstWFDRTSPLowerTrans * lowertrans, guint32 * rtp_port0, guint32 * rtp_port1)
1894 {
1895   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1896   g_return_val_if_fail (msg->client_rtp_ports != NULL, GST_WFD_EINVAL);
1897
1898   if (g_strrstr (msg->client_rtp_ports->profile, "RTP"))
1899     *trans = GST_WFD_RTSP_TRANS_RTP;
1900   if (g_strrstr (msg->client_rtp_ports->profile, "RDT"))
1901     *trans = GST_WFD_RTSP_TRANS_RDT;
1902   if (g_strrstr (msg->client_rtp_ports->profile, "AVP"))
1903     *profile = GST_WFD_RTSP_PROFILE_AVP;
1904   if (g_strrstr (msg->client_rtp_ports->profile, "SAVP"))
1905     *profile = GST_WFD_RTSP_PROFILE_SAVP;
1906   if (g_strrstr (msg->client_rtp_ports->profile, "UDP;unicast"))
1907     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP;
1908   if (g_strrstr (msg->client_rtp_ports->profile, "UDP;multicast"))
1909     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST;
1910   if (g_strrstr (msg->client_rtp_ports->profile, "TCP;unicast"))
1911     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_TCP;
1912   if (g_strrstr (msg->client_rtp_ports->profile, "HTTP"))
1913     *lowertrans = GST_WFD_RTSP_LOWER_TRANS_HTTP;
1914
1915   *rtp_port0 = msg->client_rtp_ports->rtp_port0;
1916   *rtp_port1 = msg->client_rtp_ports->rtp_port1;
1917
1918   return GST_WFD_OK;
1919 }
1920
1921 GstWFDResult
1922 gst_wfd_message_set_presentation_url (GstWFDMessage * msg, gchar * wfd_url0,
1923     gchar * wfd_url1)
1924 {
1925   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1926
1927   if (!msg->presentation_url)
1928     msg->presentation_url = g_new0 (GstWFDPresentationUrl, 1);
1929   if (wfd_url0)
1930     msg->presentation_url->wfd_url0 = g_strdup (wfd_url0);
1931   if (wfd_url1)
1932     msg->presentation_url->wfd_url1 = g_strdup (wfd_url1);
1933   return GST_WFD_OK;
1934 }
1935
1936 GstWFDResult
1937 gst_wfd_message_get_presentation_url (GstWFDMessage * msg, gchar ** wfd_url0,
1938     gchar ** wfd_url1)
1939 {
1940   g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
1941
1942   if (msg->presentation_url) {
1943     *wfd_url0 = g_strdup (msg->presentation_url->wfd_url0);
1944     *wfd_url1 = g_strdup (msg->presentation_url->wfd_url1);
1945   }
1946   return GST_WFD_OK;
1947 }
1948
1949 GstWFDResult
1950 gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg, guint64 PTS, guint64 DTS)
1951 {
1952   g_return_val_if_fail(msg != NULL, GST_WFD_EINVAL);
1953
1954   if (!msg->av_format_change_timing)
1955     msg->av_format_change_timing = g_new0(GstWFDAVFormatChangeTiming, 1);
1956
1957   msg->av_format_change_timing->PTS = PTS;
1958   msg->av_format_change_timing->DTS = DTS;
1959   return GST_WFD_OK;
1960 }
1961
1962 GstWFDResult
1963 gst_wfd_message_get_av_format_change_timing(GstWFDMessage *msg, guint64 *PTS, guint64 *DTS)
1964 {
1965   g_return_val_if_fail(msg != NULL, GST_WFD_EINVAL);
1966   g_return_val_if_fail(PTS != NULL, GST_WFD_EINVAL);
1967   g_return_val_if_fail(DTS != NULL, GST_WFD_EINVAL);
1968
1969   if (msg->av_format_change_timing) {
1970     *PTS = msg->av_format_change_timing->PTS;
1971     *DTS = msg->av_format_change_timing->DTS;
1972   }
1973
1974   return GST_WFD_OK;
1975 }