[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