[vlc-commits] [Git][videolan/vlc][master] 11 commits: preparser: set the preparsed state only if actually done

Thomas Guillem (@tguillem) gitlab at videolan.org
Fri Dec 22 16:20:43 UTC 2023



Thomas Guillem pushed to branch master at VideoLAN / VLC


Commits:
d275d1e7 by Thomas Guillem at 2023-12-22T15:55:41+00:00
preparser: set the preparsed state only if actually done

This fixes item with 0 meta, if the preparser failed (or was skipped).

This let a second chance for the player to fetch meta and attachments.

This was happening with every mock media that are skipped by the
preparser.

- - - - -
77390aac by Thomas Guillem at 2023-12-22T15:55:41+00:00
input: add INPUT_EVENT_ATTACHMENTS

Send attachments via the input_thread_t.
The possibility to send attachments via the input_item_t will be removed
soon.

- - - - -
f53180cf by Thomas Guillem at 2023-12-22T15:55:41+00:00
input: add on_attachments_added event to the parser

- - - - -
8499dd99 by Thomas Guillem at 2023-12-22T15:55:41+00:00
preparser: add on_attachments_added

- - - - -
32a94365 by Thomas Guillem at 2023-12-22T15:55:41+00:00
medialibrary: use on_attachments_added

- - - - -
dd7cdf2d by Thomas Guillem at 2023-12-22T15:55:41+00:00
lib: picture: add const

- - - - -
23a5842c by Thomas Guillem at 2023-12-22T15:55:41+00:00
lib: media: use on_attachments_added

- - - - -
a6f45882 by Thomas Guillem at 2023-12-22T15:55:41+00:00
player: add on_media_attachments_added event

- - - - -
48ed9b94 by Thomas Guillem at 2023-12-22T15:55:41+00:00
mock: add attachments support

- - - - -
182c1b63 by Thomas Guillem at 2023-12-22T15:55:41+00:00
mock: add some meta

- - - - -
08e5bcf3 by Thomas Guillem at 2023-12-22T15:55:41+00:00
test: player: test on_media_attachments_added

- - - - -


17 changed files:

- include/vlc_input_item.h
- include/vlc_player.h
- lib/media.c
- lib/picture.c
- lib/picture_internal.h
- modules/demux/mock.c
- modules/gui/qt/dialogs/dialogs_provider.cpp
- modules/gui/qt/player/player_controller.cpp
- modules/misc/medialibrary/MetadataExtractor.cpp
- modules/misc/medialibrary/fs/directory.cpp
- modules/misc/medialibrary/medialibrary.h
- src/input/input.c
- src/input/input_internal.h
- src/input/item.c
- src/player/input.c
- src/preparser/preparser.c
- test/src/player/player.c


Changes:

=====================================
include/vlc_input_item.h
=====================================
@@ -444,6 +444,23 @@ typedef struct input_item_parser_cbs_t
      * @param userdata user data set by input_item_Parse()
      */
     void (*on_subtree_added)(input_item_t *item, input_item_node_t *subtree, void *userdata);
