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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, 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:gstsdpmessage
45 * @short_description: Helper methods for dealing with SDP messages
49 * The GstSDPMessage helper functions makes it easy to parse and create SDP
54 * Last reviewed on 2007-07-24 (0.10.14)
64 #ifdef HAVE_SYS_TYPES_H
65 #include <sys/types.h>
68 #include <glib.h> /* for G_OS_WIN32 */
69 #include <gst/gstinfo.h> /* For GST_STR_NULL */
72 /* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later.
73 * minwg32 headers check WINVER before allowing the use of these */
82 #include <sys/socket.h>
84 #include <netinet/in.h>
87 #include "gstsdpmessage.h"
89 /* FIXME, is currently allocated on the stack */
90 #define MAX_LINE_LEN 1024 * 16
92 #define FREE_STRING(field) g_free (field); (field) = NULL
93 #define REPLACE_STRING(field, val) FREE_STRING(field); (field) = g_strdup (val)
95 #define INIT_ARRAY(field, type, init_func) \
99 for(i = 0; i < (field)->len; i++) \
100 init_func (&g_array_index ((field), type, i)); \
101 g_array_set_size ((field), 0); \
104 (field) = g_array_new (FALSE, TRUE, sizeof (type)); \
107 #define FREE_ARRAY(field) \
110 g_array_free ((field), TRUE); \
114 #define INIT_PTR_ARRAY(field, type, init_func) \
118 for(i = 0; i < (field)->len; i++) \
119 init_func (g_array_index ((field), type, i)); \
120 g_array_set_size ((field), 0); \
123 (field) = g_array_new (FALSE, TRUE, sizeof (type)); \
126 #define FREE_PTR_ARRAY(field) FREE_ARRAY(field)
128 #define DEFINE_STRING_SETTER(field) \
129 GstSDPResult gst_sdp_message_set_##field (GstSDPMessage *msg, const gchar *val) { \
130 g_free (msg->field); \
131 msg->field = g_strdup (val); \
134 #define DEFINE_STRING_GETTER(field) \
135 const gchar* gst_sdp_message_get_##field (const GstSDPMessage *msg) { \
139 #define DEFINE_ARRAY_LEN(field) \
140 guint gst_sdp_message_##field##_len (const GstSDPMessage *msg) { \
141 return msg->field->len; \
143 #define DEFINE_ARRAY_GETTER(method, field, type) \
144 type * gst_sdp_message_get_##method (const GstSDPMessage *msg, guint idx) { \
145 return &g_array_index (msg->field, type, idx); \
148 #define DEFINE_PTR_ARRAY_LEN(field) DEFINE_ARRAY_LEN(field)
149 #define DEFINE_PTR_ARRAY_GETTER(method, field, type) \
150 type gst_sdp_message_get_##method (const GstSDPMessage *msg, guint idx) { \
151 return g_array_index (msg->field, type, idx); \
153 #define DEFINE_PTR_ARRAY_ADDER(method, field, type, dup_method) \
154 GstSDPResult gst_sdp_message_add_##method (GstSDPMessage *msg, type val) { \
155 type v = dup_method (val); \
156 g_array_append_val (msg->field, v); \
161 gst_sdp_origin_init (GstSDPOrigin * origin)
163 FREE_STRING (origin->username);
164 FREE_STRING (origin->sess_id);
165 FREE_STRING (origin->sess_version);
166 FREE_STRING (origin->nettype);
167 FREE_STRING (origin->addrtype);
168 FREE_STRING (origin->addr);
172 gst_sdp_connection_init (GstSDPConnection * connection)
174 FREE_STRING (connection->nettype);
175 FREE_STRING (connection->addrtype);
176 FREE_STRING (connection->address);
178 connection->addr_number = 0;
182 gst_sdp_bandwidth_init (GstSDPBandwidth * bandwidth)
184 FREE_STRING (bandwidth->bwtype);
185 bandwidth->bandwidth = 0;
189 gst_sdp_time_init (GstSDPTime * t)
191 FREE_STRING (t->start);
192 FREE_STRING (t->stop);
193 INIT_PTR_ARRAY (t->repeat, gchar *, g_free);
194 FREE_PTR_ARRAY (t->repeat);
198 gst_sdp_zone_init (GstSDPZone * zone)
200 FREE_STRING (zone->time);
201 FREE_STRING (zone->typed_time);
205 gst_sdp_key_init (GstSDPKey * key)
207 FREE_STRING (key->type);
208 FREE_STRING (key->data);
212 gst_sdp_attribute_init (GstSDPAttribute * attr)
214 FREE_STRING (attr->key);
215 FREE_STRING (attr->value);
219 * gst_sdp_message_new:
220 * @msg: pointer to new #GstSDPMessage
222 * Allocate a new GstSDPMessage and store the result in @msg.
224 * Returns: a #GstSDPResult.
227 gst_sdp_message_new (GstSDPMessage ** msg)
229 GstSDPMessage *newmsg;
231 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
233 newmsg = g_new0 (GstSDPMessage, 1);
237 return gst_sdp_message_init (newmsg);
241 * gst_sdp_message_init:
242 * @msg: a #GstSDPMessage
244 * Initialize @msg so that its contents are as if it was freshly allocated
245 * with gst_sdp_message_new(). This function is mostly used to initialize a message
246 * allocated on the stack. gst_sdp_message_uninit() undoes this operation.
248 * When this function is invoked on newly allocated data (with malloc or on the
249 * stack), its contents should be set to 0 before calling this function.
251 * Returns: a #GstSDPResult.
254 gst_sdp_message_init (GstSDPMessage * msg)
256 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
258 FREE_STRING (msg->version);
259 gst_sdp_origin_init (&msg->origin);
260 FREE_STRING (msg->session_name);
261 FREE_STRING (msg->information);
262 FREE_STRING (msg->uri);
263 INIT_PTR_ARRAY (msg->emails, gchar *, g_free);
264 INIT_PTR_ARRAY (msg->phones, gchar *, g_free);
265 gst_sdp_connection_init (&msg->connection);
266 INIT_ARRAY (msg->bandwidths, GstSDPBandwidth, gst_sdp_bandwidth_init);
267 INIT_ARRAY (msg->times, GstSDPTime, gst_sdp_time_init);
268 INIT_ARRAY (msg->zones, GstSDPZone, gst_sdp_zone_init);
269 gst_sdp_key_init (&msg->key);
270 INIT_ARRAY (msg->attributes, GstSDPAttribute, gst_sdp_attribute_init);
271 INIT_ARRAY (msg->medias, GstSDPMedia, gst_sdp_media_uninit);
277 * gst_sdp_message_uninit:
278 * @msg: a #GstSDPMessage
280 * Free all resources allocated in @msg. @msg should not be used anymore after
281 * this function. This function should be used when @msg was allocated on the
282 * stack and initialized with gst_sdp_message_init().
284 * Returns: a #GstSDPResult.
287 gst_sdp_message_uninit (GstSDPMessage * msg)
289 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
291 gst_sdp_message_init (msg);
293 FREE_PTR_ARRAY (msg->emails);
294 FREE_PTR_ARRAY (msg->phones);
295 FREE_ARRAY (msg->bandwidths);
296 FREE_ARRAY (msg->times);
297 FREE_ARRAY (msg->zones);
298 FREE_ARRAY (msg->attributes);
299 FREE_ARRAY (msg->medias);
305 * gst_sdp_message_free:
306 * @msg: a #GstSDPMessage
308 * Free all resources allocated by @msg. @msg should not be used anymore after
309 * this function. This function should be used when @msg was dynamically
310 * allocated with gst_sdp_message_new().
312 * Returns: a #GstSDPResult.
315 gst_sdp_message_free (GstSDPMessage * msg)
317 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
319 gst_sdp_message_uninit (msg);
326 * gst_sdp_address_is_multicast:
327 * @nettype: a network type
328 * @addrtype: an address type
331 * Check if the given @addr is a multicast address.
333 * Returns: TRUE when @addr is multicast.
338 gst_sdp_address_is_multicast (const gchar * nettype, const gchar * addrtype,
341 struct addrinfo hints;
343 struct addrinfo *res;
344 gboolean ret = FALSE;
346 g_return_val_if_fail (addr, FALSE);
348 /* we only support IN */
349 if (nettype && strcmp (nettype, "IN") != 0)
352 memset (&hints, 0, sizeof (hints));
353 hints.ai_socktype = SOCK_DGRAM;
355 /* set the address type as a hint */
357 if (!strcmp (addrtype, "IP4"))
358 hints.ai_family = AF_INET;
359 else if (!strcmp (addrtype, "IP6"))
360 hints.ai_family = AF_INET6;
363 if (getaddrinfo (addr, NULL, &hints, &res) < 0)
366 for (ai = res; !ret && ai; ai = ai->ai_next) {
367 if (ai->ai_family == AF_INET)
369 IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)->
373 IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai->
374 ai_addr)->sin6_addr);
383 * gst_sdp_message_as_text:
384 * @msg: a #GstSDPMessage
386 * Convert the contents of @msg to a text string.
388 * Returns: A dynamically allocated string representing the SDP description.
391 gst_sdp_message_as_text (const GstSDPMessage * msg)
393 /* change all vars so they match rfc? */
397 g_return_val_if_fail (msg != NULL, NULL);
399 lines = g_string_new ("");
402 g_string_append_printf (lines, "v=%s\r\n", msg->version);
404 if (msg->origin.sess_id && msg->origin.sess_version && msg->origin.nettype &&
405 msg->origin.addrtype && msg->origin.addr)
406 g_string_append_printf (lines, "o=%s %s %s %s %s %s\r\n",
407 msg->origin.username ? msg->origin.username : "-", msg->origin.sess_id,
408 msg->origin.sess_version, msg->origin.nettype, msg->origin.addrtype,
411 if (msg->session_name)
412 g_string_append_printf (lines, "s=%s\r\n", msg->session_name);
414 if (msg->information)
415 g_string_append_printf (lines, "i=%s\r\n", msg->information);
418 g_string_append_printf (lines, "u=%s\r\n", msg->uri);
420 for (i = 0; i < gst_sdp_message_emails_len (msg); i++)
421 g_string_append_printf (lines, "e=%s\r\n",
422 gst_sdp_message_get_email (msg, i));
424 for (i = 0; i < gst_sdp_message_phones_len (msg); i++)
425 g_string_append_printf (lines, "p=%s\r\n",
426 gst_sdp_message_get_phone (msg, i));
428 if (gst_sdp_message_emails_len (msg) == 0 &&
429 gst_sdp_message_phones_len (msg) == 0)
430 g_string_append_printf (lines, "e=NONE\r\n");
432 if (msg->connection.nettype && msg->connection.addrtype &&
433 msg->connection.address) {
434 g_string_append_printf (lines, "c=%s %s %s", msg->connection.nettype,
435 msg->connection.addrtype, msg->connection.address);
436 if (gst_sdp_address_is_multicast (msg->connection.nettype,
437 msg->connection.addrtype, msg->connection.address)) {
438 /* only add ttl for IP4 */
439 if (strcmp (msg->connection.addrtype, "IP4") == 0)
440 g_string_append_printf (lines, "/%u", msg->connection.ttl);
441 if (msg->connection.addr_number > 1)
442 g_string_append_printf (lines, "/%u", msg->connection.addr_number);
444 g_string_append_printf (lines, "\r\n");
447 for (i = 0; i < gst_sdp_message_bandwidths_len (msg); i++) {
448 const GstSDPBandwidth *bandwidth = gst_sdp_message_get_bandwidth (msg, i);
450 g_string_append_printf (lines, "b=%s:%u\r\n", bandwidth->bwtype,
451 bandwidth->bandwidth);
454 for (i = 0; i < gst_sdp_message_times_len (msg); i++) {
455 const GstSDPTime *times = gst_sdp_message_get_time (msg, i);
457 g_string_append_printf (lines, "t=%s %s\r\n", times->start, times->stop);
459 if (times->repeat != NULL) {
462 g_string_append_printf (lines, "r=%s",
463 g_array_index (times->repeat, gchar *, 0));
464 for (j = 1; j < times->repeat->len; j++)
465 g_string_append_printf (lines, " %s",
466 g_array_index (times->repeat, gchar *, j));
467 g_string_append_printf (lines, "\r\n");
471 if (gst_sdp_message_zones_len (msg) > 0) {
472 const GstSDPZone *zone = gst_sdp_message_get_zone (msg, 0);
474 g_string_append_printf (lines, "z=%s %s", zone->time, zone->typed_time);
475 for (i = 1; i < gst_sdp_message_zones_len (msg); i++) {
476 zone = gst_sdp_message_get_zone (msg, i);
477 g_string_append_printf (lines, " %s %s", zone->time, zone->typed_time);
479 g_string_append_printf (lines, "\r\n");
483 g_string_append_printf (lines, "k=%s", msg->key.type);
485 g_string_append_printf (lines, ":%s", msg->key.data);
486 g_string_append_printf (lines, "\r\n");
489 for (i = 0; i < gst_sdp_message_attributes_len (msg); i++) {
490 const GstSDPAttribute *attr = gst_sdp_message_get_attribute (msg, i);
493 g_string_append_printf (lines, "a=%s", attr->key);
495 g_string_append_printf (lines, ":%s", attr->value);
496 g_string_append_printf (lines, "\r\n");
500 for (i = 0; i < gst_sdp_message_medias_len (msg); i++) {
501 const GstSDPMedia *media = gst_sdp_message_get_media (msg, i);
502 gchar *sdp_media_str;
504 sdp_media_str = gst_sdp_media_as_text (media);
505 g_string_append_printf (lines, "%s", sdp_media_str);
506 g_free (sdp_media_str);
509 return g_string_free (lines, FALSE);
515 return c >= '0' && c <= '9' ? c - '0'
516 : c >= 'A' && c <= 'F' ? c - 'A' + 10
517 : c >= 'a' && c <= 'f' ? c - 'a' + 10 : 0;
521 * gst_sdp_message_parse_uri:
522 * @uri: the start of the uri
523 * @msg: the result #GstSDPMessage
525 * Parse the null-terminated @uri and store the result in @msg.
527 * The uri should be of the form:
529 * scheme://[address[:ttl=ttl][:noa=noa]]/[sessionname]
530 * [#type=value *[&type=value]]
532 * where value is url encoded. This looslely resembles
533 * http://tools.ietf.org/html/draft-fujikawa-sdp-url-01
535 * Returns: #GST_SDP_OK on success.
540 gst_sdp_message_parse_uri (const gchar * uri, GstSDPMessage * msg)
544 const gchar *colon, *slash, *hash, *p;
547 g_return_val_if_fail (uri != NULL, GST_SDP_EINVAL);
548 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
550 colon = strstr (uri, "://");
554 /* FIXME connection info goes here */
556 slash = strstr (colon + 3, "/");
560 /* FIXME session name goes here */
562 hash = strstr (slash + 1, "#");
566 lines = g_string_new ("");
569 for (p = hash + 1; *p; p++) {
571 g_string_append_printf (lines, "\r\n");
573 g_string_append_c (lines, ' ');
574 else if (*p == '%') {
579 g_string_append_c (lines, (hex_to_int (a) << 4) | hex_to_int (b));
586 g_string_append_c (lines, *p);
589 message = g_string_free (lines, FALSE);
591 gst_sdp_message_parse_buffer ((const guint8 *) message, strlen (message),
600 return GST_SDP_EINVAL;
604 return GST_SDP_EINVAL;
608 return GST_SDP_EINVAL;
612 static const guchar acceptable[96] = {
613 /* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */
614 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, /* 2X !"#$%&'()*+,-./ */
615 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3X 0123456789:;<=>? */
616 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 4X @ABCDEFGHIJKLMNO */
617 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, /* 5X PQRSTUVWXYZ[\]^_ */
618 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 6X `abcdefghijklmno */
619 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 /* 7X pqrstuvwxyz{|}~DEL */
622 static const gchar hex[16] = "0123456789ABCDEF";
624 #define ACCEPTABLE_CHAR(a) (((guchar)(a))>=32 && ((guchar)(a))<128 && acceptable[(((guchar)a))-32])
627 * gst_sdp_message_as_uri:
628 * @scheme: the uri scheme
629 * @msg: the #GstSDPMessage
631 * Creates a uri from @msg with the given @scheme. The uri has the format:
633 * @scheme:///[#type=value *[&type=value]]
635 * Where each value is url encoded.
637 * Returns: a uri for @msg.
642 gst_sdp_message_as_uri (const gchar * scheme, const GstSDPMessage * msg)
644 gchar *serialized, *p;
649 g_return_val_if_fail (scheme != NULL, NULL);
650 g_return_val_if_fail (msg != NULL, NULL);
652 p = serialized = gst_sdp_message_as_text (msg);
654 lines = g_string_new ("");
655 g_string_append_printf (lines, "%s:///#", scheme);
659 for (p = serialized; *p; p++) {
661 g_string_append_printf (lines, "%c=", *p);
669 else if (*p == '\n') {
671 g_string_append_c (lines, '&');
673 } else if (*p == ' ')
674 g_string_append_c (lines, '+');
675 else if (ACCEPTABLE_CHAR (*p))
676 g_string_append_c (lines, *p);
679 g_string_append_printf (lines, "%%%c%c", hex[*p >> 4], hex[*p & 0xf]);
683 res = g_string_free (lines, FALSE);
690 * gst_sdp_message_set_version:
691 * @msg: a #GstSDPMessage
692 * @version: the version
694 * Set the version in @msg.
696 * Returns: a #GstSDPResult.
698 DEFINE_STRING_SETTER (version);
700 * gst_sdp_message_get_version:
701 * @msg: a #GstSDPMessage
703 * Get the version in @msg.
705 * Returns: a #GstSDPResult.
707 DEFINE_STRING_GETTER (version);
710 * gst_sdp_message_set_origin:
711 * @msg: a #GstSDPMessage
712 * @username: the user name
713 * @sess_id: a session id
714 * @sess_version: a session version
715 * @nettype: a network type
716 * @addrtype: an address type
719 * Configure the SDP origin in @msg with the given parameters.
721 * Returns: #GST_SDP_OK.
724 gst_sdp_message_set_origin (GstSDPMessage * msg, const gchar * username,
725 const gchar * sess_id, const gchar * sess_version, const gchar * nettype,
726 const gchar * addrtype, const gchar * addr)
728 REPLACE_STRING (msg->origin.username, username);
729 REPLACE_STRING (msg->origin.sess_id, sess_id);
730 REPLACE_STRING (msg->origin.sess_version, sess_version);
731 REPLACE_STRING (msg->origin.nettype, nettype);
732 REPLACE_STRING (msg->origin.addrtype, addrtype);
733 REPLACE_STRING (msg->origin.addr, addr);
739 * gst_sdp_message_get_origin:
740 * @msg: a #GstSDPMessage
742 * Get the origin of @msg.
744 * Returns: a #GstSDPOrigin. The result remains valid as long as @msg is valid.
747 gst_sdp_message_get_origin (const GstSDPMessage * msg)
753 * gst_sdp_message_set_session_name:
754 * @msg: a #GstSDPMessage
755 * @session_name: the session name
757 * Set the session name in @msg.
759 * Returns: a #GstSDPResult.
761 DEFINE_STRING_SETTER (session_name);
763 * gst_sdp_message_get_session_name:
764 * @msg: a #GstSDPMessage
766 * Get the session name in @msg.
768 * Returns: a #GstSDPResult.
770 DEFINE_STRING_GETTER (session_name);
772 * gst_sdp_message_set_information:
773 * @msg: a #GstSDPMessage
774 * @information: the information
776 * Set the information in @msg.
778 * Returns: a #GstSDPResult.
780 DEFINE_STRING_SETTER (information);
782 * gst_sdp_message_get_information:
783 * @msg: a #GstSDPMessage
785 * Get the information in @msg.
787 * Returns: a #GstSDPResult.
789 DEFINE_STRING_GETTER (information);
791 * gst_sdp_message_set_uri:
792 * @msg: a #GstSDPMessage
795 * Set the URI in @msg.
797 * Returns: a #GstSDPResult.
799 DEFINE_STRING_SETTER (uri);
801 * gst_sdp_message_get_uri:
802 * @msg: a #GstSDPMessage
804 * Get the URI in @msg.
806 * Returns: a #GstSDPResult.
808 DEFINE_STRING_GETTER (uri);
811 * gst_sdp_message_emails_len:
812 * @msg: a #GstSDPMessage
814 * Get the number of emails in @msg.
816 * Returns: the number of emails in @msg.
818 DEFINE_ARRAY_LEN (emails);
820 * gst_sdp_message_get_email:
821 * @msg: a #GstSDPMessage
822 * @idx: an email index
824 * Get the email with number @idx from @msg.
826 * Returns: the email at position @idx.
828 DEFINE_PTR_ARRAY_GETTER (email, emails, const gchar *);
831 * gst_sdp_message_add_email:
832 * @msg: a #GstSDPMessage
835 * Add @email to the list of emails in @msg.
837 * Returns: a #GstSDPResult.
839 DEFINE_PTR_ARRAY_ADDER (email, emails, const gchar *, g_strdup);
842 * gst_sdp_message_phones_len:
843 * @msg: a #GstSDPMessage
845 * Get the number of phones in @msg.
847 * Returns: the number of phones in @msg.
849 DEFINE_ARRAY_LEN (phones);
851 * gst_sdp_message_get_phone:
852 * @msg: a #GstSDPMessage
853 * @idx: a phone index
855 * Get the phone with number @idx from @msg.
857 * Returns: the phone at position @idx.
859 DEFINE_PTR_ARRAY_GETTER (phone, phones, const gchar *);
862 * gst_sdp_message_add_phone:
863 * @msg: a #GstSDPMessage
866 * Add @phone to the list of phones in @msg.
868 * Returns: a #GstSDPResult.
870 DEFINE_PTR_ARRAY_ADDER (phone, phones, const gchar *, g_strdup);
873 * gst_sdp_message_set_connection:
874 * @msg: a #GstSDPMessage
875 * @nettype: the type of network. "IN" is defined to have the meaning
877 * @addrtype: the type of address.
878 * @address: the address
879 * @ttl: the time to live of the address
880 * @addr_number: the number of layers
882 * Configure the SDP connection in @msg with the given parameters.
884 * Returns: a #GstSDPResult.
887 gst_sdp_message_set_connection (GstSDPMessage * msg, const gchar * nettype,
888 const gchar * addrtype, const gchar * address, guint ttl, guint addr_number)
890 REPLACE_STRING (msg->connection.nettype, nettype);
891 REPLACE_STRING (msg->connection.addrtype, addrtype);
892 REPLACE_STRING (msg->connection.address, address);
893 msg->connection.ttl = ttl;
894 msg->connection.addr_number = addr_number;
900 * gst_sdp_message_get_connection:
901 * @msg: a #GstSDPMessage
903 * Get the connection of @msg.
905 * Returns: a #GstSDPConnection. The result remains valid as long as @msg is valid.
907 const GstSDPConnection *
908 gst_sdp_message_get_connection (const GstSDPMessage * msg)
910 return &msg->connection;
914 * gst_sdp_message_bandwidths_len:
915 * @msg: a #GstSDPMessage
917 * Get the number of bandwidth information in @msg.
919 * Returns: the number of bandwidth information in @msg.
921 DEFINE_ARRAY_LEN (bandwidths);
923 * gst_sdp_message_get_bandwidth:
924 * @msg: a #GstSDPMessage
925 * @idx: the bandwidth index
927 * Get the bandwidth at index @idx from @msg.
929 * Returns: a #GstSDPBandwidth.
931 DEFINE_ARRAY_GETTER (bandwidth, bandwidths, const GstSDPBandwidth);
934 * gst_sdp_message_add_bandwidth:
935 * @msg: a #GstSDPMessage
936 * @bwtype: the bandwidth modifier type
937 * @bandwidth: the bandwidth in kilobits per second
939 * Add the specified bandwidth information to @msg.
941 * Returns: a #GstSDPResult.
945 gst_sdp_message_add_bandwidth (GstSDPMessage * msg, const gchar * bwtype,
950 bw.bwtype = g_strdup (bwtype);
951 bw.bandwidth = bandwidth;
953 g_array_append_val (msg->bandwidths, bw);
959 * gst_sdp_message_times_len:
960 * @msg: a #GstSDPMessage
962 * Get the number of time information entries in @msg.
964 * Returns: the number of time information entries in @msg.
966 DEFINE_ARRAY_LEN (times);
969 * gst_sdp_message_get_time:
970 * @msg: a #GstSDPMessage
971 * @idx: the time index
973 * Get time information with index @idx from @msg.
975 * Returns: a #GstSDPTime.
977 DEFINE_ARRAY_GETTER (time, times, const GstSDPTime);
980 * gst_sdp_message_add_time:
981 * @msg: a #GstSDPMessage
982 * @start: the start time
983 * @stop: the stop time
984 * @repeat: the repeat times
986 * Add time information @start and @stop to @msg.
988 * Returns: a #GstSDPResult.
991 gst_sdp_message_add_time (GstSDPMessage * msg, const gchar * start,
992 const gchar * stop, const gchar ** repeat)
996 times.start = g_strdup (start);
997 times.stop = g_strdup (stop);
999 times.repeat = g_array_new (FALSE, TRUE, sizeof (gchar *));
1000 for (; *repeat; repeat++) {
1001 gchar *r = g_strdup (*repeat);
1003 g_array_append_val (times.repeat, r);
1006 times.repeat = NULL;
1007 g_array_append_val (msg->times, times);
1013 * gst_sdp_message_zones_len:
1014 * @msg: a #GstSDPMessage
1016 * Get the number of time zone information entries in @msg.
1018 * Returns: the number of time zone information entries in @msg.
1020 DEFINE_ARRAY_LEN (zones);
1022 * gst_sdp_message_get_zone:
1023 * @msg: a #GstSDPMessage
1024 * @idx: the zone index
1026 * Get time zone information with index @idx from @msg.
1028 * Returns: a #GstSDPZone.
1030 DEFINE_ARRAY_GETTER (zone, zones, const GstSDPZone);
1033 * gst_sdp_message_add_zone:
1034 * @msg: a #GstSDPMessage
1035 * @adj_time: the NTP time that a time zone adjustment happens
1036 * @typed_time: the offset from the time when the session was first scheduled
1038 * Add time zone information to @msg.
1040 * Returns: a #GstSDPResult.
1043 gst_sdp_message_add_zone (GstSDPMessage * msg, const gchar * adj_time,
1044 const gchar * typed_time)
1048 zone.time = g_strdup (adj_time);
1049 zone.typed_time = g_strdup (typed_time);
1051 g_array_append_val (msg->zones, zone);
1057 * gst_sdp_message_set_key:
1058 * @msg: a #GstSDPMessage
1059 * @type: the encryption type
1060 * @data: the encryption data
1062 * Adds the encryption information to @msg.
1064 * Returns: a #GstSDPResult.
1067 gst_sdp_message_set_key (GstSDPMessage * msg, const gchar * type,
1070 REPLACE_STRING (msg->key.type, type);
1071 REPLACE_STRING (msg->key.data, data);
1077 * gst_sdp_message_get_key:
1078 * @msg: a #GstSDPMessage
1080 * Get the encryption information from @msg.
1082 * Returns: a #GstSDPKey.
1085 gst_sdp_message_get_key (const GstSDPMessage * msg)
1091 * gst_sdp_message_attributes_len:
1092 * @msg: a #GstSDPMessage
1094 * Get the number of attributes in @msg.
1096 * Returns: the number of attributes in @msg.
1098 DEFINE_ARRAY_LEN (attributes);
1101 * gst_sdp_message_get_attribute:
1102 * @msg: a #GstSDPMessage
1105 * Get the attribute at position @idx in @msg.
1107 * Returns: the #GstSDPAttribute at position @idx.
1109 DEFINE_ARRAY_GETTER (attribute, attributes, const GstSDPAttribute);
1112 * gst_sdp_message_get_attribute_val_n:
1113 * @msg: a #GstSDPMessage
1117 * Get the @nth attribute with key @key in @msg.
1119 * Returns: the attribute value of the @nth attribute with @key.
1122 gst_sdp_message_get_attribute_val_n (const GstSDPMessage * msg,
1123 const gchar * key, guint nth)
1127 for (i = 0; i < msg->attributes->len; i++) {
1128 GstSDPAttribute *attr;
1130 attr = &g_array_index (msg->attributes, GstSDPAttribute, i);
1131 if (!strcmp (attr->key, key)) {
1142 * gst_sdp_message_get_attribute_val:
1143 * @msg: a #GstSDPMessage
1146 * Get the first attribute with key @key in @msg.
1148 * Returns: the attribute value of the first attribute with @key.
1151 gst_sdp_message_get_attribute_val (const GstSDPMessage * msg, const gchar * key)
1153 return gst_sdp_message_get_attribute_val_n (msg, key, 0);
1157 * gst_sdp_message_add_attribute:
1158 * @msg: a #GstSDPMessage
1162 * Add the attribute with @key and @value to @msg.
1164 * Returns: @GST_SDP_OK.
1167 gst_sdp_message_add_attribute (GstSDPMessage * msg, const gchar * key,
1168 const gchar * value)
1170 GstSDPAttribute attr;
1172 attr.key = g_strdup (key);
1173 attr.value = g_strdup (value);
1175 g_array_append_val (msg->attributes, attr);
1181 * gst_sdp_message_medias_len:
1182 * @msg: a #GstSDPMessage
1184 * Get the number of media descriptions in @msg.
1186 * Returns: the number of media descriptions in @msg.
1188 DEFINE_ARRAY_LEN (medias);
1190 * gst_sdp_message_get_media:
1191 * @msg: a #GstSDPMessage
1194 * Get the media description at index @idx in @msg.
1196 * Returns: a #GstSDPMedia.
1198 DEFINE_ARRAY_GETTER (media, medias, const GstSDPMedia);
1201 * gst_sdp_message_add_media:
1202 * @msg: a #GstSDPMessage
1203 * @media: a #GstSDPMedia to add
1205 * Adds @media to the array of medias in @msg. This function takes ownership of
1206 * the contents of @media so that @media will have to be reinitialized with
1207 * gst_media_init() before it can be used again.
1209 * Returns: a #GstSDPResult.
1212 gst_sdp_message_add_media (GstSDPMessage * msg, GstSDPMedia * media)
1215 GstSDPMedia *nmedia;
1217 len = msg->medias->len;
1218 g_array_set_size (msg->medias, len + 1);
1219 nmedia = &g_array_index (msg->medias, GstSDPMedia, len);
1221 memcpy (nmedia, media, sizeof (GstSDPMedia));
1222 memset (media, 0, sizeof (GstSDPMedia));
1230 * gst_sdp_media_new:
1231 * @media: pointer to new #GstSDPMedia
1233 * Allocate a new GstSDPMedia and store the result in @media.
1235 * Returns: a #GstSDPResult.
1238 gst_sdp_media_new (GstSDPMedia ** media)
1240 GstSDPMedia *newmedia;
1242 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1244 newmedia = g_new0 (GstSDPMedia, 1);
1248 return gst_sdp_media_init (newmedia);
1252 * gst_sdp_media_init:
1253 * @media: a #GstSDPMedia
1255 * Initialize @media so that its contents are as if it was freshly allocated
1256 * with gst_sdp_media_new(). This function is mostly used to initialize a media
1257 * allocated on the stack. gst_sdp_media_uninit() undoes this operation.
1259 * When this function is invoked on newly allocated data (with malloc or on the
1260 * stack), its contents should be set to 0 before calling this function.
1262 * Returns: a #GstSDPResult.
1265 gst_sdp_media_init (GstSDPMedia * media)
1267 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1269 FREE_STRING (media->media);
1271 media->num_ports = 0;
1272 FREE_STRING (media->proto);
1273 INIT_PTR_ARRAY (media->fmts, gchar *, g_free);
1274 FREE_STRING (media->information);
1275 INIT_ARRAY (media->connections, GstSDPConnection, gst_sdp_connection_init);
1276 INIT_ARRAY (media->bandwidths, GstSDPBandwidth, gst_sdp_bandwidth_init);
1277 gst_sdp_key_init (&media->key);
1278 INIT_ARRAY (media->attributes, GstSDPAttribute, gst_sdp_attribute_init);
1284 * gst_sdp_media_uninit:
1285 * @media: a #GstSDPMedia
1287 * Free all resources allocated in @media. @media should not be used anymore after
1288 * this function. This function should be used when @media was allocated on the
1289 * stack and initialized with gst_sdp_media_init().
1291 * Returns: a #GstSDPResult.
1294 gst_sdp_media_uninit (GstSDPMedia * media)
1296 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1298 gst_sdp_media_init (media);
1299 FREE_PTR_ARRAY (media->fmts);
1300 FREE_ARRAY (media->connections);
1301 FREE_ARRAY (media->bandwidths);
1302 FREE_ARRAY (media->attributes);
1308 * gst_sdp_media_free:
1309 * @media: a #GstSDPMedia
1311 * Free all resources allocated by @media. @media should not be used anymore after
1312 * this function. This function should be used when @media was dynamically
1313 * allocated with gst_sdp_media_new().
1315 * Returns: a #GstSDPResult.
1318 gst_sdp_media_free (GstSDPMedia * media)
1320 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1322 gst_sdp_media_uninit (media);
1329 * gst_sdp_media_as_text:
1330 * @media: a #GstSDPMedia
1332 * Convert the contents of @media to a text string.
1334 * Returns: A dynamically allocated string representing the media.
1337 gst_sdp_media_as_text (const GstSDPMedia * media)
1342 g_return_val_if_fail (media != NULL, NULL);
1344 lines = g_string_new ("");
1347 g_string_append_printf (lines, "m=%s", media->media);
1349 g_string_append_printf (lines, " %u", media->port);
1351 if (media->num_ports > 1)
1352 g_string_append_printf (lines, "/%u", media->num_ports);
1354 g_string_append_printf (lines, " %s", media->proto);
1356 for (i = 0; i < gst_sdp_media_formats_len (media); i++)
1357 g_string_append_printf (lines, " %s", gst_sdp_media_get_format (media, i));
1358 g_string_append_printf (lines, "\r\n");
1360 if (media->information)
1361 g_string_append_printf (lines, "i=%s", media->information);
1363 for (i = 0; i < gst_sdp_media_connections_len (media); i++) {
1364 const GstSDPConnection *conn = gst_sdp_media_get_connection (media, i);
1366 if (conn->nettype && conn->addrtype && conn->address) {
1367 g_string_append_printf (lines, "c=%s %s %s", conn->nettype,
1368 conn->addrtype, conn->address);
1369 if (gst_sdp_address_is_multicast (conn->nettype, conn->addrtype,
1371 /* only add TTL for IP4 multicast */
1372 if (strcmp (conn->addrtype, "IP4") == 0)
1373 g_string_append_printf (lines, "/%u", conn->ttl);
1374 if (conn->addr_number > 1)
1375 g_string_append_printf (lines, "/%u", conn->addr_number);
1377 g_string_append_printf (lines, "\r\n");
1381 for (i = 0; i < gst_sdp_media_bandwidths_len (media); i++) {
1382 const GstSDPBandwidth *bandwidth = gst_sdp_media_get_bandwidth (media, i);
1384 g_string_append_printf (lines, "b=%s:%u\r\n", bandwidth->bwtype,
1385 bandwidth->bandwidth);
1388 if (media->key.type) {
1389 g_string_append_printf (lines, "k=%s", media->key.type);
1390 if (media->key.data)
1391 g_string_append_printf (lines, ":%s", media->key.data);
1392 g_string_append_printf (lines, "\r\n");
1395 for (i = 0; i < gst_sdp_media_attributes_len (media); i++) {
1396 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i);
1399 g_string_append_printf (lines, "a=%s", attr->key);
1401 g_string_append_printf (lines, ":%s", attr->value);
1402 g_string_append_printf (lines, "\r\n");
1406 return g_string_free (lines, FALSE);
1410 * gst_sdp_media_get_media:
1411 * @media: a #GstSDPMedia
1413 * Get the media description of @media.
1415 * Returns: the media description.
1418 gst_sdp_media_get_media (const GstSDPMedia * media)
1420 return media->media;
1424 * gst_sdp_media_set_media:
1425 * @media: a #GstSDPMedia
1426 * @med: the media description
1428 * Set the media description of @media to @med.
1430 * Returns: #GST_SDP_OK.
1433 gst_sdp_media_set_media (GstSDPMedia * media, const gchar * med)
1435 g_free (media->media);
1436 media->media = g_strdup (med);
1442 * gst_sdp_media_get_port:
1443 * @media: a #GstSDPMedia
1445 * Get the port number for @media.
1447 * Returns: the port number of @media.
1450 gst_sdp_media_get_port (const GstSDPMedia * media)
1456 * gst_sdp_media_get_num_ports:
1457 * @media: a #GstSDPMedia
1459 * Get the number of ports for @media.
1461 * Returns: the number of ports for @media.
1464 gst_sdp_media_get_num_ports (const GstSDPMedia * media)
1466 return media->num_ports;
1470 * gst_sdp_media_set_port_info:
1471 * @media: a #GstSDPMedia
1472 * @port: the port number
1473 * @num_ports: the number of ports
1475 * Set the port information in @media.
1477 * Returns: #GST_SDP_OK.
1480 gst_sdp_media_set_port_info (GstSDPMedia * media, guint port, guint num_ports)
1483 media->num_ports = num_ports;
1489 * gst_sdp_media_get_proto:
1490 * @media: a #GstSDPMedia
1492 * Get the transport protocol of @media
1494 * Returns: the transport protocol of @media.
1497 gst_sdp_media_get_proto (const GstSDPMedia * media)
1499 return media->proto;
1503 * gst_sdp_media_set_proto:
1504 * @media: a #GstSDPMedia
1505 * @proto: the media transport protocol
1507 * Set the media transport protocol of @media to @proto.
1509 * Returns: #GST_SDP_OK.
1512 gst_sdp_media_set_proto (GstSDPMedia * media, const gchar * proto)
1514 g_free (media->proto);
1515 media->proto = g_strdup (proto);
1521 * gst_sdp_media_formats_len:
1522 * @media: a #GstSDPMedia
1524 * Get the number of formats in @media.
1526 * Returns: the number of formats in @media.
1529 gst_sdp_media_formats_len (const GstSDPMedia * media)
1531 return media->fmts->len;
1535 * gst_sdp_media_get_format:
1536 * @media: a #GstSDPMedia
1539 * Get the format information at position @idx in @media.
1541 * Returns: the format at position @idx.
1544 gst_sdp_media_get_format (const GstSDPMedia * media, guint idx)
1546 if (idx >= media->fmts->len)
1548 return g_array_index (media->fmts, gchar *, idx);
1552 * gst_sdp_media_add_format:
1553 * @media: a #GstSDPMedia
1554 * @format: the format
1556 * Add the format information to @media.
1558 * Returns: #GST_SDP_OK.
1561 gst_sdp_media_add_format (GstSDPMedia * media, const gchar * format)
1565 fmt = g_strdup (format);
1567 g_array_append_val (media->fmts, fmt);
1573 * gst_sdp_media_get_information:
1574 * @media: a #GstSDPMedia
1576 * Get the information of @media
1578 * Returns: the information of @media.
1581 gst_sdp_media_get_information (const GstSDPMedia * media)
1583 return media->information;
1587 * gst_sdp_media_set_information:
1588 * @media: a #GstSDPMedia
1589 * @information: the media information
1591 * Set the media information of @media to @information.
1593 * Returns: #GST_SDP_OK.
1596 gst_sdp_media_set_information (GstSDPMedia * media, const gchar * information)
1598 g_free (media->information);
1599 media->information = g_strdup (information);
1605 * gst_sdp_media_connections_len:
1606 * @media: a #GstSDPMedia
1608 * Get the number of connection fields in @media.
1610 * Returns: the number of connections in @media.
1613 gst_sdp_media_connections_len (const GstSDPMedia * media)
1615 return media->connections->len;
1619 * gst_sdp_media_get_connection:
1620 * @media: a #GstSDPMedia
1623 * Get the connection at position @idx in @media.
1625 * Returns: the #GstSDPConnection at position @idx.
1627 const GstSDPConnection *
1628 gst_sdp_media_get_connection (const GstSDPMedia * media, guint idx)
1630 return &g_array_index (media->connections, GstSDPConnection, idx);
1634 * gst_sdp_media_add_connection:
1635 * @media: a #GstSDPMedia
1636 * @nettype: the type of network. "IN" is defined to have the meaning
1638 * @addrtype: the type of address.
1639 * @address: the address
1640 * @ttl: the time to live of the address
1641 * @addr_number: the number of layers
1643 * Add the given connection parameters to @media.
1645 * Returns: a #GstSDPResult.
1648 gst_sdp_media_add_connection (GstSDPMedia * media, const gchar * nettype,
1649 const gchar * addrtype, const gchar * address, guint ttl, guint addr_number)
1651 GstSDPConnection conn;
1653 conn.nettype = g_strdup (nettype);
1654 conn.addrtype = g_strdup (addrtype);
1655 conn.address = g_strdup (address);
1657 conn.addr_number = addr_number;
1659 g_array_append_val (media->connections, conn);
1665 * gst_sdp_media_bandwidths_len:
1666 * @media: a #GstSDPMedia
1668 * Get the number of bandwidth fields in @media.
1670 * Returns: the number of bandwidths in @media.
1673 gst_sdp_media_bandwidths_len (const GstSDPMedia * media)
1675 return media->bandwidths->len;
1679 * gst_sdp_media_get_bandwidth:
1680 * @media: a #GstSDPMedia
1683 * Get the bandwidth at position @idx in @media.
1685 * Returns: the #GstSDPBandwidth at position @idx.
1687 const GstSDPBandwidth *
1688 gst_sdp_media_get_bandwidth (const GstSDPMedia * media, guint idx)
1690 return &g_array_index (media->bandwidths, GstSDPBandwidth, idx);
1694 * gst_sdp_media_add_bandwidth:
1695 * @media: a #GstSDPMedia
1696 * @bwtype: the bandwidth modifier type
1697 * @bandwidth: the bandwidth in kilobits per second
1699 * Add the bandwidth information with @bwtype and @bandwidth to @media.
1701 * Returns: #GST_SDP_OK.
1704 gst_sdp_media_add_bandwidth (GstSDPMedia * media, const gchar * bwtype,
1709 bw.bwtype = g_strdup (bwtype);
1710 bw.bandwidth = bandwidth;
1712 g_array_append_val (media->bandwidths, bw);
1718 * gst_sdp_media_set_key:
1719 * @media: a #GstSDPMedia
1720 * @type: the encryption type
1721 * @data: the encryption data
1723 * Adds the encryption information to @media.
1725 * Returns: a #GstSDPResult.
1728 gst_sdp_media_set_key (GstSDPMedia * media, const gchar * type,
1731 g_free (media->key.type);
1732 media->key.type = g_strdup (type);
1733 g_free (media->key.data);
1734 media->key.data = g_strdup (data);
1740 * gst_sdp_media_get_key:
1741 * @media: a #GstSDPMedia
1743 * Get the encryption information from @media.
1745 * Returns: a #GstSDPKey.
1748 gst_sdp_media_get_key (const GstSDPMedia * media)
1754 * gst_sdp_media_attributes_len:
1755 * @media: a #GstSDPMedia
1757 * Get the number of attribute fields in @media.
1759 * Returns: the number of attributes in @media.
1762 gst_sdp_media_attributes_len (const GstSDPMedia * media)
1764 return media->attributes->len;
1768 * gst_sdp_media_add_attribute:
1769 * @media: a #GstSDPMedia
1773 * Add the attribute with @key and @value to @media.
1775 * Returns: #GST_SDP_OK.
1778 gst_sdp_media_add_attribute (GstSDPMedia * media, const gchar * key,
1779 const gchar * value)
1781 GstSDPAttribute attr;
1783 attr.key = g_strdup (key);
1784 attr.value = g_strdup (value);
1786 g_array_append_val (media->attributes, attr);
1792 * gst_sdp_media_get_attribute:
1793 * @media: a #GstSDPMedia
1796 * Get the attribute at position @idx in @media.
1798 * Returns: the #GstSDPAttribute at position @idx.
1800 const GstSDPAttribute *
1801 gst_sdp_media_get_attribute (const GstSDPMedia * media, guint idx)
1803 return &g_array_index (media->attributes, GstSDPAttribute, idx);
1807 * gst_sdp_media_get_attribute_val_n:
1808 * @media: a #GstSDPMedia
1812 * Get the @nth attribute value for @key in @media.
1814 * Returns: the @nth attribute value.
1817 gst_sdp_media_get_attribute_val_n (const GstSDPMedia * media, const gchar * key,
1822 for (i = 0; i < media->attributes->len; i++) {
1823 GstSDPAttribute *attr;
1825 attr = &g_array_index (media->attributes, GstSDPAttribute, i);
1826 if (!strcmp (attr->key, key)) {
1837 * gst_sdp_media_get_attribute_val:
1838 * @media: a #GstSDPMedia
1841 * Get the first attribute value for @key in @media.
1843 * Returns: the first attribute value for @key.
1846 gst_sdp_media_get_attribute_val (const GstSDPMedia * media, const gchar * key)
1848 return gst_sdp_media_get_attribute_val_n (media, key, 0);
1852 read_string (gchar * dest, guint size, gchar ** src)
1858 while (g_ascii_isspace (**src))
1861 while (!g_ascii_isspace (**src) && **src != '\0') {
1863 dest[idx++] = **src;
1871 read_string_del (gchar * dest, guint size, gchar del, gchar ** src)
1877 while (g_ascii_isspace (**src))
1880 while (**src != del && **src != '\0') {
1882 dest[idx++] = **src;
1903 gst_sdp_parse_line (SDPContext * c, gchar type, gchar * buffer)
1908 #define READ_STRING(field) read_string (str, sizeof (str), &p); REPLACE_STRING (field, str)
1909 #define READ_UINT(field) read_string (str, sizeof (str), &p); field = strtoul (str, NULL, 10)
1913 if (buffer[0] != '0')
1914 g_warning ("wrong SDP version");
1915 gst_sdp_message_set_version (c->msg, buffer);
1918 READ_STRING (c->msg->origin.username);
1919 READ_STRING (c->msg->origin.sess_id);
1920 READ_STRING (c->msg->origin.sess_version);
1921 READ_STRING (c->msg->origin.nettype);
1922 READ_STRING (c->msg->origin.addrtype);
1923 READ_STRING (c->msg->origin.addr);
1926 REPLACE_STRING (c->msg->session_name, buffer);
1929 if (c->state == SDP_SESSION) {
1930 REPLACE_STRING (c->msg->information, buffer);
1932 REPLACE_STRING (c->media->information, buffer);
1936 REPLACE_STRING (c->msg->uri, buffer);
1939 gst_sdp_message_add_email (c->msg, buffer);
1942 gst_sdp_message_add_phone (c->msg, buffer);
1946 GstSDPConnection conn;
1949 memset (&conn, 0, sizeof (conn));
1952 while ((str2 = strchr (str2, '/')))
1954 READ_STRING (conn.nettype);
1955 READ_STRING (conn.addrtype);
1956 READ_STRING (conn.address);
1957 /* only read TTL for IP4 */
1958 if (strcmp (conn.addrtype, "IP4") == 0)
1959 READ_UINT (conn.ttl);
1960 READ_UINT (conn.addr_number);
1962 if (c->state == SDP_SESSION) {
1963 gst_sdp_message_set_connection (c->msg, conn.nettype, conn.addrtype,
1964 conn.address, conn.ttl, conn.addr_number);
1966 gst_sdp_media_add_connection (c->media, conn.nettype, conn.addrtype,
1967 conn.address, conn.ttl, conn.addr_number);
1969 gst_sdp_connection_init (&conn);
1974 gchar str2[MAX_LINE_LEN];
1976 read_string_del (str, sizeof (str), ':', &p);
1979 read_string (str2, sizeof (str2), &p);
1980 if (c->state == SDP_SESSION)
1981 gst_sdp_message_add_bandwidth (c->msg, str, atoi (str2));
1983 gst_sdp_media_add_bandwidth (c->media, str, atoi (str2));
1991 read_string_del (str, sizeof (str), ':', &p);
1994 if (c->state == SDP_SESSION)
1995 gst_sdp_message_add_attribute (c->msg, str, p);
1997 gst_sdp_media_add_attribute (c->media, str, p);
2004 c->state = SDP_MEDIA;
2005 memset (&nmedia, 0, sizeof (nmedia));
2006 gst_sdp_media_init (&nmedia);
2008 /* m=<media> <port>/<number of ports> <proto> <fmt> ... */
2009 READ_STRING (nmedia.media);
2010 read_string (str, sizeof (str), &p);
2011 slash = g_strrstr (str, "/");
2014 nmedia.port = atoi (str);
2015 nmedia.num_ports = atoi (slash + 1);
2017 nmedia.port = atoi (str);
2018 nmedia.num_ports = -1;
2020 READ_STRING (nmedia.proto);
2022 read_string (str, sizeof (str), &p);
2023 gst_sdp_media_add_format (&nmedia, str);
2024 } while (*p != '\0');
2026 gst_sdp_message_add_media (c->msg, &nmedia);
2028 &g_array_index (c->msg->medias, GstSDPMedia, c->msg->medias->len - 1);
2038 * gst_sdp_message_parse_buffer:
2039 * @data: the start of the buffer
2040 * @size: the size of the buffer
2041 * @msg: the result #GstSDPMessage
2043 * Parse the contents of @size bytes pointed to by @data and store the result in
2046 * Returns: #GST_SDP_OK on success.
2049 gst_sdp_message_parse_buffer (const guint8 * data, guint size,
2050 GstSDPMessage * msg)
2055 gchar buffer[MAX_LINE_LEN];
2058 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
2059 g_return_val_if_fail (data != NULL, GST_SDP_EINVAL);
2060 g_return_val_if_fail (size != 0, GST_SDP_EINVAL);
2062 c.state = SDP_SESSION;
2068 while (g_ascii_isspace (*p))
2080 while (*p != '\n' && *p != '\r' && *p != '\0') {
2081 if (idx < sizeof (buffer) - 1)
2086 gst_sdp_parse_line (&c, type, buffer);
2089 while (*p != '\n' && *p != '\0')
2099 print_media (GstSDPMedia * media)
2101 g_print (" media: '%s'\n", GST_STR_NULL (media->media));
2102 g_print (" port: '%u'\n", media->port);
2103 g_print (" num_ports: '%u'\n", media->num_ports);
2104 g_print (" proto: '%s'\n", GST_STR_NULL (media->proto));
2105 if (media->fmts->len > 0) {
2108 g_print (" formats:\n");
2109 for (i = 0; i < media->fmts->len; i++) {
2110 g_print (" format '%s'\n", g_array_index (media->fmts, gchar *, i));
2113 g_print (" information: '%s'\n", GST_STR_NULL (media->information));
2114 if (media->connections->len > 0) {
2117 g_print (" connections:\n");
2118 for (i = 0; i < media->connections->len; i++) {
2119 GstSDPConnection *conn =
2120 &g_array_index (media->connections, GstSDPConnection, i);
2122 g_print (" nettype: '%s'\n", GST_STR_NULL (conn->nettype));
2123 g_print (" addrtype: '%s'\n", GST_STR_NULL (conn->addrtype));
2124 g_print (" address: '%s'\n", GST_STR_NULL (conn->address));
2125 g_print (" ttl: '%u'\n", conn->ttl);
2126 g_print (" addr_number: '%u'\n", conn->addr_number);
2129 if (media->bandwidths->len > 0) {
2132 g_print (" bandwidths:\n");
2133 for (i = 0; i < media->bandwidths->len; i++) {
2134 GstSDPBandwidth *bw =
2135 &g_array_index (media->bandwidths, GstSDPBandwidth, i);
2137 g_print (" type: '%s'\n", GST_STR_NULL (bw->bwtype));
2138 g_print (" bandwidth: '%u'\n", bw->bandwidth);
2141 g_print (" key:\n");
2142 g_print (" type: '%s'\n", GST_STR_NULL (media->key.type));
2143 g_print (" data: '%s'\n", GST_STR_NULL (media->key.data));
2144 if (media->attributes->len > 0) {
2147 g_print (" attributes:\n");
2148 for (i = 0; i < media->attributes->len; i++) {
2149 GstSDPAttribute *attr =
2150 &g_array_index (media->attributes, GstSDPAttribute, i);
2152 g_print (" attribute '%s' : '%s'\n", attr->key, attr->value);
2158 * gst_sdp_message_dump:
2159 * @msg: a #GstSDPMessage
2161 * Dump the parsed contents of @msg to stdout.
2163 * Returns: a #GstSDPResult.
2166 gst_sdp_message_dump (const GstSDPMessage * msg)
2168 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
2170 g_print ("sdp packet %p:\n", msg);
2171 g_print (" version: '%s'\n", GST_STR_NULL (msg->version));
2172 g_print (" origin:\n");
2173 g_print (" username: '%s'\n", GST_STR_NULL (msg->origin.username));
2174 g_print (" sess_id: '%s'\n", GST_STR_NULL (msg->origin.sess_id));
2175 g_print (" sess_version: '%s'\n", GST_STR_NULL (msg->origin.sess_version));
2176 g_print (" nettype: '%s'\n", GST_STR_NULL (msg->origin.nettype));
2177 g_print (" addrtype: '%s'\n", GST_STR_NULL (msg->origin.addrtype));
2178 g_print (" addr: '%s'\n", GST_STR_NULL (msg->origin.addr));
2179 g_print (" session_name: '%s'\n", GST_STR_NULL (msg->session_name));
2180 g_print (" information: '%s'\n", GST_STR_NULL (msg->information));
2181 g_print (" uri: '%s'\n", GST_STR_NULL (msg->uri));
2183 if (msg->emails->len > 0) {
2186 g_print (" emails:\n");
2187 for (i = 0; i < msg->emails->len; i++) {
2188 g_print (" email '%s'\n", g_array_index (msg->emails, gchar *, i));
2191 if (msg->phones->len > 0) {
2194 g_print (" phones:\n");
2195 for (i = 0; i < msg->phones->len; i++) {
2196 g_print (" phone '%s'\n", g_array_index (msg->phones, gchar *, i));
2199 g_print (" connection:\n");
2200 g_print (" nettype: '%s'\n", GST_STR_NULL (msg->connection.nettype));
2201 g_print (" addrtype: '%s'\n", GST_STR_NULL (msg->connection.addrtype));
2202 g_print (" address: '%s'\n", GST_STR_NULL (msg->connection.address));
2203 g_print (" ttl: '%u'\n", msg->connection.ttl);
2204 g_print (" addr_number: '%u'\n", msg->connection.addr_number);
2205 if (msg->bandwidths->len > 0) {
2208 g_print (" bandwidths:\n");
2209 for (i = 0; i < msg->bandwidths->len; i++) {
2210 GstSDPBandwidth *bw =
2211 &g_array_index (msg->bandwidths, GstSDPBandwidth, i);
2213 g_print (" type: '%s'\n", GST_STR_NULL (bw->bwtype));
2214 g_print (" bandwidth: '%u'\n", bw->bandwidth);
2217 g_print (" key:\n");
2218 g_print (" type: '%s'\n", GST_STR_NULL (msg->key.type));
2219 g_print (" data: '%s'\n", GST_STR_NULL (msg->key.data));
2220 if (msg->attributes->len > 0) {
2223 g_print (" attributes:\n");
2224 for (i = 0; i < msg->attributes->len; i++) {
2225 GstSDPAttribute *attr =
2226 &g_array_index (msg->attributes, GstSDPAttribute, i);
2228 g_print (" attribute '%s' : '%s'\n", attr->key, attr->value);
2231 if (msg->medias->len > 0) {
2234 g_print (" medias:\n");
2235 for (i = 0; i < msg->medias->len; i++) {
2236 g_print (" media %u:\n", i);
2237 print_media (&g_array_index (msg->medias, GstSDPMedia, i));