[vlc-commits] [Git][videolan/vlc][master] 9 commits: vector: add vlc_vector_push_hole()

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat Sep 2 09:50:38 UTC 2023



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
c44abd81 by Thomas Guillem at 2023-09-02T09:33:26+00:00
vector: add vlc_vector_push_hole()

- - - - -
c2cebc3d by Thomas Guillem at 2023-09-02T09:33:26+00:00
input_item: change es_format_t list handling

Use an intermediate struct that will hold a future paramater.
Use a vlc_vector instead of the ARRAY API.

- - - - -
6eea00cc by Thomas Guillem at 2023-09-02T09:33:26+00:00
input_item_t: compare es with the string identifier

Fixes #28358

- - - - -
9b1365da by Thomas Guillem at 2023-09-02T09:33:26+00:00
test: libvlc/media: add test_media_tracks()

Will fail without the previous commit.

- - - - -
fd994f2f by Thomas Guillem at 2023-09-02T09:33:26+00:00
lib/media_track: psz_id is now always valid

Even when using a preparser.

- - - - -
505c403e by Thomas Guillem at 2023-09-02T09:33:26+00:00
test: libvlc/media: test tracks str_id

- - - - -
fcf01127 by Thomas Guillem at 2023-09-02T09:33:26+00:00
input_item_t: save if the id is stable

- - - - -
b3b514e6 by Thomas Guillem at 2023-09-02T09:33:26+00:00
lib/media_track: set id_stable from an input_item_t

- - - - -
d314736c by Thomas Guillem at 2023-09-02T09:33:26+00:00
test: libvlc/media: test tracks id_stable

- - - - -


13 changed files:

- include/vlc/libvlc_media_track.h
- include/vlc_input_item.h
- include/vlc_vector.h
- lib/media.c
- lib/media_internal.h
- lib/media_track.c
- modules/gui/ncurses.c
- modules/misc/medialibrary/MetadataExtractor.cpp
- src/input/es_out.c
- src/input/item.c
- src/input/item.h
- src/test/vector.c
- test/libvlc/media.c


Changes:

=====================================
include/vlc/libvlc_media_track.h
=====================================
@@ -111,12 +111,10 @@ typedef struct libvlc_media_track_t
     char *psz_description;
 
     /** String identifier of track, can be used to save the track preference
-     * from an other LibVLC run, only valid when the track is fetch from a
-     * media_player */
+     * from an other LibVLC run */
     const char *psz_id;
     /** A string identifier is stable when it is certified to be the same
-     * across different playback instances for the same track, only valid when
-     * the track is fetch from a media_player */
+     * across different playback instances for the same track. */
     bool id_stable;
     /** Name of the track, only valid when the track is fetch from a
      * media_player */


=====================================
include/vlc_input_item.h
=====================================
@@ -33,7 +33,9 @@
 #include <vlc_epg.h>
 #include <vlc_events.h>
 #include <vlc_list.h>
+#include <vlc_vector.h>
 #include <vlc_threads.h>
+#include <vlc_es.h>
 
 #include <string.h>
 
@@ -81,6 +83,14 @@ enum input_item_type_e
     ITEM_TYPE_NUMBER
 };
 
+struct input_item_es
+{
+    es_format_t es;
+    char *id;
+    bool id_stable;
+};
+typedef struct VLC_VECTOR(struct input_item_es) input_item_es_vector;
+
 /**
  * Describes an input and is used to spawn input_thread_t objects.
  */
@@ -100,8 +110,7 @@ struct input_item_t
 
     struct vlc_list categories;      /**< List of categories */
 
-    int         i_es;                /**< Number of es format descriptions */
-    es_format_t **es;                /**< Es formats */
+    input_item_es_vector es_vec;     /**< ES formats */
 
     input_stats_t *p_stats;          /**< Statistics */
 


=====================================
include/vlc_vector.h
=====================================
@@ -319,6 +319,26 @@ vlc_vector_growsize_(size_t value)
     ) \
 )
 
