2 * Copyright (C) <2005,2006> Wim Taymans <wim@fluendo.com>
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.
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.
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.
20 * Unless otherwise indicated, Source Code is licensed under MIT license.
21 * See further explanation attached in License Statement (distributed in the file
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:
31 * The above copyright notice and this permission notice shall be included in all
32 * copies or substantial portions of the Software.
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
44 * SECTION:gstwfdmessage
45 * @short_description: Helper methods for dealing with WFD messages
49 * The GstWFDMessage helper functions makes it easy to parse and create WFD
63 //#include <gio/gio.h>
65 #include "gstwfdmessage-ext.h"
67 #define FREE_STRING(field) g_free (field); (field) = NULL
68 #define REPLACE_STRING(field, val) FREE_STRING(field); (field) = g_strdup (val)
70 G_DEFINE_BOXED_TYPE (GstWFDExtMessage, gst_wfd_ext_message, NULL, NULL);
73 * gst_wfd_ext_message_new:
74 * @msg: (out) (transfer full): pointer to new #GstWFDExtMessage
76 * Allocate a new GstWFDExtMessage and store the result in @msg.
78 * Returns: a #GstWFDResult.
81 gst_wfd_ext_message_new (GstWFDExtMessage ** msg)
83 GstWFDExtMessage *newmsg;
85 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
87 newmsg = g_new0 (GstWFDExtMessage, 1);
91 return gst_wfd_ext_message_init (newmsg);
95 * gst_wfd_ext_message_init:
96 * @msg: a #GstWFDExtMessage
98 * Initialize @msg so that its contents are as if it was freshly allocated
99 * with gst_wfd_ext_message_new(). This function is mostly used to initialize a message
100 * allocated on the stack. gst_wfd_ext_message_uninit() undoes this operation.
102 * When this function is invoked on newly allocated data (with malloc or on the
103 * stack), its contents should be set to 0 before calling this function.
105 * Returns: a #GstWFDResult.
108 gst_wfd_ext_message_init (GstWFDExtMessage * msg)
110 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
116 * gst_wfd_ext_message_uninit:
117 * @msg: a #GstWFDExtMessage
119 * Free all resources allocated in @msg. @msg should not be used anymore after
120 * this function. This function should be used when @msg was allocated on the
121 * stack and initialized with gst_wfd_ext_message_init().
123 * Returns: a #GstWFDResult.
126 gst_wfd_ext_message_uninit (GstWFDExtMessage * msg)
128 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
130 if (msg->tizen_retransmission) {
131 FREE_STRING (msg->tizen_retransmission);
134 if (msg->tizen_fec) {
135 FREE_STRING (msg->tizen_fec);
138 if (msg->tizen_latency_mode) {
139 FREE_STRING (msg->tizen_latency_mode);
146 _read_string_space_ended (gchar * dest, guint size, gchar * src)
150 while (!g_ascii_isspace (*src) && *src != '\0') {
164 _read_string_attr_and_value (gchar * attr, gchar * value, guint tsize,
165 guint vsize, gchar del, gchar * src)
171 while (*src != del && *src != '\0') {
183 while (*src != '\0') {
196 gst_wfd_parse_attribute (gchar * buffer, GstWFDExtMessage * msg)
198 gchar attr[8192] = { 0 };
199 gchar value[8192] = { 0 };
200 gchar temp[8192] = { 0 };
204 #define WFD_SKIP_SPACE(q) if (*q && g_ascii_isspace (*q)) q++
205 #define WFD_SKIP_EQUAL(q) if (*q && *q == '=') q++
206 #define WFD_SKIP_COMMA(q) if (*q && g_ascii_ispunct (*q)) q++
207 #define WFD_READ_STRING(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); REPLACE_STRING (field, temp)
208 #define WFD_READ_UINT32(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 16)
209 #define WFD_READ_UINT32_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 10)
211 _read_string_attr_and_value (attr, value, sizeof (attr), sizeof (value), ':',
214 if (!g_strcmp0 (attr, GST_STRING_TIZEN_WFD_RESTRANSMISSION)) {
215 msg->tizen_retransmission = g_new0 (GstWFDTizenRetransmission, 1);
217 if (!strstr (v, "none")) {
219 WFD_READ_UINT32_DIGIT (msg->tizen_retransmission->rtp_port);
221 WFD_READ_UINT32_DIGIT (msg->tizen_retransmission->rtcp_port);
225 else if (!g_strcmp0 (attr, GST_STRING_TIZEN_WFD_FEC)) {
226 msg->tizen_fec = g_new0 (GstWFDTizenFec, 1);
228 if (!strstr (v, "none")) {
230 WFD_READ_UINT32_DIGIT (msg->tizen_fec->t_max);
232 WFD_READ_UINT32_DIGIT (msg->tizen_fec->p_max);
235 } else if (!g_strcmp0 (attr, GST_STRING_TIZEN_WFD_LATENCY_MODE)) {
236 msg->tizen_latency_mode = g_new0 (GstWFDTizenLatencyMode, 1);
238 if (strstr (v, GST_STRING_TIZEN_WFD_LATENCY_LOW)) {
239 msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_LOW;
240 } else if (strstr (v, GST_STRING_TIZEN_WFD_LATENCY_MID)) {
241 msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_MID;
242 } else if (strstr (v, GST_STRING_TIZEN_WFD_LATENCY_HIGH)) {
243 msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_HIGH;
245 msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_NONE;
254 * gst_wfd_ext_message_parse_buffer:
255 * @data: the start of the buffer
256 * @size: the size of the buffer
257 * @msg: the result #GstSDPMessage
259 * Parse the contents of @size bytes pointed to by @data and store the result in
262 * Returns: #GST_SDP_OK on success.
265 gst_wfd_ext_message_parse_buffer (const guint8 * data, guint size,
266 GstWFDExtMessage * msg)
269 gchar buffer[255] = { 0 };
272 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
273 g_return_val_if_fail (data != NULL, GST_WFD_EINVAL);
274 g_return_val_if_fail (size != 0, GST_WFD_EINVAL);
283 while (*p != '\n' && *p != '\r' && *p != '\0') {
284 if (idx < sizeof (buffer) - 1)
289 gst_wfd_parse_attribute (buffer, msg);
299 * gst_wfd_ext_message_free:
300 * @msg: a #GstWFDExtMessage
302 * Free all resources allocated by @msg. @msg should not be used anymore after
303 * this function. This function should be used when @msg was dynamically
304 * allocated with gst_wfd_ext_message_new().
306 * Returns: a #GstWFDResult.
309 gst_wfd_ext_message_free (GstWFDExtMessage * msg)
311 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
313 gst_wfd_ext_message_uninit (msg);
320 * gst_wfd_ext_message_as_text:
321 * @msg: a #GstWFDExtMessage
323 * Convert the contents of @msg to a text string.
325 * Returns: A dynamically allocated string representing the WFD description.
328 gst_wfd_ext_message_as_text (const GstWFDExtMessage * msg)
330 /* change all vars so they match rfc? */
333 g_return_val_if_fail (msg != NULL, NULL);
335 lines = g_string_new ("");
337 if (msg->tizen_retransmission) {
338 g_string_append_printf (lines, GST_STRING_TIZEN_WFD_RESTRANSMISSION);
339 g_string_append_printf (lines, ":");
340 g_string_append_printf (lines, " %d", msg->tizen_retransmission->rtp_port);
341 g_string_append_printf (lines, " %d", msg->tizen_retransmission->rtcp_port);
342 g_string_append_printf (lines, "\r\n");
345 if (msg->tizen_fec) {
346 g_string_append_printf (lines, GST_STRING_TIZEN_WFD_FEC);
347 g_string_append_printf (lines, ":");
348 g_string_append_printf (lines, " %d", msg->tizen_fec->t_max);
349 g_string_append_printf (lines, " %d", msg->tizen_fec->p_max);
350 g_string_append_printf (lines, "\r\n");
353 if (msg->tizen_latency_mode) {
354 g_string_append_printf (lines, GST_STRING_TIZEN_WFD_LATENCY_MODE);
355 g_string_append_printf (lines, ":");
357 if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_LOW)
358 g_string_append_printf (lines, " " GST_STRING_TIZEN_WFD_LATENCY_LOW);
359 else if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_MID)
360 g_string_append_printf (lines, " " GST_STRING_TIZEN_WFD_LATENCY_MID);
361 else if (msg->tizen_latency_mode->latency_mode ==
362 GST_WFD_TIZEN_LATENCY_HIGH)
363 g_string_append_printf (lines, " " GST_STRING_TIZEN_WFD_LATENCY_HIGH);
365 g_string_append_printf (lines, " none");
367 g_string_append_printf (lines, "\r\n");
370 return g_string_free (lines, FALSE);
374 gst_wfd_ext_message_param_names_as_text (const GstWFDExtMessage * msg)
376 /* change all vars so they match rfc? */
378 g_return_val_if_fail (msg != NULL, NULL);
380 lines = g_string_new ("");
382 if (msg->tizen_retransmission) {
383 g_string_append_printf (lines, GST_STRING_TIZEN_WFD_RESTRANSMISSION);
384 g_string_append_printf (lines, "\r\n");
386 if (msg->tizen_fec) {
387 g_string_append_printf (lines, GST_STRING_TIZEN_WFD_FEC);
388 g_string_append_printf (lines, "\r\n");
390 if (msg->tizen_latency_mode) {
391 g_string_append_printf (lines, GST_STRING_TIZEN_WFD_LATENCY_MODE);
392 g_string_append_printf (lines, "\r\n");
395 return g_string_free (lines, FALSE);
399 * gst_wfd_ext_message_dump:
400 * @msg: a #GstWFDExtMessage
402 * Dump the parsed contents of @msg to stdout.
404 * Returns: a #GstWFDResult.
407 gst_wfd_ext_message_dump (const GstWFDExtMessage * msg)
409 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
411 if (msg->tizen_retransmission) {
412 g_print ("tizen_wfd_retransmission: %d %d",
413 msg->tizen_retransmission->rtp_port,
414 msg->tizen_retransmission->rtcp_port);
418 if (msg->tizen_fec) {
419 g_print ("tizen_wfd_fec: %d %d", msg->tizen_fec->t_max, msg->tizen_fec->p_max);
423 if (msg->tizen_latency_mode) {
424 g_print ("tizen_wfd_latency_mode:");
426 if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_LOW)
428 else if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_MID)
430 else if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_HIGH)
441 gst_wfd_ext_message_set_tizen_retransmission (GstWFDExtMessage * msg,
442 guint rtp_port, guint rtcp_port)
444 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
446 if (!msg->tizen_retransmission)
447 msg->tizen_retransmission = g_new0 (GstWFDTizenRetransmission, 1);
449 msg->tizen_retransmission->rtp_port = rtp_port;
450 msg->tizen_retransmission->rtcp_port = rtcp_port;
456 gst_wfd_ext_message_get_tizen_retransmission (GstWFDExtMessage * msg,
457 guint * rtp_port, guint * rtcp_port)
459 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
460 g_return_val_if_fail (msg->tizen_retransmission != NULL, GST_WFD_EINVAL);
461 g_return_val_if_fail (rtp_port != NULL, GST_WFD_EINVAL);
462 g_return_val_if_fail (rtcp_port != NULL, GST_WFD_EINVAL);
464 *rtp_port = msg->tizen_retransmission->rtp_port;
465 *rtcp_port = msg->tizen_retransmission->rtcp_port;
471 gst_wfd_ext_message_set_tizen_fec (GstWFDExtMessage * msg, guint t_max,
474 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
477 msg->tizen_fec = g_new0 (GstWFDTizenFec, 1);
479 msg->tizen_fec->t_max = t_max;
480 msg->tizen_fec->p_max = p_max;
486 gst_wfd_ext_message_get_tizen_fec (GstWFDExtMessage * msg, guint * t_max,
489 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
490 g_return_val_if_fail (msg->tizen_fec != NULL, GST_WFD_EINVAL);
491 g_return_val_if_fail (t_max != NULL, GST_WFD_EINVAL);
492 g_return_val_if_fail (p_max != NULL, GST_WFD_EINVAL);
494 *t_max = msg->tizen_fec->t_max;
495 *p_max = msg->tizen_fec->p_max;
501 gst_wfd_ext_message_set_tizen_latency_mode (GstWFDExtMessage * msg,
504 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
506 if (!msg->tizen_latency_mode)
507 msg->tizen_latency_mode = g_new0 (GstWFDTizenLatencyMode, 1);
509 msg->tizen_latency_mode->latency_mode = latency_mode;
515 gst_wfd_ext_message_get_tizen_latency_mode (GstWFDExtMessage * msg,
516 guint * latency_mode)
518 g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL);
519 g_return_val_if_fail (msg->tizen_latency_mode != NULL, GST_WFD_EINVAL);
520 g_return_val_if_fail (latency_mode != NULL, GST_WFD_EINVAL);
522 *latency_mode = msg->tizen_latency_mode->latency_mode;