2 * (c) 2010, 2012 Alexander Saprykin <xelfium@gmail.com>
4 * gsttoc.c: GstToc initialization and parsing/creation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 * @short_description: Generic table of contents support
25 * @see_also: #GstStructure, #GstEvent, #GstMessage, #GstQuery, #GstPad
27 * #GstToc functions are used to create/free #GstToc and #GstTocEntry structures.
28 * Also they are used to convert #GstToc into #GstStructure and vice versa.
30 * #GstToc lets you to inform other elements in pipeline or application that playing
31 * source has some kind of table of contents (TOC). These may be chapters, editions,
32 * angles or other types. For example: DVD chapters, Matroska chapters or cue sheet
33 * TOC. Such TOC will be useful for applications to display instead of just a
36 * Using TOC is very easy. Firstly, create #GstToc structure which represents root
37 * contents of the source. You can also attach TOC-specific tags to it. Then fill
38 * it with #GstTocEntry entries by appending them to #GstToc.entries #GstTocEntry.subentries
39 * lists. You should use GST_TOC_ENTRY_TYPE_CHAPTER for generic TOC entry and
40 * GST_TOC_ENTRY_TYPE_EDITION for the entries which are considered to be alternatives
41 * (like DVD angles, Matroska editions and so on).
43 * Note that root level of the TOC can contain only either editions or chapters. You
44 * should not mix them together at the same level. Otherwise you will get serialization
45 * /deserialization errors. Make sure that no one of the entries has negative start and
48 * Please, use #GstToc.info and #GstTocEntry.info fields in that way: create a #GstStructure,
49 * put all info related to your element there and put this structure into the info field under
50 * the name of your element. Some fields in the info structure can be used for internal purposes,
51 * so you should use it in the way described above to not to overwrite already existent fields.
53 * Use gst_event_new_toc() to create a new TOC #GstEvent, and gst_event_parse_toc() to
54 * parse received TOC event. Use gst_event_new_toc_select() to create a new TOC select #GstEvent,
55 * and gst_event_parse_toc_select() to parse received TOC select event. The same rule for
56 * the #GstMessage: gst_message_new_toc() to create new TOC #GstMessage, and
57 * gst_message_parse_toc() to parse received TOC message. Also you can create a new TOC query
58 * with gst_query_new_toc(), set it with gst_query_set_toc() and parse it with
59 * gst_query_parse_toc().
66 #include "gst_private.h"
67 #include "gstenumtypes.h"
68 #include "gsttaglist.h"
69 #include "gststructure.h"
78 * Create new #GstToc structure.
80 * Returns: newly allocated #GstToc structure, free it with gst_toc_free().
89 toc = g_slice_new0 (GstToc);
90 toc->tags = gst_tag_list_new_empty ();
91 toc->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE));
99 * @uid: unique ID (UID) in the whole TOC.
101 * Create new #GstTocEntry structure.
103 * Returns: newly allocated #GstTocEntry structure, free it with gst_toc_entry_free().
108 gst_toc_entry_new (GstTocEntryType type, const gchar * uid)
112 g_return_val_if_fail (uid != NULL, NULL);
114 entry = g_slice_new0 (GstTocEntry);
115 entry->uid = g_strdup (uid);
117 entry->tags = gst_tag_list_new_empty ();
118 entry->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE));
124 * gst_toc_entry_new_with_pad:
126 * @uid: unique ID (UID) in the whole TOC.
127 * @pad: #GstPad related to this entry.
129 * Create new #GstTocEntry structure with #GstPad related.
131 * Returns: newly allocated #GstTocEntry structure, free it with gst_toc_entry_free()
137 gst_toc_entry_new_with_pad (GstTocEntryType type, const gchar * uid,
142 g_return_val_if_fail (uid != NULL, NULL);
144 entry = g_slice_new0 (GstTocEntry);
145 entry->uid = g_strdup (uid);
147 entry->tags = gst_tag_list_new_empty ();
148 entry->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE));
150 if (pad != NULL && GST_IS_PAD (pad))
151 entry->pads = g_list_append (entry->pads, gst_object_ref (pad));
158 * @toc: #GstToc structure to free.
160 * Free unused #GstToc structure.
165 gst_toc_free (GstToc * toc)
167 g_return_if_fail (toc != NULL);
169 g_list_foreach (toc->entries, (GFunc) gst_toc_entry_free, NULL);
170 g_list_free (toc->entries);
172 if (toc->tags != NULL)
173 gst_tag_list_free (toc->tags);
175 if (toc->info != NULL)
176 gst_structure_free (toc->info);
178 g_slice_free (GstToc, toc);
182 * gst_toc_entry_free:
183 * @entry: #GstTocEntry structure to free.
185 * Free unused #GstTocEntry structure. Note that #GstTocEntry.uid will
186 * be freed with g_free() and all #GstPad objects in the #GstTocEntry.pads
187 * list will be unrefed with gst_object_unref().
192 gst_toc_entry_free (GstTocEntry * entry)
196 g_return_if_fail (entry != NULL);
198 g_list_foreach (entry->subentries, (GFunc) gst_toc_entry_free, NULL);
199 g_list_free (entry->subentries);
203 if (entry->tags != NULL)
204 gst_tag_list_free (entry->tags);
206 if (entry->info != NULL)
207 gst_structure_free (entry->info);
210 while (cur != NULL) {
211 if (GST_IS_PAD (cur->data))
212 gst_object_unref (cur->data);
216 g_list_free (entry->pads);
218 g_slice_free (GstTocEntry, entry);
221 static GstStructure *
222 gst_toc_structure_new (GstTagList * tags, GstStructure * info)
226 ret = gst_structure_new_id_empty (GST_QUARK (TOC));
229 // FIXME: don't use GST_TYPE_STRUCTURE for taglist
230 gst_structure_id_set (ret, GST_QUARK (TAGS), GST_TYPE_STRUCTURE, tags,
235 gst_structure_id_set (ret, GST_QUARK (INFO), GST_TYPE_STRUCTURE, info,
242 static GstStructure *
243 gst_toc_entry_structure_new (GstTocEntryType type, const gchar * uid,
244 GstTagList * tags, GstStructure * info)
248 ret = gst_structure_new_id_empty (GST_QUARK (TOC_ENTRY));
250 gst_structure_id_set (ret, GST_QUARK (TYPE), GST_TYPE_TOC_ENTRY_TYPE, type,
252 gst_structure_id_set (ret, GST_QUARK (UID), G_TYPE_STRING, uid, NULL);
255 // FIXME: taglist type
256 gst_structure_id_set (ret, GST_QUARK (TAGS), GST_TYPE_STRUCTURE, tags,
261 gst_structure_id_set (ret, GST_QUARK (INFO), GST_TYPE_STRUCTURE, info,
269 gst_toc_entry_structure_n_subentries (const GstStructure * entry)
271 if (G_UNLIKELY (!gst_structure_id_has_field_typed (entry,
272 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)))
275 return gst_value_array_get_size ((gst_structure_id_get_value (entry,
276 GST_QUARK (SUB_ENTRIES))));
279 static const GstStructure *
280 gst_toc_entry_structure_nth_subentry (const GstStructure * entry, guint nth)
285 count = gst_toc_entry_structure_n_subentries (entry);
290 if (G_UNLIKELY (!gst_structure_id_has_field_typed (entry,
291 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)))
295 gst_value_array_get_value (gst_structure_id_get_value (entry,
296 GST_QUARK (SUB_ENTRIES)), nth);
297 return gst_value_get_structure (array);
302 gst_toc_entry_from_structure (const GstStructure * entry, guint level)
304 GstTocEntry *ret, *subentry;
306 const GstStructure *subentry_struct;
311 guint chapters_count = 0, editions_count = 0;
313 g_return_val_if_fail (entry != NULL, NULL);
314 g_return_val_if_fail (gst_structure_id_has_field_typed (entry,
315 GST_QUARK (UID), G_TYPE_STRING), NULL);
316 g_return_val_if_fail (gst_structure_id_has_field_typed (entry,
317 GST_QUARK (TYPE), GST_TYPE_TOC_ENTRY_TYPE), NULL);
319 val = gst_structure_id_get_value (entry, GST_QUARK (UID));
320 uid = g_value_get_string (val);
322 ret = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid);
324 gst_structure_get_enum (entry, g_quark_to_string (GST_QUARK (TYPE)),
325 GST_TYPE_TOC_ENTRY_TYPE, (gint *) & (ret->type));
327 if (gst_structure_id_has_field_typed (entry,
328 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)) {
329 count = gst_toc_entry_structure_n_subentries (entry);
331 for (i = 0; i < count; ++i) {
332 subentry_struct = gst_toc_entry_structure_nth_subentry (entry, i);
333 subentry = gst_toc_entry_from_structure (subentry_struct, level + 1);
335 /* skip empty editions */
336 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
337 && subentry->subentries == NULL)) {
339 ("Empty edition found while deserializing TOC from GstStructure, skipping");
343 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
348 /* check for mixed content */
349 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
351 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
352 gst_toc_entry_free (subentry);
353 gst_toc_entry_free (ret);
357 if (G_UNLIKELY (subentry == NULL)) {
358 gst_toc_entry_free (ret);
362 ret->subentries = g_list_prepend (ret->subentries, subentry);
365 ret->subentries = g_list_reverse (ret->subentries);
368 if (gst_structure_id_has_field_typed (entry,
369 GST_QUARK (TAGS), GST_TYPE_STRUCTURE)) {
370 val = gst_structure_id_get_value (entry, GST_QUARK (TAGS));
372 if (G_LIKELY (GST_IS_TAG_LIST (gst_value_get_structure (val)))) {
373 list = gst_tag_list_copy (GST_TAG_LIST (gst_value_get_structure (val)));
374 gst_tag_list_free (ret->tags);
379 if (gst_structure_id_has_field_typed (entry,
380 GST_QUARK (INFO), GST_TYPE_STRUCTURE)) {
381 val = gst_structure_id_get_value (entry, GST_QUARK (INFO));
383 if (G_LIKELY (GST_IS_STRUCTURE (gst_value_get_structure (val)))) {
384 st = gst_structure_copy (gst_value_get_structure (val));
385 gst_structure_free (ret->info);
394 __gst_toc_from_structure (const GstStructure * toc)
397 GstTocEntry *subentry;
398 const GstStructure *subentry_struct;
403 guint editions_count = 0, chapters_count = 0;
405 g_return_val_if_fail (toc != NULL, NULL);
407 ret = gst_toc_new ();
409 if (gst_structure_id_has_field_typed (toc,
410 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)) {
411 count = gst_toc_entry_structure_n_subentries (toc);
413 for (i = 0; i < count; ++i) {
414 subentry_struct = gst_toc_entry_structure_nth_subentry (toc, i);
415 subentry = gst_toc_entry_from_structure (subentry_struct, 0);
417 /* skip empty editions */
418 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
419 && subentry->subentries == NULL)) {
421 ("Empty edition found while deserializing TOC from GstStructure, skipping");
425 /* check for success */
426 if (G_UNLIKELY (subentry == NULL)) {
427 g_critical ("Couldn't serialize deserializing TOC from GstStructure");
432 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
437 /* check for mixed content */
438 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
440 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
441 gst_toc_entry_free (subentry);
446 ret->entries = g_list_prepend (ret->entries, subentry);
449 ret->entries = g_list_reverse (ret->entries);
452 if (gst_structure_id_has_field_typed (toc,
453 GST_QUARK (TAGS), GST_TYPE_STRUCTURE)) {
454 val = gst_structure_id_get_value (toc, GST_QUARK (TAGS));
456 if (G_LIKELY (GST_IS_TAG_LIST (gst_value_get_structure (val)))) {
457 list = gst_tag_list_copy (GST_TAG_LIST (gst_value_get_structure (val)));
458 gst_tag_list_free (ret->tags);
463 if (gst_structure_id_has_field_typed (toc,
464 GST_QUARK (INFO), GST_TYPE_STRUCTURE)) {
465 val = gst_structure_id_get_value (toc, GST_QUARK (INFO));
467 if (G_LIKELY (GST_IS_STRUCTURE (gst_value_get_structure (val)))) {
468 st = gst_structure_copy (gst_value_get_structure (val));
469 gst_structure_free (ret->info);
474 if (G_UNLIKELY (ret->entries == NULL)) {
482 static GstStructure *
483 gst_toc_entry_to_structure (const GstTocEntry * entry, guint level)
485 GstStructure *ret, *subentry_struct;
486 GstTocEntry *subentry;
488 GValue subentries_val = { 0 };
489 GValue entry_val = { 0 };
490 guint chapters_count = 0, editions_count = 0;
492 g_return_val_if_fail (entry != NULL, NULL);
495 gst_toc_entry_structure_new (entry->type, entry->uid, entry->tags,
498 g_value_init (&subentries_val, GST_TYPE_ARRAY);
499 g_value_init (&entry_val, GST_TYPE_STRUCTURE);
501 cur = entry->subentries;
502 while (cur != NULL) {
503 subentry = cur->data;
505 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
510 /* check for mixed content */
511 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
513 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
514 gst_structure_free (ret);
515 g_value_unset (&entry_val);
516 g_value_unset (&subentries_val);
520 /* skip empty editions */
521 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
522 && subentry->subentries == NULL)) {
524 ("Empty edition found while serializing TOC to GstStructure, skipping");
529 subentry_struct = gst_toc_entry_to_structure (subentry, level + 1);
531 /* check for success */
532 if (G_UNLIKELY (subentry_struct == NULL)) {
533 gst_structure_free (ret);
534 g_value_unset (&subentries_val);
535 g_value_unset (&entry_val);
539 /* skip empty editions */
540 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
541 && subentry->subentries == NULL)) {
543 ("Empty edition found while serializing TOC to GstStructure, skipping");
548 gst_value_set_structure (&entry_val, subentry_struct);
549 gst_value_array_append_value (&subentries_val, &entry_val);
550 gst_structure_free (subentry_struct);
555 gst_structure_id_set_value (ret, GST_QUARK (SUB_ENTRIES), &subentries_val);
557 g_value_unset (&subentries_val);
558 g_value_unset (&entry_val);
563 __gst_toc_to_structure (const GstToc * toc)
566 GValue subentries_val = { 0 };
567 GstStructure *ret, *subentry_struct;
568 GstTocEntry *subentry;
570 guint editions_count = 0, chapters_count = 0;
572 g_return_val_if_fail (toc != NULL, NULL);
573 g_return_val_if_fail (toc->entries != NULL, NULL);
575 ret = gst_toc_structure_new (toc->tags, toc->info);
577 g_value_init (&val, GST_TYPE_STRUCTURE);
578 g_value_init (&subentries_val, GST_TYPE_ARRAY);
581 while (cur != NULL) {
582 subentry = cur->data;
584 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
589 /* check for mixed content */
590 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
592 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
593 gst_structure_free (ret);
594 g_value_unset (&val);
595 g_value_unset (&subentries_val);
599 /* skip empty editions */
600 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
601 && subentry->subentries == NULL)) {
603 ("Empty edition found while serializing TOC to GstStructure, skipping");
608 subentry_struct = gst_toc_entry_to_structure (subentry, 0);
610 /* check for success */
611 if (G_UNLIKELY (subentry_struct == NULL)) {
612 g_critical ("Couldn't serialize TOC to GstStructure");
613 gst_structure_free (ret);
614 g_value_unset (&val);
615 g_value_unset (&subentries_val);
619 gst_value_set_structure (&val, subentry_struct);
620 gst_value_array_append_value (&subentries_val, &val);
621 gst_structure_free (subentry_struct);
626 gst_structure_id_set_value (ret, GST_QUARK (SUB_ENTRIES), &subentries_val);
628 g_value_unset (&val);
629 g_value_unset (&subentries_val);
634 gst_toc_check_entry_for_uid (const GstTocEntry * entry, const gchar * uid)
638 g_return_val_if_fail (entry != NULL, FALSE);
639 g_return_val_if_fail (uid != NULL, FALSE);
641 if (g_strcmp0 (entry->uid, uid) == 0)
644 cur = entry->subentries;
645 while (cur != NULL) {
646 if (gst_toc_check_entry_for_uid (cur->data, uid))
655 * gst_toc_find_entry:
656 * @toc: #GstToc to search in.
657 * @uid: UID to find #GstTocEntry with.
659 * Find #GstTocEntry with given @uid in the @toc.
661 * Returns: #GstTocEntry with specified @uid from the @toc, or NULL if not found.
666 gst_toc_find_entry (const GstToc * toc, const gchar * uid)
670 g_return_val_if_fail (toc != NULL, NULL);
671 g_return_val_if_fail (uid != NULL, NULL);
674 while (cur != NULL) {
675 if (gst_toc_check_entry_for_uid (cur->data, uid))
684 * gst_toc_entry_copy:
685 * @entry: #GstTocEntry to copy.
687 * Copy #GstTocEntry with all subentries (deep copy).
689 * Returns: newly allocated #GstTocEntry in case of success, NULL otherwise;
690 * free it when done with gst_toc_entry_free().
695 gst_toc_entry_copy (const GstTocEntry * entry)
697 GstTocEntry *ret, *sub;
702 g_return_val_if_fail (entry != NULL, NULL);
704 ret = gst_toc_entry_new (entry->type, entry->uid);
706 if (GST_IS_STRUCTURE (entry->info)) {
707 st = gst_structure_copy (entry->info);
708 gst_structure_free (ret->info);
712 if (GST_IS_TAG_LIST (entry->tags)) {
713 list = gst_tag_list_copy (entry->tags);
714 gst_tag_list_free (ret->tags);
719 while (cur != NULL) {
720 if (GST_IS_PAD (cur->data))
721 ret->pads = g_list_prepend (ret->pads, gst_object_ref (cur->data));
724 ret->pads = g_list_reverse (ret->pads);
726 cur = entry->subentries;
727 while (cur != NULL) {
728 sub = gst_toc_entry_copy (cur->data);
731 ret->subentries = g_list_prepend (ret->subentries, sub);
735 ret->subentries = g_list_reverse (ret->subentries);
742 * @toc: #GstToc to copy.
744 * Copy #GstToc with all subentries (deep copy).
746 * Returns: newly allocated #GstToc in case of success, NULL otherwise;
747 * free it when done with gst_toc_free().
752 gst_toc_copy (const GstToc * toc)
760 g_return_val_if_fail (toc != NULL, NULL);
762 ret = gst_toc_new ();
764 if (GST_IS_STRUCTURE (toc->info)) {
765 st = gst_structure_copy (toc->info);
766 gst_structure_free (ret->info);
770 if (GST_IS_TAG_LIST (toc->tags)) {
771 list = gst_tag_list_copy (toc->tags);
772 gst_tag_list_free (ret->tags);
777 while (cur != NULL) {
778 entry = gst_toc_entry_copy (cur->data);
781 ret->entries = g_list_prepend (ret->entries, entry);
785 ret->entries = g_list_reverse (ret->entries);
791 * gst_toc_entry_set_start_stop:
792 * @entry: #GstTocEntry to set values.
793 * @start: start value to set.
794 * @stop: stop value to set.
796 * Set @start and @stop values for the @entry.
801 gst_toc_entry_set_start_stop (GstTocEntry * entry, gint64 start, gint64 stop)
804 GstStructure *structure = NULL;
806 g_return_if_fail (entry != NULL);
807 g_return_if_fail (GST_IS_STRUCTURE (entry->info));
809 if (gst_structure_id_has_field_typed (entry->info, GST_QUARK (TIME),
810 GST_TYPE_STRUCTURE)) {
811 val = gst_structure_id_get_value (entry->info, GST_QUARK (TIME));
812 structure = gst_structure_copy (gst_value_get_structure (val));
815 if (structure == NULL)
816 structure = gst_structure_new_id_empty (GST_QUARK (TIME_STRUCTURE));
818 gst_structure_id_set (structure, GST_QUARK (START),
819 G_TYPE_INT64, start, GST_QUARK (STOP), G_TYPE_INT64, stop, NULL);
821 gst_structure_id_set (entry->info, GST_QUARK (TIME),
822 GST_TYPE_STRUCTURE, structure, NULL);
824 gst_structure_free (structure);
828 * gst_toc_entry_get_start_stop:
829 * @entry: #GstTocEntry to get values from.
830 * @start: (out): the storage for the start value, leave #NULL if not need.
831 * @stop: (out): the storage for the stop value, leave #NULL if not need.
833 * Get start and stop values from the @entry and write them into appropriate storages.
835 * Returns: TRUE if all non-NULL storage pointers were filled with appropriate values,
841 gst_toc_entry_get_start_stop (const GstTocEntry * entry, gint64 * start,
846 const GstStructure *structure;
848 g_return_val_if_fail (entry != NULL, FALSE);
849 g_return_val_if_fail (GST_IS_STRUCTURE (entry->info), FALSE);
851 if (!gst_structure_id_has_field_typed (entry->info,
852 GST_QUARK (TIME), GST_TYPE_STRUCTURE))
855 val = gst_structure_id_get_value (entry->info, GST_QUARK (TIME));
856 structure = gst_value_get_structure (val);
859 if (gst_structure_id_has_field_typed (structure,
860 GST_QUARK (START), G_TYPE_INT64))
862 g_value_get_int64 (gst_structure_id_get_value (structure,
869 if (gst_structure_id_has_field_typed (structure,
870 GST_QUARK (STOP), G_TYPE_INT64))
872 g_value_get_int64 (gst_structure_id_get_value (structure,
882 * gst_toc_entry_type_get_nick:
883 * @type: a #GstTocEntryType.
885 * Converts @type to a string representation.
887 * Returns: Returns the human-readable @type. Can be NULL if an error occurred.
891 gst_toc_entry_type_get_nick (GstTocEntryType type)
893 const gchar *entry_types[] = { "chapter", "edition" };
895 g_return_val_if_fail ((gint) type >= 0
896 && (gint) type < G_N_ELEMENTS (entry_types), NULL);
897 return entry_types[type];
901 __gst_toc_structure_get_updated (const GstStructure * toc)
905 g_return_val_if_fail (GST_IS_STRUCTURE (toc), FALSE);
907 if (G_LIKELY (gst_structure_id_has_field_typed (toc,
908 GST_QUARK (UPDATED), G_TYPE_BOOLEAN))) {
909 val = gst_structure_id_get_value (toc, GST_QUARK (UPDATED));
910 return g_value_get_boolean (val);
917 __gst_toc_structure_set_updated (GstStructure * toc, gboolean updated)
919 g_return_if_fail (toc != NULL);
921 gst_structure_id_set (toc, GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated,
926 __gst_toc_structure_get_extend_uid (const GstStructure * toc)
930 g_return_val_if_fail (GST_IS_STRUCTURE (toc), NULL);
932 if (G_LIKELY (gst_structure_id_has_field_typed (toc,
933 GST_QUARK (EXTEND_UID), G_TYPE_STRING))) {
934 val = gst_structure_id_get_value (toc, GST_QUARK (EXTEND_UID));
935 return g_strdup (g_value_get_string (val));
942 __gst_toc_structure_set_extend_uid (GstStructure * toc,
943 const gchar * extend_uid)
945 g_return_if_fail (toc != NULL);
946 g_return_if_fail (extend_uid != NULL);
948 gst_structure_id_set (toc, GST_QUARK (EXTEND_UID), G_TYPE_STRING, extend_uid,