+
+    /**
+     * Event received when new attachments are added
+     *
+     * @note This callback is optional. It can be called several times for one
+     * parse request. The array contains only new elements after a second call.
+     *
+     * @param item the parsed item
+     * @param array valid array containing new elements, should only be used
+     * within the callback. One and all elements can be held and stored on a
+     * new variable or new array.
+     * @param count number of elements in the array
+     * @param userdata user data set by input_item_Parse()
+     */
+    void (*on_attachments_added)(input_item_t *item,
+                                 input_attachment_t *const *array,
+                                 size_t count, void *userdata);
 } input_item_parser_cbs_t;
 
 /**
@@ -513,6 +530,9 @@ struct vlc_metadata_cbs {
     void (*on_preparse_ended)(input_item_t *, enum input_item_preparse_status status, void *userdata);
     void (*on_art_fetch_ended)(input_item_t *, bool fetched, void *userdata);
     void (*on_subtree_added)(input_item_t *, input_item_node_t *subtree, void *userdata);
+    void (*on_attachments_added)(input_item_t *item,
+                                 input_attachment_t *const *array,
+                                 size_t count, void *userdata);
 };
 
 VLC_API int libvlc_MetadataRequest( libvlc_int_t *, input_item_t *,


=====================================
include/vlc_player.h
=====================================
@@ -3186,6 +3186,24 @@ struct vlc_player_cbs
     void (*on_media_subitems_changed)(vlc_player_t *player,
         input_item_t *media, input_item_node_t *new_subitems, void *data);
 
+    /**
+     * Called when new attachments are added to the media
+     *
+     * @note It can be called several times for one parse request. The array
+     * contains only new elements after a second call.
+     *
+     * @param player locked player instance
+     * @param media current media
+     * @param array valid array containing new elements, should only be used
+     * within the callback. One and all elements can be held and stored on a
+     * new variable or new array.
+     * @param count number of elements in the array
+     * @param data opaque pointer set by vlc_player_AddListener()
+     */
+    void (*on_media_attachments_added)(vlc_player_t *player,
+        input_item_t *media, input_attachment_t *const *array, size_t count,
+        void *data);
+
     /**
      * Called when a vout is started or stopped
      *


=====================================
lib/media.c
=====================================
@@ -310,15 +310,16 @@ static void input_item_duration_changed( const vlc_event_t *p_event,
     libvlc_event_send( &p_md->event_manager, &event );
 }
 
-static void input_item_attachments_found( const vlc_event_t *p_event,
-                                                 void * user_data )
+static void input_item_attachments_added( input_item_t *item,
+                                          input_attachment_t *const *array,
+                                          size_t count, void *user_data )
 {
+    VLC_UNUSED(item);
     libvlc_media_t * p_md = user_data;
     libvlc_event_t event;
 
-    libvlc_picture_list_t* list = libvlc_picture_list_from_attachments(
-                p_event->u.input_item_attachments_found.attachments,
-                p_event->u.input_item_attachments_found.count );
+    libvlc_picture_list_t* list =
+        libvlc_picture_list_from_attachments(array, count);
     if( !list )
         return;
     if( !libvlc_picture_list_count(list) )
@@ -409,10 +410,6 @@ static void install_input_item_observer( libvlc_media_t *p_md )
                       vlc_InputItemDurationChanged,
                       input_item_duration_changed,
                       p_md );
-    vlc_event_attach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemAttachmentsFound,
-                      input_item_attachments_found,
-                      p_md );
 }
 
 /**
@@ -429,10 +426,6 @@ static void uninstall_input_item_observer( libvlc_media_t *p_md )
                       vlc_InputItemDurationChanged,
                       input_item_duration_changed,
                       p_md );
-    vlc_event_detach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemAttachmentsFound,
-                      input_item_attachments_found,
-                      p_md );
 }
 
 /**
@@ -826,6 +819,7 @@ libvlc_media_get_filestat( libvlc_media_t *p_md, unsigned type, uint64_t *out )
 static const struct vlc_metadata_cbs preparser_callbacks = {
     .on_preparse_ended = input_item_preparse_ended,
     .on_subtree_added = input_item_subtree_added,
+    .on_attachments_added = input_item_attachments_added,
 };
 
 int libvlc_media_parse_request(libvlc_instance_t *inst, libvlc_media_t *media,


=====================================
lib/picture.c
=====================================
@@ -208,7 +208,7 @@ libvlc_time_t libvlc_picture_get_time( const libvlc_picture_t* pic )
     return pic->time;
 }
 
-libvlc_picture_list_t* libvlc_picture_list_from_attachments( input_attachment_t** attachments,
+libvlc_picture_list_t* libvlc_picture_list_from_attachments( input_attachment_t* const* attachments,
                                                              size_t nb_attachments )
 {
     size_t size = 0;


=====================================
lib/picture_internal.h
=====================================
@@ -44,7 +44,7 @@ libvlc_picture_t* libvlc_picture_new( vlc_object_t* p_obj, picture_t* p_pic,
                                       unsigned int i_width, unsigned int i_height,
                                       bool b_crop );
 
-libvlc_picture_list_t* libvlc_picture_list_from_attachments( input_attachment_t** attachments,
+libvlc_picture_list_t* libvlc_picture_list_from_attachments( input_attachment_t* const* attachments,
                                                              size_t nb_attachments );
 
 #endif /* PICTURE_INTERNAL_H */


=====================================
modules/demux/mock.c
=====================================
@@ -223,6 +223,7 @@ var_Read_float(const char *psz)
     X(chapter_count, ssize_t, add_integer, Ssize, 0) \
     X(null_names, bool, add_bool, Bool, false) \
     X(program_count, ssize_t, add_integer, Ssize, 0) \