+/**
+ * Push a hole at the end of the vector.
+ *
+ * The amortized complexity is O(1). The items in the hole are left
+ * uninitialized and can be accessed in the range [size-count; size-1].
+ *
+ * \param pv a pointer to the vector
+ * \param count the number of items in the hole
+ * \retval true if no allocation failed
+ * \retval false on allocation failure (the vector is left untouched)
+ */
+#define vlc_vector_push_hole(pv, count) \
+( \
+    vlc_vector_reserve(pv, (pv)->size + vlc_vector_enforce_size_t_(count)) && \
+    ( \
+        (pv)->size += vlc_vector_enforce_size_t_(count), \
+        true \
+    ) \
+)
+
 /**
  * Append `count` items at the end of the vector.
  *


=====================================
lib/media.c
=====================================
@@ -950,8 +950,7 @@ libvlc_media_get_tracklist( libvlc_media_t *p_md, libvlc_track_type_t type )
 
     vlc_mutex_lock( &p_input_item->lock );
     libvlc_media_tracklist_t *list =
-        libvlc_media_tracklist_from_es_array( p_input_item->es,
-                                              p_input_item->i_es, type );
+        libvlc_media_tracklist_from_item( p_input_item, type );
     vlc_mutex_unlock( &p_input_item->lock );
 
     return list;


=====================================
lib/media_internal.h
=====================================
@@ -83,6 +83,7 @@ typedef struct libvlc_media_trackpriv_t
         libvlc_subtitle_track_t subtitle;
     };
     vlc_es_id_t *es_id;
+    char *item_str_id;
     vlc_atomic_rc_t rc;
 } libvlc_media_trackpriv_t;
 
@@ -100,9 +101,7 @@ libvlc_media_track_t *
 libvlc_media_track_create_from_player_track( const struct vlc_player_track *track );
 
 libvlc_media_tracklist_t *
-libvlc_media_tracklist_from_es_array( es_format_t **es_array,
-                                      size_t es_count,
-                                      libvlc_track_type_t type );
+libvlc_media_tracklist_from_item( input_item_t *item, libvlc_track_type_t type );
 
 libvlc_media_tracklist_t *
 libvlc_media_tracklist_from_player( vlc_player_t *player,


=====================================
lib/media_track.c
=====================================
@@ -119,6 +119,7 @@ libvlc_media_trackpriv_new( void )
         return NULL;
 
     trackpriv->es_id = NULL;
+    trackpriv->item_str_id = NULL;
     vlc_atomic_rc_init( &trackpriv->rc );
     return trackpriv;
 }
@@ -163,6 +164,7 @@ libvlc_media_track_release( libvlc_media_track_t *track )
         libvlc_media_track_clean( track );
         if( trackpriv->es_id )
             vlc_es_id_Release( trackpriv->es_id );
+        free( trackpriv->item_str_id );
         free( trackpriv );
     }
 }
@@ -185,16 +187,15 @@ libvlc_media_tracklist_alloc( size_t count )
 }
 
 libvlc_media_tracklist_t *
-libvlc_media_tracklist_from_es_array( es_format_t **es_array,
-                                      size_t es_count,
-                                      libvlc_track_type_t type )
+libvlc_media_tracklist_from_item( input_item_t *item, libvlc_track_type_t type )
 {
     size_t count = 0;
     const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
 
-    for( size_t i = 0; i < es_count; ++i )
+    for( size_t i = 0; i < item->es_vec.size; ++i )
     {
-        if( es_array[i]->i_cat == cat )
+        const es_format_t *es_fmt = &item->es_vec.data[i].es;
+        if( es_fmt->i_cat == cat )
             count++;
     }
 
@@ -203,9 +204,11 @@ libvlc_media_tracklist_from_es_array( es_format_t **es_array,
     if( count == 0 || list == NULL )
         return list;
 
-    for( size_t i = 0; i < es_count; ++i )
+    for( size_t i = 0; i < item->es_vec.size; ++i )
     {
-        if( es_array[i]->i_cat == cat )
+        const struct input_item_es *item_es = &item->es_vec.data[i];
+        const es_format_t *es_fmt = &item_es->es;
+        if( es_fmt->i_cat == cat )
         {
             libvlc_media_trackpriv_t *trackpriv = libvlc_media_trackpriv_new();
             if( trackpriv == NULL )
@@ -214,7 +217,16 @@ libvlc_media_tracklist_from_es_array( es_format_t **es_array,
                 return NULL;
             }
             list->tracks[list->count++] = trackpriv;
-            libvlc_media_trackpriv_from_es( trackpriv, es_array[i] );
+            libvlc_media_trackpriv_from_es( trackpriv, es_fmt );
+
+            trackpriv->item_str_id = strdup( item_es->id );
+            if( trackpriv->item_str_id == NULL )
+            {
+                libvlc_media_tracklist_delete( list );
+                return NULL;
+            }
+            trackpriv->t.psz_id = trackpriv->item_str_id;
+            trackpriv->t.id_stable = item_es->id_stable;
         }
     }
 


=====================================
modules/gui/ncurses.c
=====================================
@@ -688,9 +688,9 @@ static int DrawStats(intf_thread_t *intf)
     vlc_mutex_lock(&item->lock);
     p_stats = item->p_stats;
 
-    for (int i = 0; i < item->i_es ; i++) {
-        i_audio += (item->es[i]->i_cat == AUDIO_ES);
-        i_video += (item->es[i]->i_cat == VIDEO_ES);
+    for (int i = 0; i < item->es_vec.size ; i++) {
+        i_audio += (item->es_vec.data[i].es.i_cat == AUDIO_ES);
+        i_video += (item->es_vec.data[i].es.i_cat == VIDEO_ES);
     }
 
     /* Input */


