[vlc-commits] [Git][videolan/vlc][master] 9 commits: input: add priority based metadata merging

Steve Lhomme (@robUx4) gitlab at videolan.org
Mon Aug 12 05:40:14 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
cb4c8128 by Ayush Dey at 2024-08-12T05:25:40+00:00
input: add priority based metadata merging

The vlc_meta_t struct now uses an array of struct vlc_meta_value objects to store
metadata values along with their associated priorities (VLC_META_PRIORITY_BASIC,
VLC_META_PRIORITY_PLAYLIST, VLC_META_PRIORITY_INBAND).
Modified the vlc_meta_Merge function to support priority-based metadata merging.
Metadata values and extra tags in the destination (dst) are only overwritten by
source (src) values if the source's priority is greater than or equal to the
destination's priority.
Refs #4143

- - - - -
118925e3 by Ayush Dey at 2024-08-12T05:25:40+00:00
input: add functions to set metadata with priority

Rename `vlc_meta_Set` to `vlc_meta_SetWithPriority` and `vlc_meta_SetExtra` to
`vlc_meta_SetExtraWithPriority`. These functions now accept an additional `priority`
argument to set the metadata priority for a given key.

Add two macros, `vlc_meta_Set` and `vlc_meta_SetExtra`, which call their respective
functions with `VLC_META_PRIORITY_BASIC` as the default priority.
Refs #4143

- - - - -
fd442e5a by Ayush Dey at 2024-08-12T05:25:40+00:00
lua: modify TRY_META macro to call vlc_meta_SetWithPriority

In TRY_META macro, replace input_item_Set##b() with vlc_meta_SetWithPriority().
Rename the TrackNum field to TrackNumber and ArtURL to ArtworkURL for
consistency with the vlc_meta_type_t enumeration.
Refs #4143

- - - - -
192ae78b by Ayush Dey at 2024-08-12T05:25:40+00:00
lua: add trusted metadata property

Add function `file_is_playlist` to parse the `trusted` property
of a file. This function will be used to upgrade the metadata
priority from `VLC_META_PRIORITY_BASIC` to `VLC_META_PRIORITY_PLAYLIST`
for files marked as trusted. Set the `trusted` property of CUE files
as they require playlist metadata priority.
Refs #4143

- - - - -
a4c26155 by Ayush Dey at 2024-08-12T05:25:40+00:00
lua: set metadata priority based on `trusted` property

Check for value of parsed `trusted` property. If the trusted
property is true, the metadata priority is elevated to VLC_META_PRIORITY_PLAYLIST.
If trusted is false, the metadata priority defaults to VLC_META_PRIORITY_BASIC.

Refs #4143

- - - - -
015a65ac by Ayush Dey at 2024-08-12T05:25:40+00:00
input: split StartTitle function into StartTitle and SetStopStart

This commit splits the StartTitle function and introduces the SetStopStart
function, which is responsible for assigning the 'start-time' and 'stop-time'
values of the track to the `priv->i_start` and `priv->i_stop` variables.
Refs #4143

- - - - -
1adfce74 by Ayush Dey at 2024-08-12T05:25:40+00:00
input: call SetStopStart() for all input threads

Move the SetStopStart function to ensure it is called for all input threads, especially
during preparsing. It ensures that the correct timings are used before the duration of
the input_item_t is set. Previously, 'start-time' and 'stop-time' values were not parsed
during preparation, leading to priv->i_start and priv->i_stop defaulting to 0.
Refs #4143

- - - - -
c86e464f by Ayush Dey at 2024-08-12T05:25:40+00:00
input: add input_SetItemDuration function

Add input_SetItemDuration wrapper function to use the 'start-time' and
'stop-time' values to calculate the track duration.
Refs #4143

- - - - -
bf5b6d59 by Ayush Dey at 2024-08-12T05:25:40+00:00
input: replace input_item_SetDuration calls with input_SetItemDuration