+    X(attachment_count, ssize_t, add_integer, Ssize, 0) \
     X(can_seek, bool, add_bool, Bool, true) \
     X(can_pause, bool, add_bool, Bool, true) \
     X(can_control_pace, bool, add_bool, Bool, true) \
@@ -310,6 +311,8 @@ struct demux_sys
     struct mock_video_options video;
     struct mock_audio_options audio;
     struct mock_sub_options sub;
+
+    char *art_url;
 };
 #undef X
 
@@ -359,6 +362,100 @@ CreateTitle(demux_t *demux, size_t idx)
     return t;
 }
 
+static input_attachment_t *
+CreateAttachment(demux_t *demux, const char *prefix_name, size_t index)
+{
+    input_attachment_t *attach = NULL;
+    picture_t *pic = NULL;
+    block_t *block = NULL;
+
+    char *name;
+    int ret = asprintf(&name, "%s %zu", prefix_name, index);
+    if (ret < 0)
+        return NULL;
+
+    pic = picture_New(VLC_CODEC_RGB24, 100, 100, 1, 1);
+    if (pic == NULL)
+        goto end;
+
+    memset(pic->p[0].p_pixels, 0x80, pic->p[0].i_lines * pic->p[0].i_pitch);
+
+    ret = picture_Export(VLC_OBJECT(demux), &block, NULL, pic, VLC_CODEC_BMP,
+                         0, 0, false);
+    if (ret != VLC_SUCCESS)
+        goto end;
+
+    attach = vlc_input_attachment_New(name, "image/bmp", "Mock Attach Desc",
+                                      block->p_buffer, block->i_buffer);
+
+end:
+    if (block != NULL)
+        block_Release(block);
+    if (pic != NULL)
+        picture_Release(pic);
+    free(name);
+    return attach;
+}
+
+static int
+GetAttachments(demux_t *demux, input_attachment_t ***attach_array_p,
+               int *attach_count_p)
+{
+    struct demux_sys *sys = demux->p_sys;
+    assert(sys->attachment_count > 0);
+    size_t attachment_count = sys->attachment_count;
+
+    input_attachment_t **attach_array =
+        vlc_alloc(sys->attachment_count, sizeof(*attach_array));
+    if (attach_array == NULL)
+        return VLC_ENOMEM;
+
+    for (size_t i = 0; i < attachment_count; i++)
+    {
+        attach_array[i] = CreateAttachment(demux, "Mock Attach", i);
+
+        if (attach_array[i] == NULL)
+        {
+            if (i == 0)
+            {
+                free(attach_array);
+                return VLC_ENOMEM;
+            }
+            *attach_array_p = attach_array;
+            *attach_count_p = i;
+            return VLC_SUCCESS;
+        }
+
+        if (sys->art_url == NULL
+         && asprintf(&sys->art_url, "attachment://%s",
+                     attach_array[i]->psz_name) == -1)
+            sys->art_url = NULL;
+    }
+
+    *attach_array_p = attach_array;
+    *attach_count_p = sys->attachment_count;
+
+    return VLC_SUCCESS;
+}
+
+static vlc_meta_t *
+CreateMeta(demux_t *demux)
+{
+    struct demux_sys *sys = demux->p_sys;
+
+    vlc_meta_t *meta = vlc_meta_New();
+    if (meta == NULL)
+        return NULL;
+
+    vlc_meta_SetArtist(meta, "VideoLAN");
+    vlc_meta_SetGenre(meta, "Best Media Player");
+
+    if (sys->art_url != NULL)
+        vlc_meta_SetArtURL(meta, sys->art_url);
+
+    return meta;
+}
+
 static int
 Control(demux_t *demux, int query, va_list args)
 {
@@ -379,7 +476,15 @@ Control(demux_t *demux, int query, va_list args)
             *va_arg(args, vlc_tick_t *) = sys->pts_delay;
             return VLC_SUCCESS;
         case DEMUX_GET_META:
-            return VLC_EGENERIC;
+        {
+            vlc_meta_t *meta_out = va_arg(args, vlc_meta_t *);
+            vlc_meta_t *meta = CreateMeta(demux);
+            if (meta == NULL)
+                return VLC_ENOMEM;
+            vlc_meta_Merge(meta_out, meta);
+            vlc_meta_Delete(meta);
+            return VLC_SUCCESS;
+        }
         case DEMUX_GET_SIGNAL:
             return VLC_EGENERIC;
         case DEMUX_SET_PAUSE_STATE:
@@ -492,7 +597,14 @@ Control(demux_t *demux, int query, va_list args)
         case DEMUX_HAS_UNSUPPORTED_META:
             return VLC_EGENERIC;
         case DEMUX_GET_ATTACHMENTS:
-            return VLC_EGENERIC;
+        {
+            input_attachment_t ***attach_array_p = va_arg(args, input_attachment_t***);
+            int *attach_count_p = va_arg(args, int *);
+            if (sys->attachment_count <= 0)
+                return VLC_EGENERIC;
+
+            return GetAttachments(demux, attach_array_p, attach_count_p);
+        }
         case DEMUX_CAN_RECORD:
             *va_arg(args, bool *) = sys->can_record;
             return VLC_SUCCESS;
@@ -1313,6 +1425,8 @@ Close(vlc_object_t *obj)
         DeleteTrack(demux, track);
     }
     vlc_vector_clear(&sys->tracks);
