From 3abfd2a5df1144d865eb6b6fedab4a8431131f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Wed, 27 Jan 2021 23:37:33 +0100 Subject: [PATCH] API: add TOC support (video chapters) --- .../clapper/gstclapper-media-info-private.h | 1 + lib/gst/clapper/gstclapper-media-info.c | 29 ++++++++---- lib/gst/clapper/gstclapper-media-info.h | 3 ++ lib/gst/clapper/gstclapper.c | 47 ++++++++++++++++++- 4 files changed, 69 insertions(+), 11 deletions(-) diff --git a/lib/gst/clapper/gstclapper-media-info-private.h b/lib/gst/clapper/gstclapper-media-info-private.h index 00f148b3..3e420586 100644 --- a/lib/gst/clapper/gstclapper-media-info-private.h +++ b/lib/gst/clapper/gstclapper-media-info-private.h @@ -100,6 +100,7 @@ struct _GstClapperMediaInfo gchar *container; gboolean seekable, is_live; GstTagList *tags; + GstToc *toc; GstSample *image_sample; GList *stream_list; diff --git a/lib/gst/clapper/gstclapper-media-info.c b/lib/gst/clapper/gstclapper-media-info.c index 6a2ffe23..3f35215f 100644 --- a/lib/gst/clapper/gstclapper-media-info.c +++ b/lib/gst/clapper/gstclapper-media-info.c @@ -423,26 +423,21 @@ gst_clapper_media_info_finalize (GObject * object) GstClapperMediaInfo *info = GST_CLAPPER_MEDIA_INFO (object); g_free (info->uri); + g_free (info->title); + g_free (info->container); if (info->tags) gst_tag_list_unref (info->tags); - - g_free (info->title); - - g_free (info->container); - + if (info->toc) + gst_toc_unref (info->toc); if (info->image_sample) gst_sample_unref (info->image_sample); - if (info->audio_stream_list) g_list_free (info->audio_stream_list); - if (info->video_stream_list) g_list_free (info->video_stream_list); - if (info->subtitle_stream_list) g_list_free (info->subtitle_stream_list); - if (info->stream_list) g_list_free_full (info->stream_list, g_object_unref); @@ -567,6 +562,8 @@ gst_clapper_media_info_copy (GstClapperMediaInfo * ref) info->is_live = ref->is_live; if (ref->tags) info->tags = gst_tag_list_ref (ref->tags); + if (ref->toc) + info->toc = gst_toc_ref (ref->toc); if (ref->title) info->title = g_strdup (ref->title); if (ref->container) @@ -752,6 +749,20 @@ gst_clapper_media_info_get_tags (const GstClapperMediaInfo * info) return info->tags; } +/** + * gst_clapper_media_info_get_toc: + * @info: a #GstClapperMediaInfo + * + * Returns: (transfer none): the toc contained in media info. + */ +GstToc * +gst_clapper_media_info_get_toc (const GstClapperMediaInfo * info) +{ + g_return_val_if_fail (GST_IS_CLAPPER_MEDIA_INFO (info), NULL); + + return info->toc; +} + /** * gst_clapper_media_info_get_title: * @info: a #GstClapperMediaInfo diff --git a/lib/gst/clapper/gstclapper-media-info.h b/lib/gst/clapper/gstclapper-media-info.h index e926366b..1e101caf 100644 --- a/lib/gst/clapper/gstclapper-media-info.h +++ b/lib/gst/clapper/gstclapper-media-info.h @@ -233,6 +233,9 @@ guint gst_clapper_media_info_get_number_of_subtitle_streams (const GstCl GST_CLAPPER_API GstTagList * gst_clapper_media_info_get_tags (const GstClapperMediaInfo *info); +GST_CLAPPER_API +GstToc * gst_clapper_media_info_get_toc (const GstClapperMediaInfo *info); + GST_CLAPPER_API const gchar * gst_clapper_media_info_get_title (const GstClapperMediaInfo *info); diff --git a/lib/gst/clapper/gstclapper.c b/lib/gst/clapper/gstclapper.c index 16d0ac14..2069abce 100644 --- a/lib/gst/clapper/gstclapper.c +++ b/lib/gst/clapper/gstclapper.c @@ -170,6 +170,7 @@ struct _GstClapper gint buffering; GstTagList *global_tags; + GstToc *global_toc; GstClapperMediaInfo *media_info; GstElement *current_vis_element; @@ -530,6 +531,8 @@ gst_clapper_finalize (GObject * object) g_free (self->subtitle_sid); if (self->global_tags) gst_tag_list_unref (self->global_tags); + if (self->global_toc) + gst_toc_unref (self->global_toc); if (self->video_renderer) g_object_unref (self->video_renderer); if (self->signal_dispatcher) @@ -1102,12 +1105,14 @@ emit_error (GstClapper * self, GError * err) g_object_unref (self->media_info); self->media_info = NULL; } - if (self->global_tags) { gst_tag_list_unref (self->global_tags); self->global_tags = NULL; } - + if (self->global_toc) { + gst_toc_unref (self->global_toc); + self->global_toc = NULL; + } self->seek_pending = FALSE; remove_seek_source (self); self->seek_position = GST_CLOCK_TIME_NONE; @@ -1807,6 +1812,37 @@ tags_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data) gst_tag_list_unref (tags); } +static void +toc_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data) +{ + GstClapper *self = GST_CLAPPER (user_data); + GstToc *toc = NULL; + + gst_message_parse_toc (msg, &toc, NULL); + + GST_DEBUG_OBJECT (self, "received %s toc", + gst_toc_get_scope (toc) == GST_TOC_SCOPE_GLOBAL ? "global" : "stream"); + + if (gst_toc_get_scope (toc) == GST_TOC_SCOPE_GLOBAL) { + g_mutex_lock (&self->lock); + if (self->media_info) { + if (self->media_info->toc) + gst_toc_unref (self->media_info->toc); + self->media_info->toc = gst_toc_ref (toc); + media_info_update (self, self->media_info); + g_mutex_unlock (&self->lock); + emit_media_info_updated_signal (self); + } else { + if (self->global_toc) + gst_toc_unref (self->global_toc); + self->global_toc = gst_toc_ref (toc); + g_mutex_unlock (&self->lock); + } + } + + gst_toc_unref (toc); +} + static void element_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data) { @@ -2731,8 +2767,10 @@ gst_clapper_media_info_create (GstClapper * self) media_info = gst_clapper_media_info_new (self->uri); media_info->duration = gst_clapper_get_duration (self); media_info->tags = self->global_tags; + media_info->toc = self->global_toc; media_info->is_live = self->is_live; self->global_tags = NULL; + self->global_toc = NULL; query = gst_query_new_seeking (GST_FORMAT_TIME); if (gst_element_query (self->playbin, query)) @@ -2953,6 +2991,7 @@ gst_clapper_main (gpointer data) g_signal_connect (G_OBJECT (bus), "message::element", G_CALLBACK (element_cb), self); g_signal_connect (G_OBJECT (bus), "message::tag", G_CALLBACK (tags_cb), self); + g_signal_connect (G_OBJECT (bus), "message::toc", G_CALLBACK (toc_cb), self); if (self->use_playbin3) { g_signal_connect (G_OBJECT (bus), "message::stream-collection", @@ -3256,6 +3295,10 @@ gst_clapper_stop_internal (GstClapper * self, gboolean transient) gst_tag_list_unref (self->global_tags); self->global_tags = NULL; } + if (self->global_toc) { + gst_toc_unref (self->global_toc); + self->global_toc = NULL; + } self->seek_pending = FALSE; remove_seek_source (self); self->seek_position = GST_CLOCK_TIME_NONE;