Fixes #4143

In a `vlc_meta_t` object, each metadata key is associated with a priority:
VLC_META_PRIORITY_BASIC, VLC_META_PRIORITY_PLAYLIST, or VLC_META_PRIORITY_INBAND.
During metadata merging, keys with higher or equal priority can override those
with lower priority. When parsing playlist metadata from a CUE file, keys are now
assigned a priority of VLC_META_PRIORITY_PLAYLIST. This change prevents subsequent
audio files, which have VLC_META_PRIORITY_BASIC, from overriding the playlist metadata.

Additionally, this commit ensures that the duration of individual tracks is calculated
using the 'start-time' and 'stop-time' options. This prevents the total track duration
from overriding the individual track durations in the playlist.

- - - - -


9 changed files:

- include/vlc_meta.h
- modules/lua/vlc.c
- share/lua/playlist/cue.lua
- src/input/input.c
- src/input/input_internal.h
- src/input/meta.c
- src/input/parse.c
- src/libvlccore.sym
- src/player/input.c


Changes:

=====================================
include/vlc_meta.h
=====================================
@@ -62,6 +62,13 @@ typedef enum vlc_meta_type_t
 
 #define VLC_META_TYPE_COUNT 27
 
+typedef enum
+{
+    VLC_META_PRIORITY_BASIC,
+    VLC_META_PRIORITY_PLAYLIST,
+    VLC_META_PRIORITY_INBAND
+} vlc_meta_priority_t;
+
 #define ITEM_PREPARSED       1
 #define ITEM_ART_FETCHED     2
 #define ITEM_ART_NOTFOUND    4
@@ -73,7 +80,7 @@ struct vlc_meta_t;
 
 VLC_API vlc_meta_t * vlc_meta_New( void ) VLC_USED;
 VLC_API void vlc_meta_Delete( vlc_meta_t *m );
-VLC_API void vlc_meta_Set( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val );
+VLC_API void vlc_meta_SetWithPriority( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val, vlc_meta_priority_t priority );
 VLC_API const char * vlc_meta_Get( const vlc_meta_t *p_meta, vlc_meta_type_t meta_type );
 
 /**
@@ -83,8 +90,9 @@ VLC_API const char * vlc_meta_Get( const vlc_meta_t *p_meta, vlc_meta_type_t met
  * \param psz_name meta extra name (nonnullable)
  * \param psz_value meta extra value (nullable)
  *  Removed from meta extra if set to NULL
+ * \param priority metadata priority (in terms of vlc_meta_priority_t)
  */
-VLC_API void vlc_meta_SetExtra( vlc_meta_t *m, const char *psz_name, const char *psz_value );
+VLC_API void vlc_meta_SetExtraWithPriority( vlc_meta_t *m, const char *psz_name, const char *psz_value, vlc_meta_priority_t priority );
 VLC_API const char * vlc_meta_GetExtra( const vlc_meta_t *m, const char *psz_name );
 VLC_API unsigned vlc_meta_GetExtraCount( const vlc_meta_t *m );
 
@@ -115,6 +123,9 @@ typedef struct meta_export_t
 
 VLC_API int input_item_WriteMeta(vlc_object_t *, input_item_t *);
 
+#define vlc_meta_Set( meta, meta_type, b )             vlc_meta_SetWithPriority( meta, meta_type, b, VLC_META_PRIORITY_BASIC )
+#define vlc_meta_SetExtra( meta, psz_name, psz_value ) vlc_meta_SetExtraWithPriority( meta, psz_name, psz_value, VLC_META_PRIORITY_BASIC )
+
 /* Setters for meta.
  * Warning: Make sure to use the input_item meta setters (defined in vlc_input_item.h)
  * instead of those one. */


=====================================
modules/lua/vlc.c
=====================================
@@ -95,6 +95,18 @@ static int file_compare( const char **a, const char **b )
     return strcmp( *a, *b );
 }
 