+
+    free(sys->art_url);
 }
 
 static int
@@ -1337,6 +1451,7 @@ Open(vlc_object_t *obj)
     OPTIONS_AUDIO(READ_SUBOPTION)
     OPTIONS_VIDEO(READ_SUBOPTION)
     OPTIONS_SUB(READ_SUBOPTION)
+    sys->art_url = NULL;
 
     if (sys->node_count > 0)
     {


=====================================
modules/gui/qt/dialogs/dialogs_provider.cpp
=====================================
@@ -403,7 +403,9 @@ void DialogsProvider::mediaInfoDialog( const MLItemId& itemId )
                     }, Qt::QueuedConnection );
             },
             // on_subtree_added
-            NULL
+            NULL,
+            // on_attachments_added
+            NULL,
         };
 
         input_item_parser_id_t * const parser = input_item_Parse( inputItem, VLC_OBJECT( p_intf ), &cbs, this );


=====================================
modules/gui/qt/player/player_controller.cpp
=====================================
@@ -1024,6 +1024,7 @@ static const struct vlc_player_cbs player_cbs = {
     on_player_media_meta_changed,
     on_player_media_epg_changed,
     on_player_subitems_changed,
+    nullptr, // on_media_attachments_added: not used
     on_player_vout_changed,
     on_player_corks_changed,
     on_player_playback_restore_queried,


=====================================
modules/misc/medialibrary/MetadataExtractor.cpp
=====================================
@@ -187,12 +187,14 @@ void MetadataExtractor::onParserSubtreeAdded( input_item_t *,
     ctx->mde->addSubtree( *ctx, subtree );
 }
 
-void MetadataExtractor::onAttachmentFound( const vlc_event_t* p_event, void* data )
+void MetadataExtractor::onAttachmentsAdded( input_item_t *,
+                                            input_attachment_t *const *array,
+                                            size_t count, void *data )
 {
     auto ctx = static_cast<ParseContext*>( data );
-    for ( auto i = 0u; i < p_event->u.input_item_attachments_found.count; ++i )
+    for ( auto i = 0u; i < count; ++i )
     {
-        auto a = p_event->u.input_item_attachments_found.attachments[i];
+        auto a = array[i];
         auto fcc = image_Mime2Fourcc( a->psz_mime );
         if ( fcc != VLC_CODEC_PNG && fcc != VLC_CODEC_JPEG )
             continue;
@@ -222,13 +224,10 @@ medialibrary::parser::Status MetadataExtractor::run( medialibrary::parser::IItem
     if ( ctx.inputItem == nullptr )
         return medialibrary::parser::Status::Fatal;
 
-    if ( vlc_event_attach( &ctx.inputItem->event_manager, vlc_InputItemAttachmentsFound,
-                      &MetadataExtractor::onAttachmentFound, &ctx ) != VLC_SUCCESS )
-        return medialibrary::parser::Status::Fatal;
-
     const input_item_parser_cbs_t cbs = {
         &MetadataExtractor::onParserEnded,
         &MetadataExtractor::onParserSubtreeAdded,
+        &MetadataExtractor::onAttachmentsAdded,
     };
     m_currentCtx = &ctx;
     ctx.inputItem->i_preparse_depth = 1;
@@ -239,8 +238,6 @@ medialibrary::parser::Status MetadataExtractor::run( medialibrary::parser::IItem
     };
     if ( ctx.inputParser == nullptr )
     {
-        vlc_event_detach( &ctx.inputItem->event_manager, vlc_InputItemAttachmentsFound,
-                          &MetadataExtractor::onAttachmentFound, &ctx );
         m_currentCtx = nullptr;
         return medialibrary::parser::Status::Fatal;
     }
@@ -260,8 +257,6 @@ medialibrary::parser::Status MetadataExtractor::run( medialibrary::parser::IItem
         }
         m_currentCtx = nullptr;
     }
-    vlc_event_detach( &ctx.inputItem->event_manager, vlc_InputItemAttachmentsFound,
-                      &MetadataExtractor::onAttachmentFound, &ctx );
 
     if ( !ctx.success || ctx.inputParser == nullptr )
         return medialibrary::parser::Status::Fatal;


=====================================
modules/misc/medialibrary/fs/directory.cpp
=====================================
@@ -167,6 +167,7 @@ static bool request_metadata_sync( libvlc_int_t *libvlc, input_item_t *media,
     static const input_item_parser_cbs_t cbs = {
         onParserEnded,
         onParserSubtreeAdded,
+        nullptr,
     };
 
     auto inputParser = vlc::wrap_cptr( input_item_Parse( media, VLC_OBJECT( libvlc ), &cbs, &req ),


=====================================
modules/misc/medialibrary/medialibrary.h
=====================================
@@ -106,7 +106,9 @@ private:
     static void onParserEnded( input_item_t *, int status, void *user_data );
     static void onParserSubtreeAdded( input_item_t *, input_item_node_t *subtree,
                                       void *user_data );
-    static void onAttachmentFound( const vlc_event_t* p_event, void* data );
+    static void onAttachmentsAdded( input_item_t *,
+                                    input_attachment_t *const *array,
+                                    size_t count, void *data );
 
 private:
     vlc::threads::condition_variable m_cond;


=====================================
src/input/input.c
=====================================
@@ -3116,6 +3116,12 @@ static void AppendAttachment( input_thread_t *p_input, int i_new,
             .type = vlc_InputItemAttachmentsFound,
             .u.input_item_attachments_found.attachments = pp_new,
             .u.input_item_attachments_found.count = i_new } );
+
+        input_SendEvent(p_input, &(struct vlc_input_event) {
+            .type = INPUT_EVENT_ATTACHMENTS,
+            .attachments = { .array = pp_new, .count = i_new },
+        });
+
         free( pp_new );
         return;
     }


=====================================
src/input/input_internal.h
=====================================
@@ -142,6 +142,9 @@ typedef enum input_event_type_e
 
     /* Thumbnail generation */
     INPUT_EVENT_THUMBNAIL_READY,
+
+    /* Attachments */
+    INPUT_EVENT_ATTACHMENTS,
 } input_event_type_e;
 
 #define VLC_INPUT_CAPABILITIES_SEEKABLE (1<<0)
@@ -256,6 +259,12 @@ struct vlc_input_event_vout
     vlc_es_id_t *id;
 };
 
+struct vlc_input_event_attachments
+{
+    input_attachment_t *const* array;
+    size_t count;
+};
+
 struct vlc_input_event
 {
     input_event_type_e type;
@@ -299,6 +308,8 @@ struct vlc_input_event
         float subs_fps;
         /* INPUT_EVENT_THUMBNAIL_READY */
         picture_t *thumbnail;
+        /* INPUT_EVENT_ATTACHMENTS */
+        struct vlc_input_event_attachments attachments;
     };
 };
 


