X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgsttoc.c;h=fd6bd665eb14b73b8536410ea9147cd404690b34;hb=f34472822c257359d69ebf671b81d85646a40618;hp=4e1ab8d422853abaaa77cbdb9a394f78b704b1cc;hpb=0c5b3cc5f92bca167db008ce5310279c7d11b649;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gsttoc.c b/gst/gsttoc.c index 4e1ab8d..fd6bd66 100644 --- a/gst/gsttoc.c +++ b/gst/gsttoc.c @@ -15,12 +15,13 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** * SECTION:gsttoc + * @title: GstToc * @short_description: Generic table of contents support * @see_also: #GstStructure, #GstEvent, #GstMessage, #GstQuery * @@ -35,28 +36,40 @@ * * Using TOC is very easy. Firstly, create #GstToc structure which represents root * contents of the source. You can also attach TOC-specific tags to it. Then fill - * it with #GstTocEntry entries by appending them to #GstToc.entries #GstTocEntry.subentries - * lists. You should use GST_TOC_ENTRY_TYPE_CHAPTER for generic TOC entry and - * GST_TOC_ENTRY_TYPE_EDITION for the entries which are considered to be alternatives - * (like DVD angles, Matroska editions and so on). + * it with #GstTocEntry entries by appending them to the #GstToc using + * gst_toc_append_entry(), and appending subentries to a #GstTocEntry using + * gst_toc_entry_append_sub_entry(). * * Note that root level of the TOC can contain only either editions or chapters. You * should not mix them together at the same level. Otherwise you will get serialization * /deserialization errors. Make sure that no one of the entries has negative start and * stop values. * - * Please, use #GstToc.info and #GstTocEntry.info fields in that way: create a #GstStructure, - * put all info related to your element there and put this structure into the info field under - * the name of your element. Some fields in the info structure can be used for internal purposes, - * so you should use it in the way described above to not to overwrite already existent fields. - * * Use gst_event_new_toc() to create a new TOC #GstEvent, and gst_event_parse_toc() to * parse received TOC event. Use gst_event_new_toc_select() to create a new TOC select #GstEvent, * and gst_event_parse_toc_select() to parse received TOC select event. The same rule for * the #GstMessage: gst_message_new_toc() to create new TOC #GstMessage, and - * gst_message_parse_toc() to parse received TOC message. Also you can create a new TOC query - * with gst_query_new_toc(), set it with gst_query_set_toc() and parse it with - * gst_query_parse_toc(). + * gst_message_parse_toc() to parse received TOC message. + * + * TOCs can have global scope or current scope. Global scope TOCs contain + * all entries that can possibly be selected using a toc select event, and + * are what an application is usually interested in. TOCs with current scope + * only contain the parts of the TOC relevant to the currently selected/playing + * stream; the current scope TOC is used by downstream elements such as muxers + * to write correct TOC entries when transcoding files, for example. When + * playing a DVD, the global TOC would contain a hierarchy of all titles, + * chapters and angles, for example, while the current TOC would only contain + * the chapters for the currently playing title if playback of a specific + * title was requested. + * + * Applications and plugins should not rely on TOCs having a certain kind of + * structure, but should allow for different alternatives. For example, a + * simple CUE sheet embedded in a file may be presented as a flat list of + * track entries, or could have a top-level edition node (or some other + * alternative type entry) with track entries underneath that node; or even + * multiple top-level edition nodes (or some other alternative type entries) + * each with track entries underneath, in case the source file has extracted + * a track listing from different sources). */ #ifdef HAVE_CONFIG_H @@ -84,12 +97,15 @@ struct _GstTocEntry GstClockTime start, stop; GList *subentries; GstTagList *tags; + GstTocLoopType loop_type; + gint repeat_count; }; struct _GstToc { GstMiniObject mini_object; + GstTocScope scope; GList *entries; GstTagList *tags; }; @@ -101,11 +117,15 @@ static void gst_toc_free (GstToc * toc); static GstTocEntry *gst_toc_entry_copy (const GstTocEntry * toc); static void gst_toc_entry_free (GstTocEntry * toc); +GType _gst_toc_type = 0; +GType _gst_toc_entry_type = 0; + GST_DEFINE_MINI_OBJECT_TYPE (GstToc, gst_toc); GST_DEFINE_MINI_OBJECT_TYPE (GstTocEntry, gst_toc_entry); /** * gst_toc_new: + * @scope: scope of this TOC * * Create a new #GstToc structure. * @@ -113,22 +133,40 @@ GST_DEFINE_MINI_OBJECT_TYPE (GstTocEntry, gst_toc_entry); * with gst_toc_unref(). */ GstToc * -gst_toc_new (void) +gst_toc_new (GstTocScope scope) { GstToc *toc; + g_return_val_if_fail (scope == GST_TOC_SCOPE_GLOBAL || + scope == GST_TOC_SCOPE_CURRENT, NULL); + toc = g_slice_new0 (GstToc); gst_mini_object_init (GST_MINI_OBJECT_CAST (toc), 0, GST_TYPE_TOC, (GstMiniObjectCopyFunction) gst_toc_copy, NULL, (GstMiniObjectFreeFunction) gst_toc_free); + toc->scope = scope; toc->tags = gst_tag_list_new_empty (); return toc; } /** + * gst_toc_get_scope: + * @toc: a #GstToc instance + * + * Returns: scope of @toc + */ +GstTocScope +gst_toc_get_scope (const GstToc * toc) +{ + g_return_val_if_fail (toc != NULL, GST_TOC_SCOPE_GLOBAL); + + return toc->scope; +} + +/** * gst_toc_set_tags: * @toc: A #GstToc instance * @tags: (allow-none) (transfer full): A #GstTagList or %NULL @@ -271,6 +309,10 @@ gst_toc_free (GstToc * toc) if (toc->tags != NULL) gst_tag_list_unref (toc->tags); +#ifdef USE_POISONING + memset (toc, 0xff, sizeof (GstToc)); +#endif + g_slice_free (GstToc, toc); } @@ -287,6 +329,10 @@ gst_toc_entry_free (GstTocEntry * entry) if (entry->tags != NULL) gst_tag_list_unref (entry->tags); +#ifdef USE_POISONING + memset (entry, 0xff, sizeof (GstTocEntry)); +#endif + g_slice_free (GstTocEntry, entry); } @@ -323,7 +369,8 @@ gst_toc_entry_find_sub_entry (const GstTocEntry * entry, const gchar * uid) * * Find #GstTocEntry with given @uid in the @toc. * - * Returns: (transfer none): #GstTocEntry with specified @uid from the @toc, or NULL if not found. + * Returns: (transfer none) (nullable): #GstTocEntry with specified + * @uid from the @toc, or %NULL if not found. */ GstTocEntry * gst_toc_find_entry (const GstToc * toc, const gchar * uid) @@ -350,21 +397,33 @@ gst_toc_find_entry (const GstToc * toc, const gchar * uid) return NULL; } +static GList * +gst_toc_deep_copy_toc_entries (GList * entry_list) +{ + GQueue new_entries = G_QUEUE_INIT; + GList *l; + + for (l = entry_list; l != NULL; l = l->next) + g_queue_push_tail (&new_entries, gst_toc_entry_copy (l->data)); + + return new_entries.head; +} + /** * gst_toc_entry_copy: * @entry: #GstTocEntry to copy. * * Copy #GstTocEntry with all subentries (deep copy). * - * Returns: newly allocated #GstTocEntry in case of success, NULL otherwise; - * free it when done with gst_toc_entry_unref(). + * Returns: (nullable): newly allocated #GstTocEntry in case of + * success, %NULL otherwise; free it when done with + * gst_toc_entry_unref(). */ static GstTocEntry * gst_toc_entry_copy (const GstTocEntry * entry) { - GstTocEntry *ret, *sub; + GstTocEntry *ret; GstTagList *list; - GList *cur; g_return_val_if_fail (entry != NULL, NULL); @@ -380,16 +439,7 @@ gst_toc_entry_copy (const GstTocEntry * entry) ret->tags = list; } - cur = entry->subentries; - while (cur != NULL) { - sub = gst_toc_entry_copy (cur->data); - - if (sub != NULL) - ret->subentries = g_list_prepend (ret->subentries, sub); - - cur = cur->next; - } - ret->subentries = g_list_reverse (ret->subentries); + ret->subentries = gst_toc_deep_copy_toc_entries (entry->subentries); return ret; } @@ -400,20 +450,18 @@ gst_toc_entry_copy (const GstTocEntry * entry) * * Copy #GstToc with all subentries (deep copy). * - * Returns: newly allocated #GstToc in case of success, NULL otherwise; - * free it when done with gst_toc_free(). + * Returns: (nullable): newly allocated #GstToc in case of success, + * %NULL otherwise; free it when done with gst_toc_unref(). */ static GstToc * gst_toc_copy (const GstToc * toc) { GstToc *ret; - GstTocEntry *entry; - GList *cur; GstTagList *list; g_return_val_if_fail (toc != NULL, NULL); - ret = gst_toc_new (); + ret = gst_toc_new (toc->scope); if (GST_IS_TAG_LIST (toc->tags)) { list = gst_tag_list_copy (toc->tags); @@ -421,16 +469,7 @@ gst_toc_copy (const GstToc * toc) ret->tags = list; } - cur = toc->entries; - while (cur != NULL) { - entry = gst_toc_entry_copy (cur->data); - - if (entry != NULL) - ret->entries = g_list_prepend (ret->entries, entry); - - cur = cur->next; - } - ret->entries = g_list_reverse (ret->entries); + ret->entries = gst_toc_deep_copy_toc_entries (toc->entries); return ret; } @@ -456,20 +495,21 @@ gst_toc_entry_set_start_stop_times (GstTocEntry * entry, gint64 start, /** * gst_toc_entry_get_start_stop_times: * @entry: #GstTocEntry to get values from. - * @start: (out): the storage for the start value, leave #NULL if not need. - * @stop: (out): the storage for the stop value, leave #NULL if not need. + * @start: (out) (allow-none): the storage for the start value, leave + * %NULL if not need. + * @stop: (out) (allow-none): the storage for the stop value, leave + * %NULL if not need. * - * Get start and stop values from the @entry and write them into appropriate storages. + * Get @start and @stop values from the @entry and write them into appropriate + * storages. * - * Returns: TRUE if all non-NULL storage pointers were filled with appropriate values, - * FALSE otherwise. + * Returns: %TRUE if all non-%NULL storage pointers were filled with appropriate + * values, %FALSE otherwise. */ gboolean gst_toc_entry_get_start_stop_times (const GstTocEntry * entry, gint64 * start, gint64 * stop) { - gboolean ret = TRUE; - g_return_val_if_fail (entry != NULL, FALSE); if (start != NULL) @@ -477,10 +517,63 @@ gst_toc_entry_get_start_stop_times (const GstTocEntry * entry, gint64 * start, if (stop != NULL) *stop = entry->stop; - return ret; + return TRUE; } /** + * gst_toc_entry_set_loop: + * @entry: #GstTocEntry to set values. + * @loop_type: loop_type value to set. + * @repeat_count: repeat_count value to set. + * + * Set @loop_type and @repeat_count values for the @entry. + * + * Since: 1.4 + */ +void +gst_toc_entry_set_loop (GstTocEntry * entry, GstTocLoopType loop_type, + gint repeat_count) +{ + g_return_if_fail (entry != NULL); + + entry->loop_type = loop_type; + entry->repeat_count = repeat_count; +} + +/** + * gst_toc_entry_get_loop: + * @entry: #GstTocEntry to get values from. + * @loop_type: (out) (allow-none): the storage for the loop_type + * value, leave %NULL if not need. + * @repeat_count: (out) (allow-none): the storage for the repeat_count + * value, leave %NULL if not need. + * + * Get @loop_type and @repeat_count values from the @entry and write them into + * appropriate storages. Loops are e.g. used by sampled instruments. GStreamer + * is not automatically applying the loop. The application can process this + * meta data and use it e.g. to send a seek-event to loop a section. + * + * Returns: %TRUE if all non-%NULL storage pointers were filled with appropriate + * values, %FALSE otherwise. + * + * Since: 1.4 + */ +gboolean +gst_toc_entry_get_loop (const GstTocEntry * entry, GstTocLoopType * loop_type, + gint * repeat_count) +{ + g_return_val_if_fail (entry != NULL, FALSE); + + if (loop_type != NULL) + *loop_type = entry->loop_type; + if (repeat_count != NULL) + *repeat_count = entry->repeat_count; + + return TRUE; +} + + +/** * gst_toc_entry_type_get_nick: * @type: a #GstTocEntryType. * @@ -597,7 +690,7 @@ gst_toc_entry_append_sub_entry (GstTocEntry * entry, GstTocEntry * subentry) } /** - * gst_toc_entry_get_uid: + * gst_toc_entry_get_sub_entries: * @entry: A #GstTocEntry instance * * Gets the sub-entries of @entry. @@ -692,7 +785,7 @@ gst_toc_entry_get_toc (GstTocEntry * entry) * * Gets the parent #GstTocEntry of @entry. * - * Returns: (transfer none): The parent #GstTocEntry of @entry + * Returns: (transfer none) (nullable): The parent #GstTocEntry of @entry */ GstTocEntry * gst_toc_entry_get_parent (GstTocEntry * entry) @@ -730,7 +823,15 @@ void gst_toc_dump (GstToc * toc) { #ifndef GST_DISABLE_GST_DEBUG - GST_TRACE (" Toc %p, tags: %" GST_PTR_FORMAT, toc, toc->tags); + GST_TRACE (" Toc %p, scope: %s, tags: %" GST_PTR_FORMAT, toc, + (toc->scope == GST_TOC_SCOPE_GLOBAL) ? "global" : "current", toc->tags); gst_toc_dump_entries (toc->entries, 2); #endif } + +void +_priv_gst_toc_initialize (void) +{ + _gst_toc_type = gst_toc_get_type (); + _gst_toc_entry_type = gst_toc_entry_get_type (); +}