=====================================
modules/misc/medialibrary/MetadataExtractor.cpp
=====================================
@@ -136,10 +136,10 @@ void MetadataExtractor::populateItem( medialibrary::parser::IItem& item, input_i
 
     item.setDuration( MS_FROM_VLC_TICK(inputItem->i_duration) );
 
-    for ( auto i = 0; i < inputItem->i_es; ++i )
+    for ( auto i = 0; i < inputItem->es_vec.size; ++i )
     {
         medialibrary::parser::IItem::Track t;
-        const es_format_t *p_es = inputItem->es[i];
+        const es_format_t *p_es = &inputItem->es_vec.data[i].es;
 
         switch ( p_es->i_cat )
         {


=====================================
src/input/es_out.c
=====================================
@@ -4251,7 +4251,8 @@ static int EsOutEsUpdateFmt(es_out_t *out, es_out_id_t *es,
     if (ret == VLC_SUCCESS)
     {
         EsOutUpdateEsLanguageTitle(es, &es->fmt_out);
-        input_item_UpdateTracksInfo(input_GetItem(p_input), &es->fmt_out);
+        input_item_UpdateTracksInfo(input_GetItem(p_input), &es->fmt_out,
+                                    es->id.str_id, es->id.stable);
     }
 
     return ret;
@@ -4281,7 +4282,7 @@ static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const vlc_meta_t *p
     const es_format_t *p_fmt_es = &es->fmt;
     const es_format_t *fmt = es->fmt_out.i_cat != UNKNOWN_ES ? &es->fmt_out : &es->fmt;
 
-    input_item_UpdateTracksInfo( p_item , fmt );
+    input_item_UpdateTracksInfo( p_item , fmt, es->id.str_id, es->id.stable );
 
     /* Create category */
     char* psz_cat = EsInfoCategoryName( es );


=====================================
src/input/item.c
=====================================
@@ -500,12 +500,13 @@ void input_item_Release( input_item_t *p_item )
     TAB_CLEAN( p_item->i_options, p_item->ppsz_options );
     free( p_item->optflagv );
 
-    for( int i = 0; i < p_item->i_es; i++ )
+    for( size_t i = 0; i < p_item->es_vec.size; ++i )
     {
-        es_format_Clean( p_item->es[i] );
-        free( p_item->es[i] );
+        struct input_item_es *item_es = &p_item->es_vec.data[i];
+        es_format_Clean( &item_es->es );
+        free( item_es->id );
     }
-    TAB_CLEAN( p_item->i_es, p_item->es );
+    vlc_vector_destroy( &p_item->es_vec );
 
     for( int i = 0; i < p_item->i_epg; i++ )
         vlc_epg_Delete( p_item->pp_epg[i] );
@@ -1100,7 +1101,7 @@ input_item_NewExt( const char *psz_uri, const char *psz_name,
 
     p_input->i_duration = duration;
     vlc_list_init( &p_input->categories );
-    TAB_INIT( p_input->i_es, p_input->es );
+    vlc_vector_init( &p_input->es_vec );
     p_input->p_stats = NULL;
     TAB_INIT( p_input->i_epg, p_input->pp_epg );
     TAB_INIT( p_input->i_slaves, p_input->pp_slaves );
@@ -1320,32 +1321,43 @@ void input_item_node_RemoveNode( input_item_node_t *parent,
 }
 
 /* Called by es_out when a new Elementary Stream is added or updated. */
-void input_item_UpdateTracksInfo(input_item_t *item, const es_format_t *fmt)
+void input_item_UpdateTracksInfo(input_item_t *item, const es_format_t *fmt,
+                                 const char *es_id, bool es_id_stable)
 {
-    int i;
-    es_format_t *fmt_copy = malloc(sizeof *fmt_copy);
-    if (!fmt_copy)
-        return;
-
-    es_format_Copy(fmt_copy, fmt);
-
+    assert( es_id != NULL );
     vlc_mutex_lock( &item->lock );
 
-    for( i = 0; i < item->i_es; i++ )
+    for( size_t i = 0; i < item->es_vec.size; ++i )
     {
-        if (item->es[i]->i_id != fmt->i_id)
+        struct input_item_es *item_es = &item->es_vec.data[i];
+        if (strcmp(item_es->id, es_id) != 0)
             continue;
 
         /* We've found the right ES, replace it */
-        es_format_Clean(item->es[i]);
-        free(item->es[i]);
-        item->es[i] = fmt_copy;
+        es_format_Clean(&item_es->es);
+        es_format_Copy(&item_es->es, fmt);
+        vlc_mutex_unlock( &item->lock );
+        return;
+    }
+
+    char *es_id_dup = strdup( es_id );
+    if( es_id_dup == NULL )
+    {
         vlc_mutex_unlock( &item->lock );
         return;
     }
 
     /* ES not found, insert it */
-    TAB_APPEND(item->i_es, item->es, fmt_copy);
+    if (vlc_vector_push_hole( &item->es_vec, 1 ))
+    {
+        struct input_item_es *item_es = &item->es_vec.data[item->es_vec.size - 1];
+        item_es->id = es_id_dup;
+        item_es->id_stable = es_id_stable;
+        es_format_Copy( &item_es->es, fmt );
+    }
+    else
+        free( es_id_dup );
+
     vlc_mutex_unlock( &item->lock );
 }
 


=====================================
src/input/item.h
=====================================
@@ -27,7 +27,8 @@
 #include <vlc_atomic.h>
 
 void input_item_SetErrorWhenReading( input_item_t *p_i, bool b_error );
-void input_item_UpdateTracksInfo( input_item_t *item, const es_format_t *fmt );
+void input_item_UpdateTracksInfo( input_item_t *item, const es_format_t *fmt,
+                                  const char *es_id, bool stable );
 bool input_item_ShouldPreparseSubItems( input_item_t *p_i );
 
 typedef struct input_item_owner


=====================================
src/test/vector.c
=====================================
@@ -87,9 +87,15 @@ static void test_vector_push_array(void)
 
     int items[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
     ok = vlc_vector_push_all(&vec, items, 8);
+    assert(ok);
 
+    int items_hole[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
+    ok = vlc_vector_push_hole(&vec, 8);
     assert(ok);
-    assert(vec.size == 13);
+    for (size_t i = 0; i < 8; ++i)
+        vec.data[vec.size-8+i] = items_hole[i];
+
+    assert(vec.size == 21);
     assert(vec.data[0] == 3);
     assert(vec.data[1] == 14);
     assert(vec.data[2] == 15);
@@ -103,6 +109,14 @@ static void test_vector_push_array(void)
     assert(vec.data[10] == 6);
     assert(vec.data[11] == 7);
     assert(vec.data[12] == 8);
+    assert(vec.data[13] == 7);
+    assert(vec.data[14] == 6);
+    assert(vec.data[15] == 5);
+    assert(vec.data[16] == 4);
+    assert(vec.data[17] == 3);
+    assert(vec.data[18] == 2);
+    assert(vec.data[19] == 1);
+    assert(vec.data[20] == 0);
 
     vlc_vector_destroy(&vec);
 }


=====================================
test/libvlc/media.c
=====================================
@@ -103,10 +103,11 @@ static void print_media(libvlc_media_t *media)
     }
 }
 
-static void test_media_preparsed(libvlc_instance_t *vlc, const char *path,
-                                 const char *location,
-                                 libvlc_media_parse_flag_t parse_flags,
-                                 libvlc_media_parsed_status_t i_expected_status)
+static libvlc_media_t *
+test_media_preparsed_ext(libvlc_instance_t *vlc, const char *path,
+                         const char *location,
+                         libvlc_media_parse_flag_t parse_flags,
+                         libvlc_media_parsed_status_t i_expected_status)
 {
     test_log ("test_media_preparsed: %s, expected: %d\n", path ? path : location,
               i_expected_status);
@@ -137,6 +138,74 @@ static void test_media_preparsed(libvlc_instance_t *vlc, const char *path,
     if (i_expected_status == libvlc_media_parsed_status_done)
         print_media(media);
 
+    return media;
+}
+
+static void test_media_preparsed(libvlc_instance_t *vlc, const char *path,
+                                 const char *location,
+                                 libvlc_media_parse_flag_t parse_flags,
+                                 libvlc_media_parsed_status_t i_expected_status)
+{
+    libvlc_media_t *media = test_media_preparsed_ext(vlc, path, location,
+                                                     parse_flags,
+                                                     i_expected_status);
+    libvlc_media_release (media);
+}
+
+static void test_media_tracks(libvlc_instance_t *vlc)
+{
+    const char *url =
+        "mock://video_track_count=4;audio_track_count=42;"
+        "video_width=100;video_height=50;"
+        "audio_channels=2;audio_rate=48000;";
+    libvlc_media_t *media =
+        test_media_preparsed_ext(vlc, NULL, url,
+                                 libvlc_media_parse_local|libvlc_media_parse_forced,
+                                 libvlc_media_parsed_status_done);
+
+    libvlc_media_tracklist_t *tracklist;
+
+    tracklist = libvlc_media_get_tracklist(media, libvlc_track_video);
+    assert(tracklist != NULL);
+    assert(libvlc_media_tracklist_count(tracklist) == 4);
+    for (size_t i = 0; i < libvlc_media_tracklist_count(tracklist); ++i)
+    {
+        libvlc_media_track_t *track = libvlc_media_tracklist_at(tracklist, i);
+        assert(track->i_type == libvlc_track_video);
+        assert(track->video != NULL);
+        assert(track->video->i_width == 100);
+        assert(track->video->i_height == 50);
+
+        char buf[] = "video/4";
+        sprintf(buf, "video/%zu", i);
+        assert(strcmp(track->psz_id, buf) == 0);
+        assert(track->id_stable);
+    }
+    libvlc_media_tracklist_delete(tracklist);
+
+    tracklist = libvlc_media_get_tracklist(media, libvlc_track_audio);
+    assert(tracklist != NULL);
+    assert(libvlc_media_tracklist_count(tracklist) == 42);
+    for (size_t i = 0; i < libvlc_media_tracklist_count(tracklist); ++i)
+    {
+        libvlc_media_track_t *track = libvlc_media_tracklist_at(tracklist, i);
+        assert(track->i_type == libvlc_track_audio);
+        assert(track->audio != NULL);
+        assert(track->audio->i_channels == 2);
+        assert(track->audio->i_rate == 48000);
+
+        char buf[] = "audio/42";
+        sprintf(buf, "audio/%zu", i);
+        assert(strcmp(track->psz_id, buf) == 0);
+        assert(track->id_stable);
+    }
+    libvlc_media_tracklist_delete(tracklist);
+
+    tracklist = libvlc_media_get_tracklist(media, libvlc_track_text);
+    assert(tracklist != NULL);
+    assert(libvlc_media_tracklist_count(tracklist) == 0);
+    libvlc_media_tracklist_delete(tracklist);
+
     libvlc_media_release (media);
 }
 
@@ -394,6 +463,7 @@ int main(int i_argc, char *ppsz_argv[])
                           libvlc_media_parse_local,
                           libvlc_media_parsed_status_skipped);
     test_media_subitems (vlc);
+    test_media_tracks (vlc);
 
     /* Testing libvlc_MetadataRequest timeout and libvlc_MetadataCancel. For
      * that, we need to create a local input_item_t based on a pipe. There is



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0ba30f46f588d4a32d588324bf85f155419445c4...d314736cef648841deee50ba310e1c659c85e329

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0ba30f46f588d4a32d588324bf85f155419445c4...d314736cef648841deee50ba310e1c659c85e329
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