=====================================
src/input/item.c
=====================================
@@ -1414,6 +1414,13 @@ input_item_parser_InputEvent(input_thread_t *input,
                 parser->cbs->on_subtree_added(input_GetItem(input),
                                               event->subitems, parser->userdata);
             break;
+        case INPUT_EVENT_ATTACHMENTS:
+            if (parser->cbs->on_attachments_added != NULL)
+                parser->cbs->on_attachments_added(input_GetItem(input),
+                                                  event->attachments.array,
+                                                  event->attachments.count,
+                                                  parser->userdata);
+            break;
         default:
             break;
     }


=====================================
src/player/input.c
=====================================
@@ -888,6 +888,12 @@ input_thread_Events(input_thread_t *input_thread,
             vlc_player_SendEvent(player, on_teletext_transparency_changed,
                                  input->teletext_transparent);
             break;
+        case INPUT_EVENT_ATTACHMENTS:
+            vlc_player_SendEvent(player, on_media_attachments_added,
+                                 input_GetItem(input->thread),
+                                 event->attachments.array,
+                                 event->attachments.count);
+            break;
         default:
             break;
     }


=====================================
src/preparser/preparser.c
=====================================
@@ -171,6 +171,27 @@ OnParserSubtreeAdded(input_item_t *item, input_item_node_t *subtree,
         task->cbs->on_subtree_added(task->item, subtree, task->userdata);
 }
 