+/* Function to parse the trusted property of a file */
+static bool file_is_playlist( lua_State *L )
+{
+    bool trusted = false;
+    lua_getfield(L, -1, "trusted");
+    if( !lua_isnil(L, -1) && lua_isboolean(L, -1) )
+        trusted = lua_toboolean(L, -1);
+
+    lua_pop( L, 1 );
+    return trusted;
+}
+
 static char **vlclua_dir_list_append( char **restrict list, char *basedir,
                                       const char *luadirname )
 {
@@ -246,6 +258,8 @@ char *vlclua_find_file( const char *psz_luadirname, const char *psz_name )
 void vlclua_read_meta_data( vlc_object_t *p_this, lua_State *L,
                             input_item_t *p_input )
 {
+    vlc_meta_priority_t priority = file_is_playlist( L )? VLC_META_PRIORITY_PLAYLIST:
+                                                          VLC_META_PRIORITY_BASIC;
 #define TRY_META( a, b )                                        \
     lua_getfield( L, -1, a );                                   \
     if( lua_isstring( L, -1 ) &&                                \
@@ -254,16 +268,20 @@ void vlclua_read_meta_data( vlc_object_t *p_this, lua_State *L,
         char *psz_value = strdup( lua_tostring( L, -1 ) );      \
         EnsureUTF8( psz_value );                                \
         msg_Dbg( p_this, #b ": %s", psz_value );                \
-        input_item_Set ## b ( p_input, psz_value );             \
+        vlc_meta_SetWithPriority( p_input->p_meta,              \
+                                  vlc_meta_ ## b,               \
+                                  psz_value,                    \
+                                  priority );                   \
         free( psz_value );                                      \
     }                                                           \
     lua_pop( L, 1 ); /* pop a */
+    vlc_mutex_lock( &p_input->lock );
     TRY_META( "title", Title );
     TRY_META( "artist", Artist );
     TRY_META( "genre", Genre );
     TRY_META( "copyright", Copyright );
     TRY_META( "album", Album );
-    TRY_META( "tracknum", TrackNum );
+    TRY_META( "tracknum", TrackNumber );
     TRY_META( "description", Description );
     TRY_META( "rating", Rating );
     TRY_META( "date", Date );
@@ -273,13 +291,14 @@ void vlclua_read_meta_data( vlc_object_t *p_this, lua_State *L,
     TRY_META( "nowplaying", NowPlaying );
     TRY_META( "publisher",  Publisher );
     TRY_META( "encodedby",  EncodedBy );
-    TRY_META( "arturl",     ArtURL );
+    TRY_META( "arturl",     ArtworkURL );
     TRY_META( "trackid",    TrackID );
     TRY_META( "director",   Director );
     TRY_META( "season",     Season );
     TRY_META( "episode",    Episode );
     TRY_META( "show_name",  ShowName );
     TRY_META( "actors",     Actors );
+    vlc_mutex_unlock( &p_input->lock );
 }
 
 #undef vlclua_read_custom_meta_data
@@ -311,7 +330,9 @@ void vlclua_read_custom_meta_data( vlc_object_t *p_this, lua_State *L,
             const char *psz_key = lua_tostring( L, -2 );
             const char *psz_value = lua_tostring( L, -1 );
 
-            vlc_meta_SetExtra( p_input->p_meta, psz_key, psz_value );
+            vlc_meta_priority_t priority = file_is_playlist( L )? VLC_META_PRIORITY_PLAYLIST:
+                                                                  VLC_META_PRIORITY_BASIC;
+            vlc_meta_SetExtraWithPriority( p_input->p_meta, psz_key, psz_value, priority );
 
             lua_pop( L, 1 ); /* pop "value" */
         }


=====================================
share/lua/playlist/cue.lua
=====================================
@@ -74,6 +74,7 @@ function cue_track( global, track )
     t.date = track.date or global.date
     t.description = global.comment
     t.tracknum = track.num
+    t.trusted = true
     t.options = { ":start-time=" .. track.index01}
 
     return t


=====================================
src/input/input.c
=====================================
@@ -897,6 +897,11 @@ static void StartTitle( input_thread_t * p_input )
                 priv->master->i_seekpoint_offset;
     if( val.i_int > 0 /* TODO: check upper boundary */ )
         input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val );
+}
+
+static void SetStopStart( input_thread_t * p_input )
+{
+    input_thread_private_t *priv = input_priv(p_input);
 
     /* Start/stop/run time */
     priv->i_start = llroundl(CLOCK_FREQ *
@@ -1335,6 +1340,7 @@ static int Init( input_thread_t * p_input )
 
     InitTitle( p_input, false );
 
+    SetStopStart( p_input );
     /* Load master infos */
     InputSourceStatistics( master, priv->p_item, priv->p_es_out );
 
@@ -3477,3 +3483,16 @@ bool input_CanPaceControl(input_thread_t *input)
     input_thread_private_t *priv = input_priv(input);
     return priv->master->b_can_pace_control;
 }
+
+void input_SetItemDuration(input_thread_t *input, vlc_tick_t duration)
+{
+    input_thread_private_t *priv = input_priv(input);
+    input_item_t *item = input_GetItem(input);
+
+    if( priv->i_stop == 0 ) /* consider `duration` as stop time, if stop-time not set */
+        duration -= priv->i_start;
+    else /* calculate duration based on start-time and stop-time */
+        duration = priv->i_stop - priv->i_start;
+
+    input_item_SetDuration(item, duration);
+}
\ No newline at end of file


=====================================
src/input/input_internal.h
=====================================
@@ -639,6 +639,17 @@ input_attachment_t *input_GetAttachment(input_thread_t *input, const char *name)
 
 bool input_CanPaceControl(input_thread_t *input);
 
+/**
+ * Set the duration of the input item.
+ *
+ * This function sets the duration of the input item associated with the input thread.
+ * It uses the 'start-time' and 'stop-time' values to calculate the track duration.
+ *
+ * @param input The input thread object.
+ * @param duration The duration to be set, in vlc_tick_t units.
+ */
+void input_SetItemDuration(input_thread_t *input, vlc_tick_t duration);
+
 /* Bound pts_delay */
 #define INPUT_PTS_DELAY_MAX VLC_TICK_FROM_SEC(60)
 


=====================================
src/input/meta.c
=====================================
@@ -36,9 +36,15 @@
 #include "../preparser/art.h"
 #include <vlc_charset.h>
 
+struct vlc_meta_value
+{
+    vlc_meta_priority_t priority;
+    char *value;
+};
+
 struct vlc_meta_t
 {
-    char * ppsz_meta[VLC_META_TYPE_COUNT];
+    struct vlc_meta_value meta[VLC_META_TYPE_COUNT];
 
     vlc_dictionary_t extra_tags;
 
@@ -99,23 +105,41 @@ vlc_meta_t *vlc_meta_New( void )
     vlc_meta_t *m = (vlc_meta_t*)malloc( sizeof(*m) );
     if( !m )
         return NULL;
-    memset( m->ppsz_meta, 0, sizeof(m->ppsz_meta) );
+    for( int i = 0; i < VLC_META_TYPE_COUNT ; i++ )
+    {
+        m->meta[i].value = NULL;
+        m->meta[i].priority = VLC_META_PRIORITY_BASIC;
+    }
     m->i_status = 0;
     vlc_dictionary_init( &m->extra_tags, 0 );
     return m;
 }
 
-/* Free a dictionary key allocated by strdup() in vlc_meta_SetExtra() */
+/* Allocate and insert the new value in the dictionary key `psz_name` */
+static void vlc_meta_InsertExtra( vlc_meta_t *m, const char *psz_name, const char *psz_value, vlc_meta_priority_t priority )
+{
+    struct vlc_meta_value *meta_value = malloc( sizeof(*meta_value) );
+    if( meta_value )
+    {
+        meta_value->value = strdup(psz_value);
+        meta_value->priority = priority;
+        vlc_dictionary_insert( &m->extra_tags, psz_name, meta_value );
+    }
+}
+
+/* Free a dictionary key allocated by strdup() in vlc_meta_SetExtraWithPriority() */
 static void vlc_meta_FreeExtraKey( void *p_data, void *p_obj )
 {
     VLC_UNUSED( p_obj );
-    free( p_data );
+    struct vlc_meta_value *meta_value = p_data;
+    free( meta_value->value );
+    free( meta_value );
 }
 
 void vlc_meta_Delete( vlc_meta_t *m )
 {
     for( int i = 0; i < VLC_META_TYPE_COUNT ; i++ )
-        free( m->ppsz_meta[i] );
+        free( m->meta[i].value );
     vlc_dictionary_clear( &m->extra_tags, vlc_meta_FreeExtraKey, NULL );
     free( m );
 }
@@ -126,32 +150,36 @@ void vlc_meta_Delete( vlc_meta_t *m )
  * FIXME - Why don't we merge those two?
  */
 
-void vlc_meta_Set( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val )
+void vlc_meta_SetWithPriority( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val, vlc_meta_priority_t priority )
 {
-    free( p_meta->ppsz_meta[meta_type] );
+    free( p_meta->meta[meta_type].value );
     assert( psz_val == NULL || IsUTF8( psz_val ) );
-    p_meta->ppsz_meta[meta_type] = psz_val ? strdup( psz_val ) : NULL;
+    p_meta->meta[meta_type].value = psz_val ? strdup( psz_val ) : NULL;
+    p_meta->meta[meta_type].priority = priority;
 }
 
 const char *vlc_meta_Get( const vlc_meta_t *p_meta, vlc_meta_type_t meta_type )
 {
-    return p_meta->ppsz_meta[meta_type];
+    return p_meta->meta[meta_type].value;
 }
 
-void vlc_meta_SetExtra( vlc_meta_t *m, const char *psz_name, const char *psz_value )
+void vlc_meta_SetExtraWithPriority( vlc_meta_t *m, const char *psz_name, const char *psz_value, vlc_meta_priority_t priority )
 {
     assert( psz_name );
-    char *psz_oldvalue = (char *)vlc_dictionary_value_for_key( &m->extra_tags, psz_name );
-    if( psz_oldvalue != kVLCDictionaryNotFound )
+    struct vlc_meta_value *old_meta_value = vlc_dictionary_value_for_key( &m->extra_tags, psz_name );
+    if( old_meta_value != kVLCDictionaryNotFound )
         vlc_dictionary_remove_value_for_key( &m->extra_tags, psz_name,
                                             vlc_meta_FreeExtraKey, NULL );
     if ( psz_value )
-        vlc_dictionary_insert( &m->extra_tags, psz_name, strdup(psz_value) );
+        vlc_meta_InsertExtra( m, psz_name, psz_value, priority );
 }
 
 const char * vlc_meta_GetExtra( const vlc_meta_t *m, const char *psz_name )
 {
-    return (char *)vlc_dictionary_value_for_key(&m->extra_tags, psz_name);
+    struct vlc_meta_value *meta_value = vlc_dictionary_value_for_key(&m->extra_tags, psz_name);
+    if( !meta_value )
+        return NULL;
+    return meta_value->value;
 }
 
 unsigned vlc_meta_GetExtraCount( const vlc_meta_t *m )
@@ -188,10 +216,13 @@ void vlc_meta_Merge( vlc_meta_t *dst, const vlc_meta_t *src )
 
     for( int i = 0; i < VLC_META_TYPE_COUNT; i++ )
     {
-        if( src->ppsz_meta[i] )
+        /* overwrite metadata only when priority of src is 
+           greater than or equal to the priority of dst */
+        if( src->meta[i].value && src->meta[i].priority >= dst->meta[i].priority )
         {
-            free( dst->ppsz_meta[i] );
-            dst->ppsz_meta[i] = strdup( src->ppsz_meta[i] );
+            free( dst->meta[i].value );
+            dst->meta[i].value = strdup( src->meta[i].value );
+            dst->meta[i].priority = src->meta[i].priority;
         }
     }
 
@@ -200,10 +231,20 @@ void vlc_meta_Merge( vlc_meta_t *dst, const vlc_meta_t *src )
     for( int i = 0; ppsz_all_keys && ppsz_all_keys[i]; i++ )
     {
         /* Always try to remove the previous value */
-        vlc_dictionary_remove_value_for_key( &dst->extra_tags, ppsz_all_keys[i], vlc_meta_FreeExtraKey, NULL );
+        struct vlc_meta_value *dst_meta_value = vlc_dictionary_value_for_key( &dst->extra_tags, ppsz_all_keys[i] );
+        struct vlc_meta_value *src_meta_value = vlc_dictionary_value_for_key( &src->extra_tags, ppsz_all_keys[i] );
+        if( dst_meta_value )
+        {
+            /* overwrite metadata only when priority of src is 
+               greater than or equal to the priority of dst */
+            if( src_meta_value->priority < dst_meta_value->priority )
+                continue;
+
+            vlc_dictionary_remove_value_for_key( &dst->extra_tags, ppsz_all_keys[i], vlc_meta_FreeExtraKey, NULL );
+        }
+
+        vlc_meta_InsertExtra( dst, ppsz_all_keys[i], src_meta_value->value, src_meta_value->priority );
 
-        void *p_value = vlc_dictionary_value_for_key( &src->extra_tags, ppsz_all_keys[i] );
-        vlc_dictionary_insert( &dst->extra_tags, ppsz_all_keys[i], strdup( (const char*)p_value ) );
         free( ppsz_all_keys[i] );
     }
     free( ppsz_all_keys );


=====================================
src/input/parse.c
=====================================
@@ -56,7 +56,7 @@ input_item_parser_InputEvent(input_thread_t *input,
     switch (event->type)
     {
         case INPUT_EVENT_TIMES:
-            input_item_SetDuration(input_GetItem(input), event->times.length);
+            input_SetItemDuration(input, event->times.length);
             break;
         case INPUT_EVENT_STATE:
             parser->state = event->state.value;


=====================================
src/libvlccore.sym
=====================================
@@ -668,7 +668,7 @@ vlc_killed
 vlc_join
 vlc_thread_set_name
 vlc_list_children
-vlc_meta_SetExtra
+vlc_meta_SetExtraWithPriority
 vlc_meta_CopyExtraNames
 vlc_meta_Delete
 vlc_meta_Get
@@ -677,7 +677,7 @@ vlc_meta_GetExtraCount
 vlc_meta_GetStatus
 vlc_meta_Merge
 vlc_meta_New
-vlc_meta_Set
+vlc_meta_SetWithPriority
 vlc_meta_SetStatus
 vlc_meta_TypeToLocalizedString
 vlc_meta_TypeToString


=====================================
src/player/input.c
=====================================
@@ -933,7 +933,7 @@ input_thread_Events(input_thread_t *input_thread,
             if (input->length != event->times.length)
             {
                 input->length = event->times.length;
-                input_item_SetDuration(input_GetItem(input->thread), event->times.length);
+                input_SetItemDuration(input->thread, event->times.length);
                 vlc_player_SendEvent(player, on_length_changed, input->length);
                 changed = true;
             }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c4fa5e312cec9835217b14610ebbd198faa98c63...bf5b6d594cf550a3ca31104de543e7e09ac7ea30

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c4fa5e312cec9835217b14610ebbd198faa98c63...bf5b6d594cf550a3ca31104de543e7e09ac7ea30
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list