From e2170cbdc7d6f0b6dd0693f683a1ada76ffda2bf Mon Sep 17 00:00:00 2001 From: Rafostar Date: Tue, 12 Jan 2021 13:23:19 +0100 Subject: [PATCH] player: add TOC support Retrive and store TOC data as part of global MediaInfo object. This is useful for obtaining various video info stored in TOC (e.g. chapters). --- .../gst/player/gstplayer-media-info-private.h | 1 + gst-libs/gst/player/gstplayer-media-info.c | 19 ++++++++ gst-libs/gst/player/gstplayer-media-info.h | 3 ++ gst-libs/gst/player/gstplayer.c | 46 +++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/gst-libs/gst/player/gstplayer-media-info-private.h b/gst-libs/gst/player/gstplayer-media-info-private.h index 70aaea925..5c9902287 100644 --- a/gst-libs/gst/player/gstplayer-media-info-private.h +++ b/gst-libs/gst/player/gstplayer-media-info-private.h @@ -99,6 +99,7 @@ struct _GstPlayerMediaInfo gchar *container; gboolean seekable, is_live; GstTagList *tags; + GstToc *toc; GstSample *image_sample; GList *stream_list; diff --git a/gst-libs/gst/player/gstplayer-media-info.c b/gst-libs/gst/player/gstplayer-media-info.c index 6c9a4a887..4b31e8a3e 100644 --- a/gst-libs/gst/player/gstplayer-media-info.c +++ b/gst-libs/gst/player/gstplayer-media-info.c @@ -430,6 +430,9 @@ gst_player_media_info_finalize (GObject * object) g_free (info->container); + if (info->toc) + gst_toc_unref (info->toc); + if (info->image_sample) gst_sample_unref (info->image_sample); @@ -566,6 +569,8 @@ gst_player_media_info_copy (GstPlayerMediaInfo * 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) @@ -751,6 +756,20 @@ gst_player_media_info_get_tags (const GstPlayerMediaInfo * info) return info->tags; } +/** + * gst_player_media_info_get_toc: + * @info: a #GstPlayerMediaInfo + * + * Returns: (transfer none): the toc contained in media info. + */ +GstToc * +gst_player_media_info_get_toc (const GstPlayerMediaInfo * info) +{ + g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), NULL); + + return info->toc; +} + /** * gst_player_media_info_get_title: * @info: a #GstPlayerMediaInfo diff --git a/gst-libs/gst/player/gstplayer-media-info.h b/gst-libs/gst/player/gstplayer-media-info.h index ab034b158..8f6220ad9 100644 --- a/gst-libs/gst/player/gstplayer-media-info.h +++ b/gst-libs/gst/player/gstplayer-media-info.h @@ -232,6 +232,9 @@ guint gst_player_media_info_get_number_of_subtitle_streams (const GstPla GST_PLAYER_API GstTagList* gst_player_media_info_get_tags (const GstPlayerMediaInfo *info); +GST_PLAYER_API +GstToc* gst_player_media_info_get_toc (const GstPlayerMediaInfo *info); + GST_PLAYER_API const gchar* gst_player_media_info_get_title (const GstPlayerMediaInfo *info); diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c index 62d5cb487..76c2341ba 100644 --- a/gst-libs/gst/player/gstplayer.c +++ b/gst-libs/gst/player/gstplayer.c @@ -182,6 +182,7 @@ struct _GstPlayer gint buffering; GstTagList *global_tags; + GstToc *global_toc; GstPlayerMediaInfo *media_info; GstElement *current_vis_element; @@ -542,6 +543,8 @@ gst_player_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) @@ -1120,6 +1123,11 @@ emit_error (GstPlayer * self, GError * err) 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; @@ -1819,6 +1827,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) +{ + GstPlayer *self = GST_PLAYER (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) { @@ -2743,8 +2782,10 @@ gst_player_media_info_create (GstPlayer * self) media_info = gst_player_media_info_new (self->uri); media_info->duration = gst_player_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)) @@ -2969,6 +3010,7 @@ gst_player_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", @@ -3273,6 +3315,10 @@ gst_player_stop_internal (GstPlayer * 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; -- 2.28.0