+static void
+OnParserAttachmentsAdded(input_item_t *item,
+                         input_attachment_t *const *array,
+                         size_t count, void *task_)
+{
+    VLC_UNUSED(item);
+    struct task *task = task_;
+
+    if (task->cbs && task->cbs->on_attachments_added)
+        task->cbs->on_attachments_added(task->item, array, count, task->userdata);
+}
+
+static void
+SetItemPreparsed(struct task *task)
+{
+    int status = atomic_load_explicit(&task->preparse_status,
+                                      memory_order_relaxed);
+    if (status == ITEM_PREPARSE_DONE)
+        input_item_SetPreparsed(task->item);
+}
+
 static void
 OnArtFetchEnded(input_item_t *item, bool fetched, void *userdata)
 {
@@ -180,7 +201,7 @@ OnArtFetchEnded(input_item_t *item, bool fetched, void *userdata)
     struct task *task = userdata;
 
     if (!atomic_load(&task->interrupted))
-        input_item_SetPreparsed(task->item);
+        SetItemPreparsed(task);
 
     NotifyPreparseEnded(task, fetched);
     TaskDelete(task);
@@ -196,6 +217,7 @@ Parse(struct task *task, vlc_tick_t deadline)
     static const input_item_parser_cbs_t cbs = {
         .on_ended = OnParserEnded,
         .on_subtree_added = OnParserSubtreeAdded,
+        .on_attachments_added = OnParserAttachmentsAdded,
     };
 
     vlc_object_t *obj = task->preparser->owner;
@@ -268,7 +290,7 @@ RunnableRun(void *userdata)
         return; /* Remove the task and notify from the fetcher callback */
 
     if (!atomic_load(&task->interrupted))
-        input_item_SetPreparsed(task->item);
+        SetItemPreparsed(task);
 
 end:
     NotifyPreparseEnded(task, false);


=====================================
test/src/player/player.c
=====================================
@@ -118,6 +118,12 @@ struct report_media_subitems
     input_item_t **items;
 };
 
+struct report_media_attachments
+{
+    input_attachment_t **array;
+    size_t count;
+};
+
 #define REPORT_LIST \
     X(input_item_t *, on_current_media_changed) \
     X(enum vlc_player_state, on_state_changed) \
@@ -146,6 +152,7 @@ struct report_media_subitems
     X(input_item_t *, on_media_meta_changed) \
     X(input_item_t *, on_media_epg_changed) \
     X(struct report_media_subitems, on_media_subitems_changed) \
+    X(struct report_media_attachments, on_media_attachments_added) \
 
 struct report_timer
 {
@@ -204,6 +211,7 @@ struct media_params
 
     size_t title_count;
     size_t chapter_count;
+    size_t attachment_count;
 
     bool can_seek;
     bool can_pause;
@@ -227,6 +235,7 @@ struct media_params
     .video_frame_rate_base = 1, \
     .title_count = 0, \
     .chapter_count = 0, \
+    .attachment_count = 0, \
     .can_seek = true, \
     .can_pause = true, \
     .error = false, \
@@ -583,6 +592,25 @@ player_on_media_subitems_changed(vlc_player_t *player, input_item_t *media,
     VEC_PUSH(on_media_subitems_changed, report);
 }
 
+static void
+player_on_media_attachments_added(vlc_player_t *player,
+                                  input_item_t *media,
+                                  input_attachment_t *const *array, size_t count,
+                                  void *data)
+{
+    (void) media;
+    struct ctx *ctx = get_ctx(player, data);
+
+    struct report_media_attachments report = {
+        .array = vlc_alloc(count, sizeof(input_attachment_t *)),
+        .count = count,
+    };
+    assert(report.array);
+    for (size_t i = 0; i < count; ++i)
+        report.array[i] = vlc_input_attachment_Hold(array[i]);
+    VEC_PUSH(on_media_attachments_added, report);
+}
+
 #define VEC_LAST(vec) (vec)->data[(vec)->size - 1]
 #define assert_position(ctx, report) do { \
     assert(fabs((report)->pos - (report)->time / (float) ctx->params.length) < 0.001); \
@@ -713,6 +741,16 @@ ctx_reset(struct ctx *ctx)
             free(report.items);
         }
     }
