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"
76 static GstToc *gst_toc_copy (const GstToc * toc);
77 static void gst_toc_free (GstToc * toc);
78 #undef gst_toc_entry_copy
79 static GstTocEntry *gst_toc_entry_copy (const GstTocEntry * toc);
80 static void gst_toc_entry_free (GstTocEntry * toc);
82 GST_DEFINE_MINI_OBJECT_TYPE (GstToc, gst_toc);
83 GST_DEFINE_MINI_OBJECT_TYPE (GstTocEntry, gst_toc_entry);
88 * Create a new #GstToc structure.
90 * Returns: (transfer full): newly allocated #GstToc structure, free it
91 * with gst_toc_unref().
100 toc = g_slice_new0 (GstToc);
102 gst_mini_object_init (GST_MINI_OBJECT_CAST (toc), GST_TYPE_TOC,
103 (GstMiniObjectCopyFunction) gst_toc_copy, NULL,
104 (GstMiniObjectFreeFunction) gst_toc_free);
106 toc->tags = gst_tag_list_new_empty ();
107 toc->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE));
113 gst_toc_entry_new_internal (GstTocEntryType type, const gchar * uid,
118 entry = g_slice_new0 (GstTocEntry);
120 gst_mini_object_init (GST_MINI_OBJECT_CAST (entry), GST_TYPE_TOC_ENTRY,
121 (GstMiniObjectCopyFunction) gst_toc_entry_copy, NULL,
122 (GstMiniObjectFreeFunction) gst_toc_entry_free);
124 entry->uid = g_strdup (uid);
126 entry->tags = gst_tag_list_new_empty ();
127 entry->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE));
129 if (pad != NULL && GST_IS_PAD (pad))
130 entry->pads = g_list_append (entry->pads, gst_object_ref (pad));
138 * @uid: unique ID (UID) in the whole TOC.
140 * Create new #GstTocEntry structure.
142 * Returns: newly allocated #GstTocEntry structure, free it with gst_toc_entry_unref().
147 gst_toc_entry_new (GstTocEntryType type, const gchar * uid)
149 g_return_val_if_fail (uid != NULL, NULL);
151 return gst_toc_entry_new_internal (type, uid, NULL);
155 * gst_toc_entry_new_with_pad:
157 * @uid: unique ID (UID) in the whole TOC.
158 * @pad: #GstPad related to this entry.
160 * Create new #GstTocEntry structure with #GstPad related.
162 * Returns: newly allocated #GstTocEntry structure, free it with gst_toc_entry_unref()
168 gst_toc_entry_new_with_pad (GstTocEntryType type, const gchar * uid,
171 g_return_val_if_fail (uid != NULL, NULL);
173 return gst_toc_entry_new_internal (type, uid, pad);
177 gst_toc_free (GstToc * toc)
179 g_list_foreach (toc->entries, (GFunc) gst_mini_object_unref, NULL);
180 g_list_free (toc->entries);
182 if (toc->tags != NULL)
183 gst_tag_list_unref (toc->tags);
185 if (toc->info != NULL)
186 gst_structure_free (toc->info);
188 g_slice_free (GstToc, toc);
192 gst_toc_entry_free (GstTocEntry * entry)
196 g_return_if_fail (entry != NULL);
198 g_list_foreach (entry->subentries, (GFunc) gst_mini_object_unref, NULL);
199 g_list_free (entry->subentries);
203 if (entry->tags != NULL)
204 gst_tag_list_unref (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 gst_structure_id_set (ret, GST_QUARK (TAGS), GST_TYPE_TAG_LIST, tags, NULL);
233 gst_structure_id_set (ret, GST_QUARK (INFO), GST_TYPE_STRUCTURE, info,
240 static GstStructure *
241 gst_toc_entry_structure_new (GstTocEntryType type, const gchar * uid,
242 GstTagList * tags, GstStructure * info)
246 ret = gst_structure_new_id_empty (GST_QUARK (TOC_ENTRY));
248 gst_structure_id_set (ret, GST_QUARK (TYPE), GST_TYPE_TOC_ENTRY_TYPE, type,
250 gst_structure_id_set (ret, GST_QUARK (UID), G_TYPE_STRING, uid, NULL);
253 gst_structure_id_set (ret, GST_QUARK (TAGS), GST_TYPE_TAG_LIST, tags, NULL);
257 gst_structure_id_set (ret, GST_QUARK (INFO), GST_TYPE_STRUCTURE, info,
265 gst_toc_entry_structure_n_subentries (const GstStructure * entry)
267 if (G_UNLIKELY (!gst_structure_id_has_field_typed (entry,
268 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)))
271 return gst_value_array_get_size ((gst_structure_id_get_value (entry,
272 GST_QUARK (SUB_ENTRIES))));
275 static const GstStructure *
276 gst_toc_entry_structure_nth_subentry (const GstStructure * entry, guint nth)
281 count = gst_toc_entry_structure_n_subentries (entry);
286 if (G_UNLIKELY (!gst_structure_id_has_field_typed (entry,
287 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)))
291 gst_value_array_get_value (gst_structure_id_get_value (entry,
292 GST_QUARK (SUB_ENTRIES)), nth);
293 return gst_value_get_structure (array);
298 gst_toc_entry_from_structure (const GstStructure * entry, guint level)
300 GstTocEntry *ret, *subentry;
302 const GstStructure *subentry_struct;
307 guint chapters_count = 0, editions_count = 0;
309 g_return_val_if_fail (entry != NULL, NULL);
310 g_return_val_if_fail (gst_structure_id_has_field_typed (entry,
311 GST_QUARK (UID), G_TYPE_STRING), NULL);
312 g_return_val_if_fail (gst_structure_id_has_field_typed (entry,
313 GST_QUARK (TYPE), GST_TYPE_TOC_ENTRY_TYPE), NULL);
315 val = gst_structure_id_get_value (entry, GST_QUARK (UID));
316 uid = g_value_get_string (val);
318 ret = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid);
320 gst_structure_get_enum (entry, g_quark_to_string (GST_QUARK (TYPE)),
321 GST_TYPE_TOC_ENTRY_TYPE, (gint *) & (ret->type));
323 if (gst_structure_id_has_field_typed (entry,
324 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)) {
325 count = gst_toc_entry_structure_n_subentries (entry);
327 for (i = 0; i < count; ++i) {
328 subentry_struct = gst_toc_entry_structure_nth_subentry (entry, i);
329 subentry = gst_toc_entry_from_structure (subentry_struct, level + 1);
331 /* skip empty editions */
332 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
333 && subentry->subentries == NULL)) {
335 ("Empty edition found while deserializing TOC from GstStructure, skipping");
339 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
344 /* check for mixed content */
345 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
347 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
348 gst_toc_entry_unref (subentry);
349 gst_toc_entry_unref (ret);
353 if (G_UNLIKELY (subentry == NULL)) {
354 gst_toc_entry_unref (ret);
358 ret->subentries = g_list_prepend (ret->subentries, subentry);
361 ret->subentries = g_list_reverse (ret->subentries);
364 if (gst_structure_id_has_field_typed (entry, GST_QUARK (TAGS),
365 GST_TYPE_TAG_LIST)) {
366 val = gst_structure_id_get_value (entry, GST_QUARK (TAGS));
368 if (G_LIKELY (GST_IS_TAG_LIST (g_value_get_boxed (val)))) {
369 list = gst_tag_list_copy (GST_TAG_LIST (g_value_get_boxed (val)));
370 gst_tag_list_unref (ret->tags);
375 if (gst_structure_id_has_field_typed (entry,
376 GST_QUARK (INFO), GST_TYPE_STRUCTURE)) {
377 val = gst_structure_id_get_value (entry, GST_QUARK (INFO));
379 if (G_LIKELY (GST_IS_STRUCTURE (gst_value_get_structure (val)))) {
380 st = gst_structure_copy (gst_value_get_structure (val));
381 gst_structure_free (ret->info);
390 __gst_toc_from_structure (const GstStructure * toc)
393 GstTocEntry *subentry;
394 const GstStructure *subentry_struct;
399 guint editions_count = 0, chapters_count = 0;
401 g_return_val_if_fail (toc != NULL, NULL);
403 ret = gst_toc_new ();
405 if (gst_structure_id_has_field_typed (toc,
406 GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)) {
407 count = gst_toc_entry_structure_n_subentries (toc);
409 for (i = 0; i < count; ++i) {
410 subentry_struct = gst_toc_entry_structure_nth_subentry (toc, i);
411 subentry = gst_toc_entry_from_structure (subentry_struct, 0);
413 /* skip empty editions */
414 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
415 && subentry->subentries == NULL)) {
417 ("Empty edition found while deserializing TOC from GstStructure, skipping");
421 /* check for success */
422 if (G_UNLIKELY (subentry == NULL)) {
423 g_critical ("Couldn't serialize deserializing TOC from GstStructure");
428 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
433 /* check for mixed content */
434 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
436 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
437 gst_toc_entry_unref (subentry);
442 ret->entries = g_list_prepend (ret->entries, subentry);
445 ret->entries = g_list_reverse (ret->entries);
448 if (gst_structure_id_has_field_typed (toc, GST_QUARK (TAGS),
449 GST_TYPE_TAG_LIST)) {
450 val = gst_structure_id_get_value (toc, GST_QUARK (TAGS));
452 if (G_LIKELY (GST_IS_TAG_LIST (g_value_get_boxed (val)))) {
453 list = gst_tag_list_copy (GST_TAG_LIST (g_value_get_boxed (val)));
454 gst_tag_list_unref (ret->tags);
459 if (gst_structure_id_has_field_typed (toc,
460 GST_QUARK (INFO), GST_TYPE_STRUCTURE)) {
461 val = gst_structure_id_get_value (toc, GST_QUARK (INFO));
463 if (G_LIKELY (GST_IS_STRUCTURE (gst_value_get_structure (val)))) {
464 st = gst_structure_copy (gst_value_get_structure (val));
465 gst_structure_free (ret->info);
470 if (G_UNLIKELY (ret->entries == NULL)) {
478 static GstStructure *
479 gst_toc_entry_to_structure (const GstTocEntry * entry, guint level)
481 GstStructure *ret, *subentry_struct;
482 GstTocEntry *subentry;
484 GValue subentries_val = { 0 };
485 GValue entry_val = { 0 };
486 guint chapters_count = 0, editions_count = 0;
488 g_return_val_if_fail (entry != NULL, NULL);
491 gst_toc_entry_structure_new (entry->type, entry->uid, entry->tags,
494 g_value_init (&subentries_val, GST_TYPE_ARRAY);
495 g_value_init (&entry_val, GST_TYPE_STRUCTURE);
497 cur = entry->subentries;
498 while (cur != NULL) {
499 subentry = cur->data;
501 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
506 /* check for mixed content */
507 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
509 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
510 gst_structure_free (ret);
511 g_value_unset (&entry_val);
512 g_value_unset (&subentries_val);
516 /* skip empty editions */
517 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
518 && subentry->subentries == NULL)) {
520 ("Empty edition found while serializing TOC to GstStructure, skipping");
525 subentry_struct = gst_toc_entry_to_structure (subentry, level + 1);
527 /* check for success */
528 if (G_UNLIKELY (subentry_struct == NULL)) {
529 gst_structure_free (ret);
530 g_value_unset (&subentries_val);
531 g_value_unset (&entry_val);
535 /* skip empty editions */
536 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
537 && subentry->subentries == NULL)) {
539 ("Empty edition found while serializing TOC to GstStructure, skipping");
544 gst_value_set_structure (&entry_val, subentry_struct);
545 gst_value_array_append_value (&subentries_val, &entry_val);
546 gst_structure_free (subentry_struct);
551 gst_structure_id_set_value (ret, GST_QUARK (SUB_ENTRIES), &subentries_val);
553 g_value_unset (&subentries_val);
554 g_value_unset (&entry_val);
559 __gst_toc_to_structure (const GstToc * toc)
562 GValue subentries_val = { 0 };
563 GstStructure *ret, *subentry_struct;
564 GstTocEntry *subentry;
566 guint editions_count = 0, chapters_count = 0;
568 g_return_val_if_fail (toc != NULL, NULL);
569 g_return_val_if_fail (toc->entries != NULL, NULL);
571 ret = gst_toc_structure_new (toc->tags, toc->info);
573 g_value_init (&val, GST_TYPE_STRUCTURE);
574 g_value_init (&subentries_val, GST_TYPE_ARRAY);
577 while (cur != NULL) {
578 subentry = cur->data;
580 if (subentry->type == GST_TOC_ENTRY_TYPE_EDITION)
585 /* check for mixed content */
586 if (G_UNLIKELY (chapters_count > 0 && editions_count > 0)) {
588 ("Mixed editions and chapters in the TOC contents, the TOC is broken");
589 gst_structure_free (ret);
590 g_value_unset (&val);
591 g_value_unset (&subentries_val);
595 /* skip empty editions */
596 if (G_UNLIKELY (subentry->type == GST_TOC_ENTRY_TYPE_EDITION
597 && subentry->subentries == NULL)) {
599 ("Empty edition found while serializing TOC to GstStructure, skipping");
604 subentry_struct = gst_toc_entry_to_structure (subentry, 0);
606 /* check for success */
607 if (G_UNLIKELY (subentry_struct == NULL)) {
608 g_critical ("Couldn't serialize TOC to GstStructure");
609 gst_structure_free (ret);
610 g_value_unset (&val);
611 g_value_unset (&subentries_val);
615 gst_value_set_structure (&val, subentry_struct);
616 gst_value_array_append_value (&subentries_val, &val);
617 gst_structure_free (subentry_struct);
622 gst_structure_id_set_value (ret, GST_QUARK (SUB_ENTRIES), &subentries_val);
624 g_value_unset (&val);
625 g_value_unset (&subentries_val);
630 gst_toc_check_entry_for_uid (const GstTocEntry * entry, const gchar * uid)
634 g_return_val_if_fail (entry != NULL, FALSE);
635 g_return_val_if_fail (uid != NULL, FALSE);
637 if (g_strcmp0 (entry->uid, uid) == 0)
640 cur = entry->subentries;
641 while (cur != NULL) {
642 if (gst_toc_check_entry_for_uid (cur->data, uid))
651 * gst_toc_find_entry:
652 * @toc: #GstToc to search in.
653 * @uid: UID to find #GstTocEntry with.
655 * Find #GstTocEntry with given @uid in the @toc.
657 * Returns: #GstTocEntry with specified @uid from the @toc, or NULL if not found.
662 gst_toc_find_entry (const GstToc * toc, const gchar * uid)
666 g_return_val_if_fail (toc != NULL, NULL);
667 g_return_val_if_fail (uid != NULL, NULL);
670 while (cur != NULL) {
671 if (gst_toc_check_entry_for_uid (cur->data, uid))
680 * gst_toc_entry_copy:
681 * @entry: #GstTocEntry to copy.
683 * Copy #GstTocEntry with all subentries (deep copy).
685 * Returns: newly allocated #GstTocEntry in case of success, NULL otherwise;
686 * free it when done with gst_toc_entry_unref().
691 gst_toc_entry_copy (const GstTocEntry * entry)
693 GstTocEntry *ret, *sub;
698 g_return_val_if_fail (entry != NULL, NULL);
700 ret = gst_toc_entry_new (entry->type, entry->uid);
702 if (GST_IS_STRUCTURE (entry->info)) {
703 st = gst_structure_copy (entry->info);
704 gst_structure_free (ret->info);
708 if (GST_IS_TAG_LIST (entry->tags)) {
709 list = gst_tag_list_copy (entry->tags);
710 gst_tag_list_unref (ret->tags);
715 while (cur != NULL) {
716 if (GST_IS_PAD (cur->data))
717 ret->pads = g_list_prepend (ret->pads, gst_object_ref (cur->data));
720 ret->pads = g_list_reverse (ret->pads);
722 cur = entry->subentries;
723 while (cur != NULL) {
724 sub = gst_toc_entry_copy (cur->data);
727 ret->subentries = g_list_prepend (ret->subentries, sub);
731 ret->subentries = g_list_reverse (ret->subentries);
738 * @toc: #GstToc to copy.
740 * Copy #GstToc with all subentries (deep copy).
742 * Returns: newly allocated #GstToc in case of success, NULL otherwise;
743 * free it when done with gst_toc_free().
748 gst_toc_copy (const GstToc * toc)
756 g_return_val_if_fail (toc != NULL, NULL);
758 ret = gst_toc_new ();
760 if (GST_IS_STRUCTURE (toc->info)) {
761 st = gst_structure_copy (toc->info);
762 gst_structure_free (ret->info);
766 if (GST_IS_TAG_LIST (toc->tags)) {
767 list = gst_tag_list_copy (toc->tags);
768 gst_tag_list_unref (ret->tags);
773 while (cur != NULL) {
774 entry = gst_toc_entry_copy (cur->data);
777 ret->entries = g_list_prepend (ret->entries, entry);
781 ret->entries = g_list_reverse (ret->entries);
787 * gst_toc_entry_set_start_stop:
788 * @entry: #GstTocEntry to set values.
789 * @start: start value to set.
790 * @stop: stop value to set.
792 * Set @start and @stop values for the @entry.
797 gst_toc_entry_set_start_stop (GstTocEntry * entry, gint64 start, gint64 stop)
800 GstStructure *structure = NULL;
802 g_return_if_fail (entry != NULL);
803 g_return_if_fail (GST_IS_STRUCTURE (entry->info));
805 if (gst_structure_id_has_field_typed (entry->info, GST_QUARK (TIME),
806 GST_TYPE_STRUCTURE)) {
807 val = gst_structure_id_get_value (entry->info, GST_QUARK (TIME));
808 structure = gst_structure_copy (gst_value_get_structure (val));
811 if (structure == NULL)
812 structure = gst_structure_new_id_empty (GST_QUARK (TIME_STRUCTURE));
814 gst_structure_id_set (structure, GST_QUARK (START),
815 G_TYPE_INT64, start, GST_QUARK (STOP), G_TYPE_INT64, stop, NULL);
817 gst_structure_id_set (entry->info, GST_QUARK (TIME),
818 GST_TYPE_STRUCTURE, structure, NULL);
820 gst_structure_free (structure);
824 * gst_toc_entry_get_start_stop:
825 * @entry: #GstTocEntry to get values from.
826 * @start: (out): the storage for the start value, leave #NULL if not need.
827 * @stop: (out): the storage for the stop value, leave #NULL if not need.
829 * Get start and stop values from the @entry and write them into appropriate storages.
831 * Returns: TRUE if all non-NULL storage pointers were filled with appropriate values,
837 gst_toc_entry_get_start_stop (const GstTocEntry * entry, gint64 * start,
842 const GstStructure *structure;
844 g_return_val_if_fail (entry != NULL, FALSE);
845 g_return_val_if_fail (GST_IS_STRUCTURE (entry->info), FALSE);
847 if (!gst_structure_id_has_field_typed (entry->info,
848 GST_QUARK (TIME), GST_TYPE_STRUCTURE))
851 val = gst_structure_id_get_value (entry->info, GST_QUARK (TIME));
852 structure = gst_value_get_structure (val);
855 if (gst_structure_id_has_field_typed (structure,
856 GST_QUARK (START), G_TYPE_INT64))
858 g_value_get_int64 (gst_structure_id_get_value (structure,
865 if (gst_structure_id_has_field_typed (structure,
866 GST_QUARK (STOP), G_TYPE_INT64))
868 g_value_get_int64 (gst_structure_id_get_value (structure,
878 * gst_toc_entry_type_get_nick:
879 * @type: a #GstTocEntryType.
881 * Converts @type to a string representation.
883 * Returns: Returns the human-readable @type. Can be NULL if an error occurred.
887 gst_toc_entry_type_get_nick (GstTocEntryType type)
889 const gchar *entry_types[] = { "chapter", "edition" };
891 g_return_val_if_fail ((gint) type >= 0
892 && (gint) type < G_N_ELEMENTS (entry_types), NULL);
893 return entry_types[type];
897 __gst_toc_structure_get_updated (const GstStructure * toc)
901 g_return_val_if_fail (GST_IS_STRUCTURE (toc), FALSE);
903 if (G_LIKELY (gst_structure_id_has_field_typed (toc,
904 GST_QUARK (UPDATED), G_TYPE_BOOLEAN))) {
905 val = gst_structure_id_get_value (toc, GST_QUARK (UPDATED));
906 return g_value_get_boolean (val);
913 __gst_toc_structure_set_updated (GstStructure * toc, gboolean updated)
915 g_return_if_fail (toc != NULL);
917 gst_structure_id_set (toc, GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated,
922 __gst_toc_structure_get_extend_uid (const GstStructure * toc)
926 g_return_val_if_fail (GST_IS_STRUCTURE (toc), NULL);
928 if (G_LIKELY (gst_structure_id_has_field_typed (toc,
929 GST_QUARK (EXTEND_UID), G_TYPE_STRING))) {
930 val = gst_structure_id_get_value (toc, GST_QUARK (EXTEND_UID));
931 return g_strdup (g_value_get_string (val));
938 __gst_toc_structure_set_extend_uid (GstStructure * toc,
939 const gchar * extend_uid)
941 g_return_if_fail (toc != NULL);
942 g_return_if_fail (extend_uid != NULL);
944 gst_structure_id_set (toc, GST_QUARK (EXTEND_UID), G_TYPE_STRING, extend_uid,