clapper: Fallback to stream tags for single stream content

In cases where audio file is played, there may not be separate global tags due to
only single stream. In this cases we should also use stream tags as if they were
global ones, but at the same time prioritize global tags if any are available.
This commit is contained in:
Rafał Dzięgiel
2025-12-18 15:32:04 +01:00
parent 1ab691ab8e
commit 5f7cf0c4c8
5 changed files with 39 additions and 20 deletions

View File

@@ -28,7 +28,7 @@
G_BEGIN_DECLS
G_GNUC_INTERNAL
void clapper_media_item_update_from_tag_list (ClapperMediaItem *item, const GstTagList *tags, ClapperPlayer *player);
void clapper_media_item_update_from_tag_list (ClapperMediaItem *item, const GstTagList *tags, gboolean allow_overwrite, ClapperPlayer *player);
G_GNUC_INTERNAL
void clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDiscovererInfo *info);

View File

@@ -652,22 +652,18 @@ clapper_media_item_get_timeline (ClapperMediaItem *self)
void
clapper_media_item_update_from_tag_list (ClapperMediaItem *self, const GstTagList *tags,
ClapperPlayer *player)
gboolean allow_overwrite, ClapperPlayer *player)
{
GstTagScope scope = gst_tag_list_get_scope (tags);
ClapperReactableItemUpdatedFlags flags = 0;
gboolean changed = clapper_media_item_insert_tags_internal (self, tags, player->app_bus, allow_overwrite, &flags);
if (scope == GST_TAG_SCOPE_GLOBAL) {
ClapperReactableItemUpdatedFlags flags = 0;
gboolean changed = clapper_media_item_insert_tags_internal (self, tags, player->app_bus, TRUE, &flags);
if (changed) {
ClapperFeaturesManager *features_manager;
if (changed) {
ClapperFeaturesManager *features_manager;
if (player->reactables_manager)
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, self, flags);
if ((features_manager = clapper_player_get_features_manager (player)))
clapper_features_manager_trigger_item_updated (features_manager, self);
}
if (player->reactables_manager)
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, self, flags);
if ((features_manager = clapper_player_get_features_manager (player)))
clapper_features_manager_trigger_item_updated (features_manager, self);
}
}
@@ -783,8 +779,8 @@ clapper_media_item_update_from_parsed_playlist (ClapperMediaItem *self, GListSto
GST_OBJECT_LOCK (other_item);
if (other_item->tags)
clapper_media_item_update_from_tag_list (self, other_item->tags, player);
if (other_item->tags) // Tags are always GLOBAL here
clapper_media_item_update_from_tag_list (self, other_item->tags, TRUE, player);
/* Since its redirect now, we have to update title to describe new file instead of
* being a playlist title. If other item had parsed title, it also means that tags

View File

@@ -1038,7 +1038,9 @@ _handle_tag_msg (GstMessage *msg, ClapperPlayer *player)
}
player->pending_tags = gst_tag_list_ref (tags);
} else if (G_LIKELY (player->played_item != NULL)) {
clapper_media_item_update_from_tag_list (player->played_item, tags, player);
gboolean is_global = (gst_tag_list_get_scope (tags) == GST_TAG_SCOPE_GLOBAL);
if (is_global || player->stream_tags_allowed)
clapper_media_item_update_from_tag_list (player->played_item, tags, is_global, player);
}
gst_tag_list_unref (tags);
@@ -1116,10 +1118,28 @@ static inline void
_handle_stream_collection_msg (GstMessage *msg, ClapperPlayer *player)
{
GstStreamCollection *collection = NULL;
guint i, n_streams, n_video = 0, n_audio = 0, n_text = 0;
GST_INFO_OBJECT (player, "Stream collection");
gst_message_parse_stream_collection (msg, &collection);
n_streams = gst_stream_collection_get_size (collection);
for (i = 0; i < n_streams; ++i) {
GstStream *stream = gst_stream_collection_get_stream (collection, i);
GstStreamType stream_type = gst_stream_get_stream_type (stream);
if ((stream_type & GST_STREAM_TYPE_VIDEO) == GST_STREAM_TYPE_VIDEO)
n_video++;
else if ((stream_type & GST_STREAM_TYPE_AUDIO) == GST_STREAM_TYPE_AUDIO)
n_audio++;
else if ((stream_type & GST_STREAM_TYPE_TEXT) == GST_STREAM_TYPE_TEXT)
n_text++;
}
player->stream_tags_allowed = (n_video + n_audio + n_text == 1);
GST_DEBUG_OBJECT (player, "Stream tags allowed: %s", (player->stream_tags_allowed) ? "yes" : "no");
clapper_player_take_stream_collection (player, collection);
}
@@ -1214,9 +1234,10 @@ _handle_stream_start_msg (GstMessage *msg, ClapperPlayer *player)
clapper_player_playbin_update_current_decoders (player);
if (player->pending_tags) {
if (G_LIKELY (player->played_item != NULL))
clapper_media_item_update_from_tag_list (player->played_item, player->pending_tags, player);
if (G_LIKELY (player->played_item != NULL)) {
/* Pending tags come from "extractablesrc" and are always GLOBAL (preferred) */
clapper_media_item_update_from_tag_list (player->played_item, player->pending_tags, TRUE, player);
}
gst_clear_tag_list (&player->pending_tags);
}
if (player->pending_toc) {

View File

@@ -61,6 +61,7 @@ struct _ClapperPlayer
/* Pending tags/toc that arrive before stream start.
* To be applied to "played_item", thus no lock needed. */
gboolean stream_tags_allowed;
GstTagList *pending_tags;
GstToc *pending_toc;

View File

@@ -780,6 +780,7 @@ clapper_player_reset (ClapperPlayer *self, gboolean pending_dispose)
GST_OBJECT_UNLOCK (self);
self->stream_tags_allowed = FALSE;
gst_clear_tag_list (&self->pending_tags);
if (self->pending_toc) {