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 is_multicast_address (const gchar * host_name, guint * family)
328 struct addrinfo hints;
330 struct addrinfo *res;
331 gboolean ret = FALSE;
333 memset (&hints, 0, sizeof (hints));
334 hints.ai_socktype = SOCK_DGRAM;
336 g_return_val_if_fail (host_name, FALSE);
338 if (getaddrinfo (host_name, NULL, &hints, &res) < 0)
341 for (ai = res; !ret && ai; ai = ai->ai_next) {
342 if (ai->ai_family == AF_INET)
344 IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)->sin_addr.
348 IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai->ai_addr)->
351 *family = ai->ai_family;
360 * gst_sdp_message_as_text:
361 * @msg: a #GstSDPMessage
363 * Convert the contents of @msg to a text string.
365 * Returns: A dynamically allocated string representing the SDP description.
368 gst_sdp_message_as_text (const GstSDPMessage * msg)
370 /* change all vars so they match rfc? */
374 g_return_val_if_fail (msg != NULL, NULL);
376 lines = g_string_new ("");
379 g_string_append_printf (lines, "v=%s\r\n", msg->version);
381 if (msg->origin.sess_id && msg->origin.sess_version && msg->origin.nettype &&
382 msg->origin.addrtype && msg->origin.addr)
383 g_string_append_printf (lines, "o=%s %s %s %s %s %s\r\n",
384 msg->origin.username ? msg->origin.username : "-", msg->origin.sess_id,
385 msg->origin.sess_version, msg->origin.nettype, msg->origin.addrtype,
388 if (msg->session_name)
389 g_string_append_printf (lines, "s=%s\r\n", msg->session_name);
391 if (msg->information)
392 g_string_append_printf (lines, "i=%s\r\n", msg->information);
395 g_string_append_printf (lines, "u=%s\r\n", msg->uri);
397 for (i = 0; i < gst_sdp_message_emails_len (msg); i++)
398 g_string_append_printf (lines, "e=%s\r\n",
399 gst_sdp_message_get_email (msg, i));
401 for (i = 0; i < gst_sdp_message_phones_len (msg); i++)
402 g_string_append_printf (lines, "p=%s\r\n",
403 gst_sdp_message_get_phone (msg, i));
405 if (gst_sdp_message_emails_len (msg) == 0 &&
406 gst_sdp_message_phones_len (msg) == 0)
407 g_string_append_printf (lines, "e=NONE\r\n");
409 if (msg->connection.nettype && msg->connection.addrtype &&
410 msg->connection.address) {
413 g_string_append_printf (lines, "c=%s %s %s", msg->connection.nettype,
414 msg->connection.addrtype, msg->connection.address);
415 if (is_multicast_address (msg->connection.address, &family)) {
416 if (family == AF_INET)
417 g_string_append_printf (lines, "/%u", msg->connection.ttl);
418 if (msg->connection.addr_number > 1)
419 g_string_append_printf (lines, "/%u", msg->connection.addr_number);
421 g_string_append_printf (lines, "\r\n");
424 for (i = 0; i < gst_sdp_message_bandwidths_len (msg); i++) {
425 const GstSDPBandwidth *bandwidth = gst_sdp_message_get_bandwidth (msg, i);
427 g_string_append_printf (lines, "b=%s:%u\r\n", bandwidth->bwtype,
428 bandwidth->bandwidth);
431 for (i = 0; i < gst_sdp_message_times_len (msg); i++) {
432 const GstSDPTime *times = gst_sdp_message_get_time (msg, i);
434 g_string_append_printf (lines, "t=%s %s\r\n", times->start, times->stop);
436 if (times->repeat != NULL) {
439 g_string_append_printf (lines, "r=%s",
440 g_array_index (times->repeat, gchar *, 0));
441 for (j = 1; j < times->repeat->len; j++)
442 g_string_append_printf (lines, " %s",
443 g_array_index (times->repeat, gchar *, j));
444 g_string_append_printf (lines, "\r\n");
448 if (gst_sdp_message_zones_len (msg) > 0) {
449 const GstSDPZone *zone = gst_sdp_message_get_zone (msg, 0);
451 g_string_append_printf (lines, "z=%s %s", zone->time, zone->typed_time);
452 for (i = 1; i < gst_sdp_message_zones_len (msg); i++) {
453 zone = gst_sdp_message_get_zone (msg, i);
454 g_string_append_printf (lines, " %s %s", zone->time, zone->typed_time);
456 g_string_append_printf (lines, "\r\n");
460 g_string_append_printf (lines, "k=%s", msg->key.type);
462 g_string_append_printf (lines, ":%s", msg->key.data);
463 g_string_append_printf (lines, "\r\n");
466 for (i = 0; i < gst_sdp_message_attributes_len (msg); i++) {
467 const GstSDPAttribute *attr = gst_sdp_message_get_attribute (msg, i);
470 g_string_append_printf (lines, "a=%s", attr->key);
472 g_string_append_printf (lines, ":%s", attr->value);
473 g_string_append_printf (lines, "\r\n");
477 for (i = 0; i < gst_sdp_message_medias_len (msg); i++) {
478 const GstSDPMedia *media = gst_sdp_message_get_media (msg, i);
479 gchar *sdp_media_str;
481 sdp_media_str = gst_sdp_media_as_text (media);
482 g_string_append_printf (lines, "%s", sdp_media_str);
483 g_free (sdp_media_str);
486 return g_string_free (lines, FALSE);
490 * gst_sdp_message_set_version:
491 * @msg: a #GstSDPMessage
492 * @version: the version
494 * Set the version in @msg.
496 * Returns: a #GstSDPResult.
498 DEFINE_STRING_SETTER (version);
500 * gst_sdp_message_get_version:
501 * @msg: a #GstSDPMessage
503 * Get the version in @msg.
505 * Returns: a #GstSDPResult.
507 DEFINE_STRING_GETTER (version);
510 * gst_sdp_message_set_origin:
511 * @msg: a #GstSDPMessage
512 * @username: the user name
513 * @sess_id: a session id
514 * @sess_version: a session version
515 * @nettype: a network type
516 * @addrtype: an address type
519 * Configure the SDP origin in @msg with the given parameters.
521 * Returns: #GST_SDP_OK.
524 gst_sdp_message_set_origin (GstSDPMessage * msg, const gchar * username,
525 const gchar * sess_id, const gchar * sess_version, const gchar * nettype,
526 const gchar * addrtype, const gchar * addr)
528 REPLACE_STRING (msg->origin.username, username);
529 REPLACE_STRING (msg->origin.sess_id, sess_id);
530 REPLACE_STRING (msg->origin.sess_version, sess_version);
531 REPLACE_STRING (msg->origin.nettype, nettype);
532 REPLACE_STRING (msg->origin.addrtype, addrtype);
533 REPLACE_STRING (msg->origin.addr, addr);
539 * gst_sdp_message_get_origin:
540 * @msg: a #GstSDPMessage
542 * Get the origin of @msg.
544 * Returns: a #GstSDPOrigin. The result remains valid as long as @msg is valid.
547 gst_sdp_message_get_origin (const GstSDPMessage * msg)
553 * gst_sdp_message_set_session_name:
554 * @msg: a #GstSDPMessage
555 * @session_name: the session name
557 * Set the session name in @msg.
559 * Returns: a #GstSDPResult.
561 DEFINE_STRING_SETTER (session_name);
563 * gst_sdp_message_get_session_name:
564 * @msg: a #GstSDPMessage
566 * Get the session name in @msg.
568 * Returns: a #GstSDPResult.
570 DEFINE_STRING_GETTER (session_name);
572 * gst_sdp_message_set_information:
573 * @msg: a #GstSDPMessage
574 * @information: the information
576 * Set the information in @msg.
578 * Returns: a #GstSDPResult.
580 DEFINE_STRING_SETTER (information);
582 * gst_sdp_message_get_information:
583 * @msg: a #GstSDPMessage
585 * Get the information in @msg.
587 * Returns: a #GstSDPResult.
589 DEFINE_STRING_GETTER (information);
591 * gst_sdp_message_set_uri:
592 * @msg: a #GstSDPMessage
595 * Set the URI in @msg.
597 * Returns: a #GstSDPResult.
599 DEFINE_STRING_SETTER (uri);
601 * gst_sdp_message_get_uri:
602 * @msg: a #GstSDPMessage
604 * Get the URI in @msg.
606 * Returns: a #GstSDPResult.
608 DEFINE_STRING_GETTER (uri);
611 * gst_sdp_message_emails_len:
612 * @msg: a #GstSDPMessage
614 * Get the number of emails in @msg.
616 * Returns: the number of emails in @msg.
618 DEFINE_ARRAY_LEN (emails);
620 * gst_sdp_message_get_email:
621 * @msg: a #GstSDPMessage
622 * @idx: an email index
624 * Get the email with number @idx from @msg.
626 * Returns: the email at position @idx.
628 DEFINE_PTR_ARRAY_GETTER (email, emails, const gchar *);
631 * gst_sdp_message_add_email:
632 * @msg: a #GstSDPMessage
635 * Add @email to the list of emails in @msg.
637 * Returns: a #GstSDPResult.
639 DEFINE_PTR_ARRAY_ADDER (email, emails, const gchar *, g_strdup);
642 * gst_sdp_message_phones_len:
643 * @msg: a #GstSDPMessage
645 * Get the number of phones in @msg.
647 * Returns: the number of phones in @msg.
649 DEFINE_ARRAY_LEN (phones);
651 * gst_sdp_message_get_phone:
652 * @msg: a #GstSDPMessage
653 * @idx: a phone index
655 * Get the phone with number @idx from @msg.
657 * Returns: the phone at position @idx.
659 DEFINE_PTR_ARRAY_GETTER (phone, phones, const gchar *);
662 * gst_sdp_message_add_phone:
663 * @msg: a #GstSDPMessage
666 * Add @phone to the list of phones in @msg.
668 * Returns: a #GstSDPResult.
670 DEFINE_PTR_ARRAY_ADDER (phone, phones, const gchar *, g_strdup);
673 * gst_sdp_message_set_connection:
674 * @msg: a #GstSDPMessage
675 * @nettype: the type of network. "IN" is defined to have the meaning
677 * @addrtype: the type of address.
678 * @address: the address
679 * @ttl: the time to live of the address
680 * @addr_number: the number of layers
682 * Configure the SDP connection in @msg with the given parameters.
684 * Returns: a #GstSDPResult.
687 gst_sdp_message_set_connection (GstSDPMessage * msg, const gchar * nettype,
688 const gchar * addrtype, const gchar * address, guint ttl, guint addr_number)
690 REPLACE_STRING (msg->connection.nettype, nettype);
691 REPLACE_STRING (msg->connection.addrtype, addrtype);
692 REPLACE_STRING (msg->connection.address, address);
693 msg->connection.ttl = ttl;
694 msg->connection.addr_number = addr_number;
700 * gst_sdp_message_get_connection:
701 * @msg: a #GstSDPMessage
703 * Get the connection of @msg.
705 * Returns: a #GstSDPConnection. The result remains valid as long as @msg is valid.
707 const GstSDPConnection *
708 gst_sdp_message_get_connection (const GstSDPMessage * msg)
710 return &msg->connection;
714 * gst_sdp_message_bandwidths_len:
715 * @msg: a #GstSDPMessage
717 * Get the number of bandwidth information in @msg.
719 * Returns: the number of bandwidth information in @msg.
721 DEFINE_ARRAY_LEN (bandwidths);
723 * gst_sdp_message_get_bandwidth:
724 * @msg: a #GstSDPMessage
725 * @idx: the bandwidth index
727 * Get the bandwidth at index @idx from @msg.
729 * Returns: a #GstSDPBandwidth.
731 DEFINE_ARRAY_GETTER (bandwidth, bandwidths, const GstSDPBandwidth);
734 * gst_sdp_message_add_bandwidth:
735 * @msg: a #GstSDPMessage
736 * @bwtype: the bandwidth modifier type
737 * @bandwidth: the bandwidth in kilobits per second
739 * Add the specified bandwidth information to @msg.
741 * Returns: a #GstSDPResult.
745 gst_sdp_message_add_bandwidth (GstSDPMessage * msg, const gchar * bwtype,
750 bw.bwtype = g_strdup (bwtype);
751 bw.bandwidth = bandwidth;
753 g_array_append_val (msg->bandwidths, bw);
759 * gst_sdp_message_times_len:
760 * @msg: a #GstSDPMessage
762 * Get the number of time information entries in @msg.
764 * Returns: the number of time information entries in @msg.
766 DEFINE_ARRAY_LEN (times);
769 * gst_sdp_message_get_time:
770 * @msg: a #GstSDPMessage
771 * @idx: the time index
773 * Get time information with index @idx from @msg.
775 * Returns: a #GstSDPTime.
777 DEFINE_ARRAY_GETTER (time, times, const GstSDPTime);
780 * gst_sdp_message_add_time:
781 * @msg: a #GstSDPMessage
782 * @start: the start time
783 * @stop: the stop time
784 * @repeat: the repeat times
786 * Add time information @start and @stop to @msg.
788 * Returns: a #GstSDPResult.
791 gst_sdp_message_add_time (GstSDPMessage * msg, const gchar * start,
792 const gchar * stop, const gchar ** repeat)
796 times.start = g_strdup (start);
797 times.stop = g_strdup (stop);
799 times.repeat = g_array_new (FALSE, TRUE, sizeof (gchar *));
800 for (; *repeat; repeat++) {
801 gchar *r = g_strdup (*repeat);
803 g_array_append_val (times.repeat, r);
807 g_array_append_val (msg->times, times);
813 * gst_sdp_message_zones_len:
814 * @msg: a #GstSDPMessage
816 * Get the number of time zone information entries in @msg.
818 * Returns: the number of time zone information entries in @msg.
820 DEFINE_ARRAY_LEN (zones);
822 * gst_sdp_message_get_zone:
823 * @msg: a #GstSDPMessage
824 * @idx: the zone index
826 * Get time zone information with index @idx from @msg.
828 * Returns: a #GstSDPZone.
830 DEFINE_ARRAY_GETTER (zone, zones, const GstSDPZone);
833 * gst_sdp_message_add_zone:
834 * @msg: a #GstSDPMessage
835 * @adj_time: the NTP time that a time zone adjustment happens
836 * @typed_time: the offset from the time when the session was first scheduled
838 * Add time zone information to @msg.
840 * Returns: a #GstSDPResult.
843 gst_sdp_message_add_zone (GstSDPMessage * msg, const gchar * adj_time,
844 const gchar * typed_time)
848 zone.time = g_strdup (adj_time);
849 zone.typed_time = g_strdup (typed_time);
851 g_array_append_val (msg->zones, zone);
857 * gst_sdp_message_set_key:
858 * @msg: a #GstSDPMessage
859 * @type: the encryption type
860 * @data: the encryption data
862 * Adds the encryption information to @msg.
864 * Returns: a #GstSDPResult.
867 gst_sdp_message_set_key (GstSDPMessage * msg, const gchar * type,
870 REPLACE_STRING (msg->key.type, type);
871 REPLACE_STRING (msg->key.data, data);
877 * gst_sdp_message_get_key:
878 * @msg: a #GstSDPMessage
880 * Get the encryption information from @msg.
882 * Returns: a #GstSDPKey.
885 gst_sdp_message_get_key (const GstSDPMessage * msg)
891 * gst_sdp_message_attributes_len:
892 * @msg: a #GstSDPMessage
894 * Get the number of attributes in @msg.
896 * Returns: the number of attributes in @msg.
898 DEFINE_ARRAY_LEN (attributes);
901 * gst_sdp_message_get_attribute:
902 * @msg: a #GstSDPMessage
905 * Get the attribute at position @idx in @msg.
907 * Returns: the #GstSDPAttribute at position @idx.
909 DEFINE_ARRAY_GETTER (attribute, attributes, const GstSDPAttribute);
912 * gst_sdp_message_get_attribute_val_n:
913 * @msg: a #GstSDPMessage
917 * Get the @nth attribute with key @key in @msg.
919 * Returns: the attribute value of the @nth attribute with @key.
922 gst_sdp_message_get_attribute_val_n (const GstSDPMessage * msg,
923 const gchar * key, guint nth)
927 for (i = 0; i < msg->attributes->len; i++) {
928 GstSDPAttribute *attr;
930 attr = &g_array_index (msg->attributes, GstSDPAttribute, i);
931 if (!strcmp (attr->key, key)) {
942 * gst_sdp_message_get_attribute_val:
943 * @msg: a #GstSDPMessage
946 * Get the first attribute with key @key in @msg.
948 * Returns: the attribute value of the first attribute with @key.
951 gst_sdp_message_get_attribute_val (const GstSDPMessage * msg, const gchar * key)
953 return gst_sdp_message_get_attribute_val_n (msg, key, 0);
957 * gst_sdp_message_add_attribute:
958 * @msg: a #GstSDPMessage
962 * Add the attribute with @key and @value to @msg.
964 * Returns: @GST_SDP_OK.
967 gst_sdp_message_add_attribute (GstSDPMessage * msg, const gchar * key,
970 GstSDPAttribute attr;
972 attr.key = g_strdup (key);
973 attr.value = g_strdup (value);
975 g_array_append_val (msg->attributes, attr);
981 * gst_sdp_message_medias_len:
982 * @msg: a #GstSDPMessage
984 * Get the number of media descriptions in @msg.
986 * Returns: the number of media descriptions in @msg.
988 DEFINE_ARRAY_LEN (medias);
990 * gst_sdp_message_get_media:
991 * @msg: a #GstSDPMessage
994 * Get the media description at index @idx in @msg.
996 * Returns: a #GstSDPMedia.
998 DEFINE_ARRAY_GETTER (media, medias, const GstSDPMedia);
1001 * gst_sdp_message_add_media:
1002 * @msg: a #GstSDPMessage
1003 * @media: a #GstSDPMedia to add
1005 * Adds @media to the array of medias in @msg. This function takes ownership of
1006 * the contents of @media so that @media will have to be reinitialized with
1007 * gst_media_init() before it can be used again.
1009 * Returns: a #GstSDPResult.
1012 gst_sdp_message_add_media (GstSDPMessage * msg, GstSDPMedia * media)
1015 GstSDPMedia *nmedia;
1017 len = msg->medias->len;
1018 g_array_set_size (msg->medias, len + 1);
1019 nmedia = &g_array_index (msg->medias, GstSDPMedia, len);
1021 memcpy (nmedia, media, sizeof (GstSDPMedia));
1022 memset (media, 0, sizeof (GstSDPMedia));
1030 * gst_sdp_media_new:
1031 * @media: pointer to new #GstSDPMedia
1033 * Allocate a new GstSDPMedia and store the result in @media.
1035 * Returns: a #GstSDPResult.
1038 gst_sdp_media_new (GstSDPMedia ** media)
1040 GstSDPMedia *newmedia;
1042 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1044 newmedia = g_new0 (GstSDPMedia, 1);
1048 return gst_sdp_media_init (newmedia);
1052 * gst_sdp_media_init:
1053 * @media: a #GstSDPMedia
1055 * Initialize @media so that its contents are as if it was freshly allocated
1056 * with gst_sdp_media_new(). This function is mostly used to initialize a media
1057 * allocated on the stack. gst_sdp_media_uninit() undoes this operation.
1059 * When this function is invoked on newly allocated data (with malloc or on the
1060 * stack), its contents should be set to 0 before calling this function.
1062 * Returns: a #GstSDPResult.
1065 gst_sdp_media_init (GstSDPMedia * media)
1067 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1069 FREE_STRING (media->media);
1071 media->num_ports = 0;
1072 FREE_STRING (media->proto);
1073 INIT_PTR_ARRAY (media->fmts, gchar *, g_free);
1074 FREE_STRING (media->information);
1075 INIT_ARRAY (media->connections, GstSDPConnection, gst_sdp_connection_init);
1076 INIT_ARRAY (media->bandwidths, GstSDPBandwidth, gst_sdp_bandwidth_init);
1077 gst_sdp_key_init (&media->key);
1078 INIT_ARRAY (media->attributes, GstSDPAttribute, gst_sdp_attribute_init);
1084 * gst_sdp_media_uninit:
1085 * @media: a #GstSDPMedia
1087 * Free all resources allocated in @media. @media should not be used anymore after
1088 * this function. This function should be used when @media was allocated on the
1089 * stack and initialized with gst_sdp_media_init().
1091 * Returns: a #GstSDPResult.
1094 gst_sdp_media_uninit (GstSDPMedia * media)
1096 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1098 gst_sdp_media_init (media);
1099 FREE_PTR_ARRAY (media->fmts);
1100 FREE_ARRAY (media->connections);
1101 FREE_ARRAY (media->bandwidths);
1102 FREE_ARRAY (media->attributes);
1108 * gst_sdp_media_free:
1109 * @media: a #GstSDPMedia
1111 * Free all resources allocated by @media. @media should not be used anymore after
1112 * this function. This function should be used when @media was dynamically
1113 * allocated with gst_sdp_media_new().
1115 * Returns: a #GstSDPResult.
1118 gst_sdp_media_free (GstSDPMedia * media)
1120 g_return_val_if_fail (media != NULL, GST_SDP_EINVAL);
1122 gst_sdp_media_uninit (media);
1129 * gst_sdp_media_as_text:
1130 * @media: a #GstSDPMedia
1132 * Convert the contents of @media to a text string.
1134 * Returns: A dynamically allocated string representing the media.
1137 gst_sdp_media_as_text (const GstSDPMedia * media)
1142 g_return_val_if_fail (media != NULL, NULL);
1144 lines = g_string_new ("");
1147 g_string_append_printf (lines, "m=%s", media->media);
1149 g_string_append_printf (lines, " %u", media->port);
1151 if (media->num_ports > 1)
1152 g_string_append_printf (lines, "/%u", media->num_ports);
1154 g_string_append_printf (lines, " %s", media->proto);
1156 for (i = 0; i < gst_sdp_media_formats_len (media); i++)
1157 g_string_append_printf (lines, " %s", gst_sdp_media_get_format (media, i));
1158 g_string_append_printf (lines, "\r\n");
1160 if (media->information)
1161 g_string_append_printf (lines, "i=%s", media->information);
1163 for (i = 0; i < gst_sdp_media_connections_len (media); i++) {
1164 const GstSDPConnection *conn = gst_sdp_media_get_connection (media, i);
1166 if (conn->nettype && conn->addrtype && conn->address) {
1169 g_string_append_printf (lines, "c=%s %s %s", conn->nettype,
1170 conn->addrtype, conn->address);
1171 if (is_multicast_address (conn->address, &family)) {
1172 if (family == AF_INET)
1173 g_string_append_printf (lines, "/%u", conn->ttl);
1174 if (conn->addr_number > 1)
1175 g_string_append_printf (lines, "/%u", conn->addr_number);
1177 g_string_append_printf (lines, "\r\n");
1181 for (i = 0; i < gst_sdp_media_bandwidths_len (media); i++) {
1182 const GstSDPBandwidth *bandwidth = gst_sdp_media_get_bandwidth (media, i);
1184 g_string_append_printf (lines, "b=%s:%u\r\n", bandwidth->bwtype,
1185 bandwidth->bandwidth);
1188 if (media->key.type) {
1189 g_string_append_printf (lines, "k=%s", media->key.type);
1190 if (media->key.data)
1191 g_string_append_printf (lines, ":%s", media->key.data);
1192 g_string_append_printf (lines, "\r\n");
1195 for (i = 0; i < gst_sdp_media_attributes_len (media); i++) {
1196 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i);
1199 g_string_append_printf (lines, "a=%s", attr->key);
1201 g_string_append_printf (lines, ":%s", attr->value);
1202 g_string_append_printf (lines, "\r\n");
1206 return g_string_free (lines, FALSE);
1210 * gst_sdp_media_get_media:
1211 * @media: a #GstSDPMedia
1213 * Get the media description of @media.
1215 * Returns: the media description.
1218 gst_sdp_media_get_media (const GstSDPMedia * media)
1220 return media->media;
1224 * gst_sdp_media_set_media:
1225 * @media: a #GstSDPMedia
1226 * @med: the media description
1228 * Set the media description of @media to @med.
1230 * Returns: #GST_SDP_OK.
1233 gst_sdp_media_set_media (GstSDPMedia * media, const gchar * med)
1235 g_free (media->media);
1236 media->media = g_strdup (med);
1242 * gst_sdp_media_get_port:
1243 * @media: a #GstSDPMedia
1245 * Get the port number for @media.
1247 * Returns: the port number of @media.
1250 gst_sdp_media_get_port (const GstSDPMedia * media)
1256 * gst_sdp_media_get_num_ports:
1257 * @media: a #GstSDPMedia
1259 * Get the number of ports for @media.
1261 * Returns: the number of ports for @media.
1264 gst_sdp_media_get_num_ports (const GstSDPMedia * media)
1266 return media->num_ports;
1270 * gst_sdp_media_set_port_info:
1271 * @media: a #GstSDPMedia
1272 * @port: the port number
1273 * @num_ports: the number of ports
1275 * Set the port information in @media.
1277 * Returns: #GST_SDP_OK.
1280 gst_sdp_media_set_port_info (GstSDPMedia * media, guint port, guint num_ports)
1283 media->num_ports = num_ports;
1289 * gst_sdp_media_get_proto:
1290 * @media: a #GstSDPMedia
1292 * Get the transport protocol of @media
1294 * Returns: the transport protocol of @media.
1297 gst_sdp_media_get_proto (const GstSDPMedia * media)
1299 return media->proto;
1303 * gst_sdp_media_set_proto:
1304 * @media: a #GstSDPMedia
1305 * @proto: the media transport protocol
1307 * Set the media transport protocol of @media to @proto.
1309 * Returns: #GST_SDP_OK.
1312 gst_sdp_media_set_proto (GstSDPMedia * media, const gchar * proto)
1314 g_free (media->proto);
1315 media->proto = g_strdup (proto);
1321 * gst_sdp_media_formats_len:
1322 * @media: a #GstSDPMedia
1324 * Get the number of formats in @media.
1326 * Returns: the number of formats in @media.
1329 gst_sdp_media_formats_len (const GstSDPMedia * media)
1331 return media->fmts->len;
1335 * gst_sdp_media_get_format:
1336 * @media: a #GstSDPMedia
1339 * Get the format information at position @idx in @media.
1341 * Returns: the format at position @idx.
1344 gst_sdp_media_get_format (const GstSDPMedia * media, guint idx)
1346 if (idx >= media->fmts->len)
1348 return g_array_index (media->fmts, gchar *, idx);
1352 * gst_sdp_media_add_format:
1353 * @media: a #GstSDPMedia
1354 * @format: the format
1356 * Add the format information to @media.
1358 * Returns: #GST_SDP_OK.
1361 gst_sdp_media_add_format (GstSDPMedia * media, const gchar * format)
1365 fmt = g_strdup (format);
1367 g_array_append_val (media->fmts, fmt);
1373 * gst_sdp_media_get_information:
1374 * @media: a #GstSDPMedia
1376 * Get the information of @media
1378 * Returns: the information of @media.
1381 gst_sdp_media_get_information (const GstSDPMedia * media)
1383 return media->information;
1387 * gst_sdp_media_set_information:
1388 * @media: a #GstSDPMedia
1389 * @information: the media information
1391 * Set the media information of @media to @information.
1393 * Returns: #GST_SDP_OK.
1396 gst_sdp_media_set_information (GstSDPMedia * media, const gchar * information)
1398 g_free (media->information);
1399 media->information = g_strdup (information);
1405 * gst_sdp_media_connections_len:
1406 * @media: a #GstSDPMedia
1408 * Get the number of connection fields in @media.
1410 * Returns: the number of connections in @media.
1413 gst_sdp_media_connections_len (const GstSDPMedia * media)
1415 return media->connections->len;
1419 * gst_sdp_media_get_connection:
1420 * @media: a #GstSDPMedia
1423 * Get the connection at position @idx in @media.
1425 * Returns: the #GstSDPConnection at position @idx.
1427 const GstSDPConnection *
1428 gst_sdp_media_get_connection (const GstSDPMedia * media, guint idx)
1430 return &g_array_index (media->connections, GstSDPConnection, idx);
1434 * gst_sdp_media_add_connection:
1435 * @media: a #GstSDPMedia
1436 * @nettype: the type of network. "IN" is defined to have the meaning
1438 * @addrtype: the type of address.
1439 * @address: the address
1440 * @ttl: the time to live of the address
1441 * @addr_number: the number of layers
1443 * Add the given connection parameters to @media.
1445 * Returns: a #GstSDPResult.
1448 gst_sdp_media_add_connection (GstSDPMedia * media, const gchar * nettype,
1449 const gchar * addrtype, const gchar * address, guint ttl, guint addr_number)
1451 GstSDPConnection conn;
1453 conn.nettype = g_strdup (nettype);
1454 conn.addrtype = g_strdup (addrtype);
1455 conn.address = g_strdup (address);
1457 conn.addr_number = addr_number;
1459 g_array_append_val (media->connections, conn);
1465 * gst_sdp_media_bandwidths_len:
1466 * @media: a #GstSDPMedia
1468 * Get the number of bandwidth fields in @media.
1470 * Returns: the number of bandwidths in @media.
1473 gst_sdp_media_bandwidths_len (const GstSDPMedia * media)
1475 return media->bandwidths->len;
1479 * gst_sdp_media_get_bandwidth:
1480 * @media: a #GstSDPMedia
1483 * Get the bandwidth at position @idx in @media.
1485 * Returns: the #GstSDPBandwidth at position @idx.
1487 const GstSDPBandwidth *
1488 gst_sdp_media_get_bandwidth (const GstSDPMedia * media, guint idx)
1490 return &g_array_index (media->bandwidths, GstSDPBandwidth, idx);
1494 * gst_sdp_media_add_bandwidth:
1495 * @media: a #GstSDPMedia
1496 * @bwtype: the bandwidth modifier type
1497 * @bandwidth: the bandwidth in kilobits per second
1499 * Add the bandwidth information with @bwtype and @bandwidth to @media.
1501 * Returns: #GST_SDP_OK.
1504 gst_sdp_media_add_bandwidth (GstSDPMedia * media, const gchar * bwtype,
1509 bw.bwtype = g_strdup (bwtype);
1510 bw.bandwidth = bandwidth;
1512 g_array_append_val (media->bandwidths, bw);
1518 * gst_sdp_media_set_key:
1519 * @media: a #GstSDPMedia
1520 * @type: the encryption type
1521 * @data: the encryption data
1523 * Adds the encryption information to @media.
1525 * Returns: a #GstSDPResult.
1528 gst_sdp_media_set_key (GstSDPMedia * media, const gchar * type,
1531 g_free (media->key.type);
1532 media->key.type = g_strdup (type);
1533 g_free (media->key.data);
1534 media->key.data = g_strdup (data);
1540 * gst_sdp_media_get_key:
1541 * @media: a #GstSDPMedia
1543 * Get the encryption information from @media.
1545 * Returns: a #GstSDPKey.
1548 gst_sdp_media_get_key (const GstSDPMedia * media)
1554 * gst_sdp_media_attributes_len:
1555 * @media: a #GstSDPMedia
1557 * Get the number of attribute fields in @media.
1559 * Returns: the number of attributes in @media.
1562 gst_sdp_media_attributes_len (const GstSDPMedia * media)
1564 return media->attributes->len;
1568 * gst_sdp_media_add_attribute:
1569 * @media: a #GstSDPMedia
1573 * Add the attribute with @key and @value to @media.
1575 * Returns: #GST_SDP_OK.
1578 gst_sdp_media_add_attribute (GstSDPMedia * media, const gchar * key,
1579 const gchar * value)
1581 GstSDPAttribute attr;
1583 attr.key = g_strdup (key);
1584 attr.value = g_strdup (value);
1586 g_array_append_val (media->attributes, attr);
1592 * gst_sdp_media_get_attribute:
1593 * @media: a #GstSDPMedia
1596 * Get the attribute at position @idx in @media.
1598 * Returns: the #GstSDPAttribute at position @idx.
1600 const GstSDPAttribute *
1601 gst_sdp_media_get_attribute (const GstSDPMedia * media, guint idx)
1603 return &g_array_index (media->attributes, GstSDPAttribute, idx);
1607 * gst_sdp_media_get_attribute_val_n:
1608 * @media: a #GstSDPMedia
1612 * Get the @nth attribute value for @key in @media.
1614 * Returns: the @nth attribute value.
1617 gst_sdp_media_get_attribute_val_n (const GstSDPMedia * media, const gchar * key,
1622 for (i = 0; i < media->attributes->len; i++) {
1623 GstSDPAttribute *attr;
1625 attr = &g_array_index (media->attributes, GstSDPAttribute, i);
1626 if (!strcmp (attr->key, key)) {
1637 * gst_sdp_media_get_attribute_val:
1638 * @media: a #GstSDPMedia
1641 * Get the first attribute value for @key in @media.
1643 * Returns: the first attribute value for @key.
1646 gst_sdp_media_get_attribute_val (const GstSDPMedia * media, const gchar * key)
1648 return gst_sdp_media_get_attribute_val_n (media, key, 0);
1652 read_string (gchar * dest, guint size, gchar ** src)
1658 while (g_ascii_isspace (**src))
1661 while (!g_ascii_isspace (**src) && **src != '\0') {
1663 dest[idx++] = **src;
1671 read_string_del (gchar * dest, guint size, gchar del, gchar ** src)
1677 while (g_ascii_isspace (**src))
1680 while (**src != del && **src != '\0') {
1682 dest[idx++] = **src;
1703 gst_sdp_parse_line (SDPContext * c, gchar type, gchar * buffer)
1708 #define READ_STRING(field) read_string (str, sizeof (str), &p); REPLACE_STRING (field, str)
1709 #define READ_UINT(field) read_string (str, sizeof (str), &p); field = strtoul (str, NULL, 10)
1713 if (buffer[0] != '0')
1714 g_warning ("wrong SDP version");
1715 gst_sdp_message_set_version (c->msg, buffer);
1718 READ_STRING (c->msg->origin.username);
1719 READ_STRING (c->msg->origin.sess_id);
1720 READ_STRING (c->msg->origin.sess_version);
1721 READ_STRING (c->msg->origin.nettype);
1722 READ_STRING (c->msg->origin.addrtype);
1723 READ_STRING (c->msg->origin.addr);
1726 REPLACE_STRING (c->msg->session_name, buffer);
1729 if (c->state == SDP_SESSION) {
1730 REPLACE_STRING (c->msg->information, buffer);
1732 REPLACE_STRING (c->media->information, buffer);
1736 REPLACE_STRING (c->msg->uri, buffer);
1739 gst_sdp_message_add_email (c->msg, buffer);
1742 gst_sdp_message_add_phone (c->msg, buffer);
1746 GstSDPConnection conn;
1749 memset (&conn, 0, sizeof (conn));
1752 while ((str2 = strchr (str2, '/')))
1754 READ_STRING (conn.nettype);
1755 READ_STRING (conn.addrtype);
1756 READ_STRING (conn.address);
1757 READ_UINT (conn.ttl);
1758 READ_UINT (conn.addr_number);
1760 if (c->state == SDP_SESSION) {
1761 gst_sdp_message_set_connection (c->msg, conn.nettype, conn.addrtype,
1762 conn.address, conn.ttl, conn.addr_number);
1764 gst_sdp_media_add_connection (c->media, conn.nettype, conn.addrtype,
1765 conn.address, conn.ttl, conn.addr_number);
1767 gst_sdp_connection_init (&conn);
1772 gchar str2[MAX_LINE_LEN];
1774 read_string_del (str, sizeof (str), ':', &p);
1777 read_string (str2, sizeof (str2), &p);
1778 if (c->state == SDP_SESSION)
1779 gst_sdp_message_add_bandwidth (c->msg, str, atoi (str2));
1781 gst_sdp_media_add_bandwidth (c->media, str, atoi (str2));
1789 read_string_del (str, sizeof (str), ':', &p);
1792 if (c->state == SDP_SESSION)
1793 gst_sdp_message_add_attribute (c->msg, str, p);
1795 gst_sdp_media_add_attribute (c->media, str, p);
1802 c->state = SDP_MEDIA;
1803 memset (&nmedia, 0, sizeof (nmedia));
1804 gst_sdp_media_init (&nmedia);
1806 /* m=<media> <port>/<number of ports> <proto> <fmt> ... */
1807 READ_STRING (nmedia.media);
1808 read_string (str, sizeof (str), &p);
1809 slash = g_strrstr (str, "/");
1812 nmedia.port = atoi (str);
1813 nmedia.num_ports = atoi (slash + 1);
1815 nmedia.port = atoi (str);
1816 nmedia.num_ports = -1;
1818 READ_STRING (nmedia.proto);
1820 read_string (str, sizeof (str), &p);
1821 gst_sdp_media_add_format (&nmedia, str);
1822 } while (*p != '\0');
1824 gst_sdp_message_add_media (c->msg, &nmedia);
1826 &g_array_index (c->msg->medias, GstSDPMedia, c->msg->medias->len - 1);
1836 * gst_sdp_message_parse_buffer:
1837 * @data: the start of the buffer
1838 * @size: the size of the buffer
1839 * @msg: the result #GstSDPMessage
1841 * Parse the contents of @size bytes pointed to by @data and store the result in
1844 * Returns: #GST_SDP_OK on success.
1847 gst_sdp_message_parse_buffer (const guint8 * data, guint size,
1848 GstSDPMessage * msg)
1853 gchar buffer[MAX_LINE_LEN];
1856 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
1857 g_return_val_if_fail (data != NULL, GST_SDP_EINVAL);
1858 g_return_val_if_fail (size != 0, GST_SDP_EINVAL);
1860 c.state = SDP_SESSION;
1866 while (g_ascii_isspace (*p))
1878 while (*p != '\n' && *p != '\r' && *p != '\0') {
1879 if (idx < sizeof (buffer) - 1)
1884 gst_sdp_parse_line (&c, type, buffer);
1887 while (*p != '\n' && *p != '\0')
1897 print_media (GstSDPMedia * media)
1899 g_print (" media: '%s'\n", GST_STR_NULL (media->media));
1900 g_print (" port: '%u'\n", media->port);
1901 g_print (" num_ports: '%u'\n", media->num_ports);
1902 g_print (" proto: '%s'\n", GST_STR_NULL (media->proto));
1903 if (media->fmts->len > 0) {
1906 g_print (" formats:\n");
1907 for (i = 0; i < media->fmts->len; i++) {
1908 g_print (" format '%s'\n", g_array_index (media->fmts, gchar *, i));
1911 g_print (" information: '%s'\n", GST_STR_NULL (media->information));
1912 if (media->connections->len > 0) {
1915 g_print (" connections:\n");
1916 for (i = 0; i < media->connections->len; i++) {
1917 GstSDPConnection *conn =
1918 &g_array_index (media->connections, GstSDPConnection, i);
1920 g_print (" nettype: '%s'\n", GST_STR_NULL (conn->nettype));
1921 g_print (" addrtype: '%s'\n", GST_STR_NULL (conn->addrtype));
1922 g_print (" address: '%s'\n", GST_STR_NULL (conn->address));
1923 g_print (" ttl: '%u'\n", conn->ttl);
1924 g_print (" addr_number: '%u'\n", conn->addr_number);
1927 if (media->bandwidths->len > 0) {
1930 g_print (" bandwidths:\n");
1931 for (i = 0; i < media->bandwidths->len; i++) {
1932 GstSDPBandwidth *bw =
1933 &g_array_index (media->bandwidths, GstSDPBandwidth, i);
1935 g_print (" type: '%s'\n", GST_STR_NULL (bw->bwtype));
1936 g_print (" bandwidth: '%u'\n", bw->bandwidth);
1939 g_print (" key:\n");
1940 g_print (" type: '%s'\n", GST_STR_NULL (media->key.type));
1941 g_print (" data: '%s'\n", GST_STR_NULL (media->key.data));
1942 if (media->attributes->len > 0) {
1945 g_print (" attributes:\n");
1946 for (i = 0; i < media->attributes->len; i++) {
1947 GstSDPAttribute *attr =
1948 &g_array_index (media->attributes, GstSDPAttribute, i);
1950 g_print (" attribute '%s' : '%s'\n", attr->key, attr->value);
1956 * gst_sdp_message_dump:
1957 * @msg: a #GstSDPMessage
1959 * Dump the parsed contents of @msg to stdout.
1961 * Returns: a #GstSDPResult.
1964 gst_sdp_message_dump (const GstSDPMessage * msg)
1966 g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
1968 g_print ("sdp packet %p:\n", msg);
1969 g_print (" version: '%s'\n", GST_STR_NULL (msg->version));
1970 g_print (" origin:\n");
1971 g_print (" username: '%s'\n", GST_STR_NULL (msg->origin.username));
1972 g_print (" sess_id: '%s'\n", GST_STR_NULL (msg->origin.sess_id));
1973 g_print (" sess_version: '%s'\n", GST_STR_NULL (msg->origin.sess_version));
1974 g_print (" nettype: '%s'\n", GST_STR_NULL (msg->origin.nettype));
1975 g_print (" addrtype: '%s'\n", GST_STR_NULL (msg->origin.addrtype));
1976 g_print (" addr: '%s'\n", GST_STR_NULL (msg->origin.addr));
1977 g_print (" session_name: '%s'\n", GST_STR_NULL (msg->session_name));
1978 g_print (" information: '%s'\n", GST_STR_NULL (msg->information));
1979 g_print (" uri: '%s'\n", GST_STR_NULL (msg->uri));
1981 if (msg->emails->len > 0) {
1984 g_print (" emails:\n");
1985 for (i = 0; i < msg->emails->len; i++) {
1986 g_print (" email '%s'\n", g_array_index (msg->emails, gchar *, i));
1989 if (msg->phones->len > 0) {
1992 g_print (" phones:\n");
1993 for (i = 0; i < msg->phones->len; i++) {
1994 g_print (" phone '%s'\n", g_array_index (msg->phones, gchar *, i));
1997 g_print (" connection:\n");
1998 g_print (" nettype: '%s'\n", GST_STR_NULL (msg->connection.nettype));
1999 g_print (" addrtype: '%s'\n", GST_STR_NULL (msg->connection.addrtype));
2000 g_print (" address: '%s'\n", GST_STR_NULL (msg->connection.address));
2001 g_print (" ttl: '%u'\n", msg->connection.ttl);
2002 g_print (" addr_number: '%u'\n", msg->connection.addr_number);
2003 if (msg->bandwidths->len > 0) {
2006 g_print (" bandwidths:\n");
2007 for (i = 0; i < msg->bandwidths->len; i++) {
2008 GstSDPBandwidth *bw =
2009 &g_array_index (msg->bandwidths, GstSDPBandwidth, i);
2011 g_print (" type: '%s'\n", GST_STR_NULL (bw->bwtype));
2012 g_print (" bandwidth: '%u'\n", bw->bandwidth);
2015 g_print (" key:\n");
2016 g_print (" type: '%s'\n", GST_STR_NULL (msg->key.type));
2017 g_print (" data: '%s'\n", GST_STR_NULL (msg->key.data));
2018 if (msg->attributes->len > 0) {
2021 g_print (" attributes:\n");
2022 for (i = 0; i < msg->attributes->len; i++) {
2023 GstSDPAttribute *attr =
2024 &g_array_index (msg->attributes, GstSDPAttribute, i);
2026 g_print (" attribute '%s' : '%s'\n", attr->key, attr->value);
2029 if (msg->medias->len > 0) {
2032 g_print (" medias:\n");
2033 for (i = 0; i < msg->medias->len; i++) {
2034 g_print (" media %u:\n", i);
2035 print_media (&g_array_index (msg->medias, GstSDPMedia, i));