+
+    {
+        struct report_media_attachments report;
+        FOREACH_VEC(report, on_media_attachments_added)
+        {
+            for (size_t i = 0; i < report.count; ++i)
+                vlc_input_attachment_Release(report.array[i]);
+            free(report.array);
+        }
+    }
 #undef CLEAN_MEDIA_VEC
 #undef FOREACH_VEC
 
@@ -755,7 +793,7 @@ create_mock_media(const char *name, const struct media_params *params)
         "video_frame_rate=%u;video_frame_rate_base=%u;"
         "title_count=%zu;chapter_count=%zu;"
         "can_seek=%d;can_pause=%d;error=%d;null_names=%d;"
-        "config=%s",
+        "config=%s;attachment_count=%zu",
         params->track_count[VIDEO_ES], params->track_count[AUDIO_ES],
         params->track_count[SPU_ES], params->program_count,
         params->video_packetized, params->audio_packetized,
@@ -763,7 +801,7 @@ create_mock_media(const char *name, const struct media_params *params)
         params->video_frame_rate, params->video_frame_rate_base,
         params->title_count, params->chapter_count,
         params->can_seek, params->can_pause, params->error, params->null_names,
-        params->config ? params->config : "");
+        params->config ? params->config : "", params->attachment_count);
     assert(ret != -1);
     input_item_t *item = input_item_New(url, name);
     assert(item);
@@ -2843,6 +2881,45 @@ test_teletext(struct ctx *ctx)
 #endif
 }
 
+static void
+test_attachments(struct ctx *ctx)
+{
+    test_log("attachments\n");
+
+    vlc_player_t *player = ctx->player;
+
+    struct media_params params = DEFAULT_MEDIA_PARAMS(VLC_TICK_FROM_SEC(1));
+    params.attachment_count = 99;
+    player_set_next_mock_media(ctx, "media1", &params);
+
+    player_start(ctx);
+
+    vec_on_media_attachments_added *vec = &ctx->report.on_media_attachments_added;
+
+    while (vec->size == 0)
+        vlc_player_CondWait(player, &ctx->wait);
+
+    input_attachment_t **array = vec->data[0].array;
+    size_t count = vec->data[0].count;
+
+    assert(count == params.attachment_count);
+
+    for (size_t i = 0; i < count; ++i)
+    {
+        input_attachment_t *attach = array[i];
+        assert(strcmp(attach->psz_mime, "image/bmp") == 0);
+        assert(strcmp(attach->psz_description, "Mock Attach Desc") == 0);
+
+        char *name;
+        int ret = asprintf(&name, "Mock Attach %zu", i);
+        assert(ret > 0);
+        assert(strcmp(attach->psz_name, name) == 0);
+        free(name);
+    }
+
+    test_end(ctx);
+}
+
 static void
 test_audio_loudness_meter_cb(vlc_tick_t date, double momentary_loudness,
                              void *data)
@@ -2994,6 +3071,7 @@ main(void)
     test_programs(&ctx);
     test_timers(&ctx);
     test_teletext(&ctx);
+    test_attachments(&ctx);
 
     test_delete_while_playback(VLC_OBJECT(ctx.vlc->p_libvlc_int), true);
     test_delete_while_playback(VLC_OBJECT(ctx.vlc->p_libvlc_int), false);



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/dbe399b593d76d722afadac8272d5939b4c20059...08e5bcf35185893ac70f95f2332c91b0242f536a

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/dbe399b593d76d722afadac8272d5939b4c20059...08e5bcf35185893ac70f95f2332c91b0242f536a
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