[vlc-commits] [Git][videolan/vlc][master] 7 commits: preparser: use an unsigned for the request identification

Thomas Guillem (@tguillem) gitlab at videolan.org
Thu Oct 17 15:07:27 UTC 2024



Thomas Guillem pushed to branch master at VideoLAN / VLC


Commits:
3d4af3b7 by Thomas Guillem at 2024-10-17T14:54:27+00:00
preparser: use an unsigned for the request identification

This id can be used to cancel a task.

- - - - -
7bf41313 by Thomas Guillem at 2024-10-17T14:54:27+00:00
preparser: return the number of tasks cancelled

- - - - -
30a97895 by Thomas Guillem at 2024-10-17T14:54:27+00:00
medialibrary: add missing error check

- - - - -
b8fe9c99 by Thomas Guillem at 2024-10-17T14:54:27+00:00
thumbnailer: move lock/cond to thumbnailer

It executes one task at a time and the mutex is only held for fast
operations.

- - - - -
69413e1d by Thomas Guillem at 2024-10-17T14:54:27+00:00
thumbnailer: store requests internally

Like the preparser is doing.

vlc_thumbnailer_request_t is now an incremented id.

vlc_thumbnailer_DestroyRequest() will only cancel the request if the id
matches. The request is now handled and cleaned internally.

The API will change in the next commit.

- - - - -
a9fdd37f by Thomas Guillem at 2024-10-17T14:54:27+00:00
thumbnailer: use an unsigned for the request identification

This id can be used to cancel a task.

vlc_thumbnailer_DestroyRequest() had been renamed to
vlc_thumbnailer_Cancel(). The new function is optional and can be used
to cancel a task. The user doesn't have the responsibility to free the
request anymore.

- - - - -
da2ff179 by Thomas Guillem at 2024-10-17T14:54:27+00:00
thumbnailer: return the number of tasks cancelled

- - - - -


17 changed files:

- include/vlc_media_source.h
- include/vlc_preparser.h
- include/vlc_thumbnailer.h
- lib/media.c
- lib/media_internal.h
- modules/gui/macosx/library/media-source/VLCMediaSource.m
- modules/gui/qt/network/networkmediamodel.cpp
- modules/gui/qt/player/player_controller.cpp
- modules/misc/medialibrary/Thumbnailer.cpp
- modules/misc/medialibrary/medialibrary.h
- src/input/thumbnailer.c
- src/libvlccore.sym
- src/media_source/media_tree.c
- src/playlist/preparse.c
- src/preparser/preparser.c
- test/libvlc/media.c
- test/src/input/thumbnail.c


Changes:

=====================================
include/vlc_media_source.h
=====================================
@@ -236,12 +236,12 @@ vlc_media_tree_Find(vlc_media_tree_t *tree, const input_item_t *media,
  * \param tree   the media tree (not necessarily locked)
  * \param parser a valid preparser
  * \param media  the media to preparse
- * \param id     a task identifier, cancel it via vlc_preparser_Cancel()
+ * \returns VLC_PREPARSER_REQ_ID_INVALID in case of error, or a valid id if the
+ * item was scheduled for preparsing. Cancel it vlc_preparser_Cancel().
  */
-VLC_API void
+VLC_API vlc_preparser_req_id
 vlc_media_tree_Preparse(vlc_media_tree_t *tree, vlc_preparser_t *parser,
-                        input_item_t *media, void *id);
-
+                        input_item_t *media);
 
 /**
  * Media source.


=====================================
include/vlc_preparser.h
=====================================
@@ -42,6 +42,9 @@
  * It will also issue art fetching requests.
  */
 typedef struct vlc_preparser_t vlc_preparser_t;
+typedef size_t vlc_preparser_req_id;
+
+#define VLC_PREPARSER_REQ_ID_INVALID 0
 
 typedef enum input_item_meta_request_option_t
 {
@@ -84,22 +87,25 @@ VLC_API vlc_preparser_t *vlc_preparser_New( vlc_object_t *obj,
  * @param cbs_userdata opaque pointer used by the callbacks
  * @param id unique id provided by the caller. This is can be used to cancel
  * the request with vlc_preparser_Cancel()
- * @returns VLC_SUCCESS if the item was scheduled for preparsing, an error code
- * otherwise
- * If this returns an error, the on_preparse_ended will *not* be invoked
+ * @return VLC_PREPARSER_REQ_ID_INVALID in case of error, or a valid id if the
+ * item was scheduled for preparsing. If this returns an
+ * error, the on_preparse_ended will *not* be invoked
  */
-VLC_API int vlc_preparser_Push( vlc_preparser_t *preparser, input_item_t *item,
-                                input_item_meta_request_option_t option,
-                                const input_item_parser_cbs_t *cbs,
-                                void *cbs_userdata, void *id );
+VLC_API vlc_preparser_req_id
+vlc_preparser_Push( vlc_preparser_t *preparser, input_item_t *item,
+                    input_item_meta_request_option_t option,
+                    const input_item_parser_cbs_t *cbs, void *cbs_userdata );
 
 /**
  * This function cancel all preparsing requests for a given id
  *
  * @param preparser the preparser object
- * @param id unique id given to vlc_preparser_Push()
+ * @param id unique id returned by vlc_preparser_Push(),
+ * VLC_PREPARSER_REQ_ID_INVALID to cancels all tasks
+ * @return number of tasks cancelled
  */
-VLC_API void vlc_preparser_Cancel( vlc_preparser_t *preparser, void *id );
+VLC_API size_t vlc_preparser_Cancel( vlc_preparser_t *preparser,
+                                     vlc_preparser_req_id id );
 
 /**
  * This function destroys the preparser object and thread.


=====================================
include/vlc_thumbnailer.h
=====================================
@@ -27,7 +27,9 @@
 #include <vlc_tick.h>
 
 typedef struct vlc_thumbnailer_t vlc_thumbnailer_t;
-typedef struct vlc_thumbnailer_request_t vlc_thumbnailer_request_t;
+typedef size_t vlc_thumbnailer_req_id;
+
+#define VLC_THUMBNAILER_REQ_ID_INVALID 0
 
 /**
  * \brief vlc_thumbnailer_cb defines a callback invoked on thumbnailing completion or error
@@ -71,17 +73,15 @@ enum vlc_thumbnailer_seek_speed
  * \param timeout A timeout value, or VLC_TICK_INVALID to disable timeout
  * \param cb A user callback to be called on completion (success & error)
  * \param user_data An opaque value, provided as pf_cb's first parameter
- * \return An opaque request object, or NULL in case of failure
+ * \returns > 0 if the item was scheduled for thumbnailing, 0 in case of error.
  *
- * If this function returns a valid request object, the callback is guaranteed
- * to be called, even in case of later failure (except if destroyed early by
+ * If this function returns a valid id, the callback is guaranteed
+ * to be called, even in case of later failure (except if cancelled early by
  * the user).
- * The returned request object must be freed with
- * vlc_thumbnailer_DestroyRequest().
  * The provided input_item will be held by the thumbnailer and can safely be
  * released safely after calling this function.
  */
-VLC_API vlc_thumbnailer_request_t*
+VLC_API vlc_thumbnailer_req_id
 vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
                                vlc_tick_t time,
                                enum vlc_thumbnailer_seek_speed speed,
@@ -96,17 +96,15 @@ vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
  * \param timeout A timeout value, or VLC_TICK_INVALID to disable timeout
  * \param cb A user callback to be called on completion (success & error)
  * \param user_data An opaque value, provided as pf_cb's first parameter
- * \return An opaque request object, or NULL in case of failure
- *
- * If this function returns a valid request object, the callback is guaranteed
- * to be called, even in case of later failure (except if destroyed early by
- * the user).
- * The returned request object must be freed with
- * vlc_thumbnailer_DestroyRequest().
+
+ * @return VLC_THUMBNAILER_REQ_ID_INVALID in case of error, or a valid id if
+ * the item was scheduled for preparsing.  If this function returns a valid id,
+ * the callback is guaranteed to be called, even in case of later failure
+ * (except if cancelled early by the user).
  * The provided input_item will be held by the thumbnailer and can safely be
- * released after calling this function.
+ * released safely after calling this function.
  */
-VLC_API vlc_thumbnailer_request_t*
+VLC_API vlc_thumbnailer_req_id
 vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
                               double pos,
                               enum vlc_thumbnailer_seek_speed speed,
@@ -114,16 +112,14 @@ vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
                               vlc_thumbnailer_cb cb, void* user_data );
 
 /**
- * \brief vlc_thumbnailer_DestroyRequest Destroy a thumbnail request
+ * \brief vlc_thumbnailer_Camcel Cancel a thumbnail request
  * \param thumbnailer A thumbnailer object
- * \param request An opaque thumbnail request object
- *
- * The request can be destroyed before receiving a callback (in that case, the
- * callback won't be called) or after (to release resources).
+ * \param id unique id returned by vlc_thumbnailer_Request*(),
+ * VLC_THUMBNAILER_REQ_ID_INVALID to cancels all tasks
+ * \return number of tasks cancelled
  */
-VLC_API void
-vlc_thumbnailer_DestroyRequest( vlc_thumbnailer_t* thumbnailer,
-                                vlc_thumbnailer_request_t* request );
+VLC_API size_t
+vlc_thumbnailer_Cancel( vlc_thumbnailer_t* thumbnailer, vlc_thumbnailer_req_id id );
 
 /**
  * \brief vlc_thumbnailer_Release releases a thumbnailer and cancel all pending requests


=====================================
lib/media.c
=====================================
@@ -39,7 +39,6 @@
 #include <vlc_url.h>
 #include <vlc_thumbnailer.h>
 #include <vlc_atomic.h>
-#include <vlc_preparser.h>
 
 #include "../src/libvlc.h"
 
@@ -372,6 +371,7 @@ libvlc_media_t * libvlc_media_new_from_input_item(input_item_t *p_input_item )
 
     p_md->p_input_item->libvlc_owner = p_md;
     atomic_init(&p_md->parsed_status, libvlc_media_parsed_status_none);
+    p_md->id = VLC_PREPARSER_REQ_ID_INVALID;
 
     libvlc_event_manager_init( &p_md->event_manager, p_md );
 
@@ -742,7 +742,6 @@ int libvlc_media_parse_request(libvlc_instance_t *inst, libvlc_media_t *media,
 
     input_item_t *item = media->p_input_item;
     input_item_meta_request_option_t parse_scope = 0;
-    int ret;
     unsigned int ref = atomic_load_explicit(&media->worker_count,
                                             memory_order_relaxed);
     do
@@ -816,9 +815,9 @@ int libvlc_media_parse_request(libvlc_instance_t *inst, libvlc_media_t *media,
 
     vlc_preparser_SetTimeout(parser, VLC_TICK_FROM_MS(timeout));
 
-    ret = vlc_preparser_Push(parser, item, parse_scope,
-                             &preparser_callbacks, media, media);
-    if (ret != VLC_SUCCESS)
+    media->id = vlc_preparser_Push(parser, item, parse_scope,
+                             &preparser_callbacks, media);
+    if (media->id == VLC_PREPARSER_REQ_ID_INVALID)
     {
         atomic_fetch_sub_explicit(&media->worker_count, 1,
                                   memory_order_relaxed);
@@ -833,7 +832,11 @@ libvlc_media_parse_stop(libvlc_instance_t *inst, libvlc_media_t *media)
 {
     vlc_preparser_t *parser = libvlc_get_preparser(inst);
     assert(parser != NULL);
-    vlc_preparser_Cancel(parser, media);
+    if (media->id != VLC_PREPARSER_REQ_ID_INVALID)
+    {
+        vlc_preparser_Cancel(parser, media->id);
+        media->id = VLC_PREPARSER_REQ_ID_INVALID;
+    }
 }
 
 // Get Parsed status for media descriptor object
@@ -921,7 +924,7 @@ struct libvlc_media_thumbnail_request_t
     unsigned int height;
     bool crop;
     libvlc_picture_type_t type;
-    vlc_thumbnailer_request_t* req;
+    vlc_thumbnailer_req_id id;
 };
 
 static void media_on_thumbnail_ready( void* data, picture_t* thumbnail )
@@ -967,14 +970,14 @@ libvlc_media_thumbnail_request_by_time( libvlc_instance_t *inst,
     req->type = picture_type;
     req->crop = crop;
     libvlc_media_retain( md );
-    req->req = vlc_thumbnailer_RequestByTime( thumb,
+    req->id = vlc_thumbnailer_RequestByTime( thumb,
         vlc_tick_from_libvlc_time( time ),
         speed == libvlc_media_thumbnail_seek_fast ?
             VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
         md->p_input_item,
         timeout > 0 ? vlc_tick_from_libvlc_time( timeout ) : VLC_TICK_INVALID,
         media_on_thumbnail_ready, req );
-    if ( req->req == NULL )
+    if ( req->id == VLC_PREPARSER_REQ_ID_INVALID )
     {
         free( req );
         libvlc_media_release( md );
@@ -1010,13 +1013,13 @@ libvlc_media_thumbnail_request_by_pos( libvlc_instance_t *inst,
     req->crop = crop;
     req->type = picture_type;
     libvlc_media_retain( md );
-    req->req = vlc_thumbnailer_RequestByPos( thumb, pos,
+    req->id = vlc_thumbnailer_RequestByPos( thumb, pos,
         speed == libvlc_media_thumbnail_seek_fast ?
             VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
         md->p_input_item,
         timeout > 0 ? vlc_tick_from_libvlc_time( timeout ) : VLC_TICK_INVALID,
         media_on_thumbnail_ready, req );
-    if ( req->req == NULL )
+    if ( req->id == VLC_PREPARSER_REQ_ID_INVALID )
     {
         free( req );
         libvlc_media_release( md );
@@ -1032,7 +1035,7 @@ void libvlc_media_thumbnail_request_destroy( libvlc_media_thumbnail_request_t *r
     vlc_thumbnailer_t *thumb = libvlc_get_thumbnailer(req->instance);
     assert(thumb != NULL);
 
-    vlc_thumbnailer_DestroyRequest( thumb, req->req );
+    vlc_thumbnailer_Cancel( thumb, req->id );
     libvlc_media_release( req->md );
     libvlc_release(req->instance);
     free( req );


=====================================
lib/media_internal.h
=====================================
@@ -30,6 +30,7 @@
 #include <vlc_common.h>
 #include <vlc_input.h>
 #include <vlc_player.h>
+#include <vlc_preparser.h>
 #include <vlc_atomic.h>
 
 struct libvlc_media_t
@@ -48,6 +49,7 @@ struct libvlc_media_t
     atomic_uint worker_count;
 
     _Atomic libvlc_media_parsed_status_t parsed_status;
+    vlc_preparser_req_id id;
 };
 
 /* Media Descriptor */


=====================================
modules/gui/macosx/library/media-source/VLCMediaSource.m
=====================================
@@ -317,7 +317,7 @@ static const char *const myFoldersDescription = "My Folders";
     }
 
     vlc_media_tree_Preparse(_p_mediaSource->tree, _p_preparser,
-                            inputNode.inputItem.vlcInputItem, NULL);
+                            inputNode.inputItem.vlcInputItem);
 }
 
 - (void)clearChildNodesForNode:(nonnull input_item_node_t*)inputNode


=====================================
modules/gui/qt/network/networkmediamodel.cpp
=====================================
@@ -95,7 +95,7 @@ class NetworkMediaModelPrivate
 public:
     NetworkMediaModelPrivate(NetworkMediaModel* pub)
         : LocalListBaseModelPrivate<NetworkMediaItemPtr>(pub)
-        , m_preparseSem(1)
+        , m_preparseSem(1), m_parserId(VLC_PREPARSER_REQ_ID_INVALID)
     {}
 
 public:
@@ -409,7 +409,8 @@ public:
             input_item_node_t* mediaNode = nullptr;
             input_item_node_t* parent = nullptr;
             vlc_media_tree_Lock(tree);
-            vlc_preparser_Cancel( parser, this );
+            if (m_parserId != VLC_PREPARSER_REQ_ID_INVALID)
+                vlc_preparser_Cancel( parser, m_parserId );
             std::vector<SharedInputItem> itemList;
             q->m_path = {QVariant::fromValue(PathNode(q->m_treeItem, q->m_name))};
             if (vlc_media_tree_Find( tree, q->m_treeItem.media.get(), &mediaNode, &parent))
@@ -437,7 +438,7 @@ public:
         }
 
         m_preparseSem.acquire();
-        vlc_media_tree_Preparse( tree, parser, q->m_treeItem.media.get(), this );
+        m_parserId = vlc_media_tree_Preparse( tree, parser, q->m_treeItem.media.get() );
 
         m_listener = std::move( l );
 
@@ -466,6 +467,8 @@ public:
     std::unique_ptr<MediaTreeListener> m_listener;
     QHash<QString, NetworkMediaItemPtr> m_items;
     std::unique_ptr<MLMediaStore> m_MLMedias;
+private:
+    vlc_preparser_req_id m_parserId;
 };
 
 // NetworkMediaModel::ListenerCb implementation
@@ -497,7 +500,11 @@ NetworkMediaModel::~NetworkMediaModel()
         auto parser = m_ctx->getNetworkPreparser();
         if (likely(parser != NULL))
         {
-            vlc_preparser_Cancel( parser, this );
+            if (d->m_parserId != VLC_PREPARSER_REQ_ID_INVALID)
+            {
+                vlc_preparser_Cancel( parser, d->m_parserId );
+                d->m_parserId = VLC_PREPARSER_REQ_ID_INVALID;
+            }
             //wait for the callback call on cancel
             d->m_preparseSem.acquire();
         }


=====================================
modules/gui/qt/player/player_controller.cpp
=====================================
@@ -1968,7 +1968,7 @@ void PlayerController::requestArtUpdate( input_item_t *p_item )
             META_REQUEST_OPTION_FETCH_LOCAL;
 
     vlc_preparser_Push( d->m_preparser, p_item, fetch_options,
-                        &art_fetcher_cbs, d, nullptr );
+                        &art_fetcher_cbs, d  );
 }
 
 void PlayerControllerPrivate::onArtFetchEnded(input_item_t *p_item, bool)


=====================================
modules/misc/medialibrary/Thumbnailer.cpp
=====================================
@@ -70,18 +70,22 @@ bool Thumbnailer::generate( const medialibrary::IMedia&, const std::string& mrl,
     {
         vlc::threads::mutex_locker lock( m_mutex );
         m_currentContext = &ctx;
-        ctx.request = vlc_thumbnailer_RequestByPos( m_thumbnailer.get(), position,
-                                      VLC_THUMBNAILER_SEEK_FAST, item.get(),
-                                      VLC_TICK_FROM_SEC( 3 ),
-                                      &onThumbnailComplete, &ctx );
+        vlc_thumbnailer_req_id requestId =
+            vlc_thumbnailer_RequestByPos( m_thumbnailer.get(), position,
+                                          VLC_THUMBNAILER_SEEK_FAST, item.get(),
+                                          VLC_TICK_FROM_SEC( 3 ),
+                                          &onThumbnailComplete, &ctx );
 
+        if (requestId == VLC_THUMBNAILER_REQ_ID_INVALID)
+        {
+            m_currentContext = nullptr;
+            return false;
+        }
         while ( ctx.done == false )
             m_cond.wait( m_mutex );
         m_currentContext = nullptr;
     }
 
-    vlc_thumbnailer_DestroyRequest(m_thumbnailer.get(), ctx.request);
-
     if ( ctx.thumbnail == nullptr )
         return false;
 


=====================================
modules/misc/medialibrary/medialibrary.h
=====================================
@@ -41,7 +41,6 @@
 struct vlc_event_t;
 struct vlc_object_t;
 struct vlc_thumbnailer_t;
-struct vlc_thumbnailer_request_t;
 
 class Logger;
 
@@ -129,7 +128,6 @@ class Thumbnailer : public medialibrary::IThumbnailer
         Thumbnailer* thumbnailer;
         bool done;
         picture_t* thumbnail;
-        vlc_thumbnailer_request_t* request;
     };
 public:
     Thumbnailer(vlc_medialibrary_module_t* ml);


=====================================
src/input/thumbnailer.c
=====================================
@@ -32,6 +32,12 @@ struct vlc_thumbnailer_t
 {
     vlc_object_t* parent;
     vlc_executor_t *executor;
+    vlc_mutex_t lock;
+    vlc_cond_t cond_ended;
+
+    vlc_thumbnailer_req_id current_id;
+
+    struct vlc_list submitted_tasks; /**< list of struct task */
 };
 
 struct seek_target
@@ -48,13 +54,8 @@ struct seek_target
     };
 };
 
-/* We may not rename vlc_thumbnailer_request_t because it is exposed in the
- * public API */
-typedef struct vlc_thumbnailer_request_t task_t;
-
-struct vlc_thumbnailer_request_t
+typedef struct task
 {
-    vlc_atomic_rc_t rc;
     vlc_thumbnailer_t *thumbnailer;
 
     struct seek_target seek_target;
@@ -68,8 +69,6 @@ struct vlc_thumbnailer_request_t
     vlc_thumbnailer_cb cb;
     void* userdata;
 
-    vlc_mutex_t lock;
-    vlc_cond_t cond_ended;
     enum
     {
         RUNNING,
@@ -78,8 +77,11 @@ struct vlc_thumbnailer_request_t
     } status;
     picture_t *pic;
 
+    vlc_thumbnailer_req_id id;
+
     struct vlc_runnable runnable; /**< to be passed to the executor */
-};
+    struct vlc_list node; /**< node of vlc_thumbnailer_t.submitted_tasks */
+} task_t;
 
 static void RunnableRun(void *);
 
@@ -92,7 +94,6 @@ TaskNew(vlc_thumbnailer_t *thumbnailer, input_item_t *item,
     if (!task)
         return NULL;
 
-    vlc_atomic_rc_init(&task->rc);
     task->thumbnailer = thumbnailer;
     task->item = item;
     task->seek_target = seek_target;
@@ -101,8 +102,6 @@ TaskNew(vlc_thumbnailer_t *thumbnailer, input_item_t *item,
     task->userdata = userdata;
     task->timeout = timeout;
 
-    vlc_mutex_init(&task->lock);
-    vlc_cond_init(&task->cond_ended);
     task->status = RUNNING;
     task->pic = NULL;
 
@@ -115,10 +114,8 @@ TaskNew(vlc_thumbnailer_t *thumbnailer, input_item_t *item,
 }
 
 static void
-TaskRelease(task_t *task)
+TaskDestroy(task_t *task)
 {
-    if (!vlc_atomic_rc_dec(&task->rc))
-        return;
     input_item_Release(task->item);
     free(task);
 }
@@ -140,14 +137,15 @@ on_thumbnailer_input_event( input_thread_t *input,
          return;
 
     task_t *task = userdata;
+    vlc_thumbnailer_t *thumbnailer = task->thumbnailer;
 
-    vlc_mutex_lock(&task->lock);
+    vlc_mutex_lock(&thumbnailer->lock);
     if (task->status != RUNNING)
     {
         /* We may receive a THUMBNAIL_READY event followed by an
          * INPUT_EVENT_STATE (end of stream), we must only consider the first
          * one. */
-        vlc_mutex_unlock(&task->lock);
+        vlc_mutex_unlock(&thumbnailer->lock);
         return;
     }
 
@@ -156,8 +154,8 @@ on_thumbnailer_input_event( input_thread_t *input,
     if (event->type == INPUT_EVENT_THUMBNAIL_READY)
         task->pic = picture_Hold(event->thumbnail);
 
-    vlc_cond_signal(&task->cond_ended);
-    vlc_mutex_unlock(&task->lock);
+    vlc_cond_signal(&thumbnailer->cond_ended);
+    vlc_mutex_unlock(&thumbnailer->lock);
 }
 
 static void
@@ -200,11 +198,11 @@ RunnableRun(void *userdata)
         goto error;
     }
 
-    vlc_mutex_lock(&task->lock);
+    vlc_mutex_lock(&thumbnailer->lock);
     if (task->timeout == VLC_TICK_INVALID)
     {
         while (task->status == RUNNING)
-            vlc_cond_wait(&task->cond_ended, &task->lock);
+            vlc_cond_wait(&thumbnailer->cond_ended, &thumbnailer->lock);
     }
     else
     {
@@ -212,13 +210,15 @@ RunnableRun(void *userdata)
         int timeout = 0;
         while (task->status == RUNNING && timeout == 0)
             timeout =
-                vlc_cond_timedwait(&task->cond_ended, &task->lock, deadline);
+                vlc_cond_timedwait(&thumbnailer->cond_ended, &thumbnailer->lock, deadline);
     }
     picture_t* pic = task->pic;
     task->pic = NULL;
 
     bool notify = task->status != INTERRUPTED;
-    vlc_mutex_unlock(&task->lock);
+
+    vlc_list_remove(&task->node);
+    vlc_mutex_unlock(&thumbnailer->lock);
 
     if (notify)
         NotifyThumbnail(task, pic);
@@ -230,20 +230,10 @@ RunnableRun(void *userdata)
     input_Close(input);
 
 error:
-    TaskRelease(task);
+    TaskDestroy(task);
 }
 
-static void
-Interrupt(task_t *task)
-{
-    /* Wake up RunnableRun() which will call input_Stop() */
-    vlc_mutex_lock(&task->lock);
-    task->status = INTERRUPTED;
-    vlc_cond_signal(&task->cond_ended);
-    vlc_mutex_unlock(&task->lock);
-}
-
-static task_t *
+static vlc_thumbnailer_req_id
 RequestCommon(vlc_thumbnailer_t *thumbnailer, struct seek_target seek_target,
               enum vlc_thumbnailer_seek_speed speed, input_item_t *item,
               vlc_tick_t timeout, vlc_thumbnailer_cb cb, void *userdata)
@@ -252,16 +242,22 @@ RequestCommon(vlc_thumbnailer_t *thumbnailer, struct seek_target seek_target,
     task_t *task = TaskNew(thumbnailer, item, seek_target, fast_seek, cb,
                            userdata, timeout);
     if (!task)
-        return NULL;
+        return 0;
+
+    vlc_mutex_lock(&thumbnailer->lock);
+    vlc_thumbnailer_req_id id = task->id = thumbnailer->current_id++;
+    static_assert(VLC_THUMBNAILER_REQ_ID_INVALID == 0, "Invalid id should be 0");
+    if (unlikely(thumbnailer->current_id == 0)) /* unsigned wrapping */
+        ++thumbnailer->current_id;
+    vlc_list_append(&task->node, &thumbnailer->submitted_tasks);
+    vlc_mutex_unlock(&thumbnailer->lock);
 
-    /* One ref for the executor */
-    vlc_atomic_rc_inc(&task->rc);
     vlc_executor_Submit(thumbnailer->executor, &task->runnable);
 
-    return task;
+    return id;
 }
 
-task_t *
+vlc_thumbnailer_req_id
 vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
                                vlc_tick_t time,
                                enum vlc_thumbnailer_seek_speed speed,
@@ -276,7 +272,7 @@ vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
                          userdata);
 }
 
-task_t *
+vlc_thumbnailer_req_id
 vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
                               double pos, enum vlc_thumbnailer_seek_speed speed,
                               input_item_t *item, vlc_tick_t timeout,
@@ -290,20 +286,36 @@ vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
                          userdata);
 }
 
-void vlc_thumbnailer_DestroyRequest( vlc_thumbnailer_t* thumbnailer, task_t* task )
+size_t vlc_thumbnailer_Cancel( vlc_thumbnailer_t* thumbnailer, vlc_thumbnailer_req_id id )
 {
-    bool canceled = vlc_executor_Cancel(thumbnailer->executor, &task->runnable);
-    if (canceled)
+    vlc_mutex_lock(&thumbnailer->lock);
+
+    task_t *task;
+    size_t count = 0;
+    vlc_list_foreach(task, &thumbnailer->submitted_tasks, node)
     {
-        /* Release the executor reference (since it won't run) */
-        bool ret = vlc_atomic_rc_dec(&task->rc);
-        /* Assert that only the caller got the reference */
-        assert(!ret); (void) ret;
+        if (id == VLC_THUMBNAILER_REQ_ID_INVALID || task->id == id)
+        {
+            count++;
+            bool canceled =
+                vlc_executor_Cancel(thumbnailer->executor, &task->runnable);
+            if (canceled)
+            {
+                vlc_list_remove(&task->node);
+                TaskDestroy(task);
+            }
+            else
+            {
+                /* The task will be finished and destroyed after run() */
+                task->status = INTERRUPTED;
+                vlc_cond_signal(&thumbnailer->cond_ended);
+            }
+        }
     }
-    else
-        Interrupt(task);
 
-    TaskRelease(task);
+    vlc_mutex_unlock(&thumbnailer->lock);
+
+    return count;
 }
 
 vlc_thumbnailer_t *vlc_thumbnailer_Create( vlc_object_t* parent)
@@ -320,6 +332,10 @@ vlc_thumbnailer_t *vlc_thumbnailer_Create( vlc_object_t* parent)
     }
 
     thumbnailer->parent = parent;
+    thumbnailer->current_id = 1;
+    vlc_mutex_init(&thumbnailer->lock);
+    vlc_cond_init(&thumbnailer->cond_ended);
+    vlc_list_init(&thumbnailer->submitted_tasks);
 
     return thumbnailer;
 }


=====================================
src/libvlccore.sym
=====================================
@@ -833,7 +833,7 @@ vlc_encoder_Destroy
 vlc_thumbnailer_Create
 vlc_thumbnailer_RequestByTime
 vlc_thumbnailer_RequestByPos
-vlc_thumbnailer_DestroyRequest
+vlc_thumbnailer_Cancel
 vlc_thumbnailer_Release
 vlc_player_AddAssociatedMedia
 vlc_player_AddListener


=====================================
src/media_source/media_tree.c
=====================================
@@ -338,20 +338,19 @@ static const input_item_parser_cbs_t preparser_callbacks = {
     .on_subtree_added = media_subtree_changed,
 };
 
-void
+vlc_preparser_req_id
 vlc_media_tree_Preparse(vlc_media_tree_t *tree, vlc_preparser_t *parser,
-                        input_item_t *media, void* id)
+                        input_item_t *media)
 {
 #ifdef TEST_MEDIA_SOURCE
     VLC_UNUSED(tree);
     VLC_UNUSED(parser);
     VLC_UNUSED(media);
-    VLC_UNUSED(id);
     VLC_UNUSED(preparser_callbacks);
 #else
-    vlc_preparser_Push(parser, media, META_REQUEST_OPTION_PARSE |
-                       META_REQUEST_OPTION_DO_INTERACT |
-                       META_REQUEST_OPTION_PARSE_SUBITEMS,
-                       &preparser_callbacks, tree, id);
+    return vlc_preparser_Push(parser, media, META_REQUEST_OPTION_PARSE |
+                              META_REQUEST_OPTION_DO_INTERACT |
+                              META_REQUEST_OPTION_PARSE_SUBITEMS,
+                              &preparser_callbacks, tree);
 #endif
 }


=====================================
src/playlist/preparse.c
=====================================
@@ -155,6 +155,6 @@ vlc_playlist_AutoPreparse(vlc_playlist_t *playlist, input_item_t *input,
             options |= META_REQUEST_OPTION_PARSE_SUBITEMS;
 
         vlc_preparser_Push(playlist->parser, input, options,
-                           &preparser_callbacks, playlist, NULL);
+                           &preparser_callbacks, playlist);
     }
 }


=====================================
src/preparser/preparser.c
=====================================
@@ -40,6 +40,7 @@ struct vlc_preparser_t
     atomic_bool deactivated;
 
     vlc_mutex_t lock;
+    vlc_preparser_req_id current_id;
     struct vlc_list submitted_tasks; /**< list of struct task */
 };
 
@@ -50,7 +51,7 @@ struct task
     input_item_meta_request_option_t options;
     const input_item_parser_cbs_t *cbs;
     void *userdata;
-    void *id;
+    vlc_preparser_req_id id;
     vlc_tick_t timeout;
 
     input_item_parser_id_t *parser;
@@ -69,8 +70,7 @@ static void RunnableRun(void *);
 static struct task *
 TaskNew(vlc_preparser_t *preparser, input_item_t *item,
         input_item_meta_request_option_t options,
-        const input_item_parser_cbs_t *cbs, void *userdata,
-        void *id, vlc_tick_t timeout)
+        const input_item_parser_cbs_t *cbs, void *userdata, vlc_tick_t timeout)
 {
     assert(timeout >= 0);
 
@@ -83,7 +83,6 @@ TaskNew(vlc_preparser_t *preparser, input_item_t *item,
     task->options = options;
     task->cbs = cbs;
     task->userdata = userdata;
-    task->id = id;
     task->timeout = timeout;
 
     input_item_Hold(item);
@@ -106,12 +105,24 @@ TaskDelete(struct task *task)
     free(task);
 }
 
-static void
+static vlc_preparser_req_id
+PreparserGetNextTaskIdLocked(vlc_preparser_t *preparser, struct task *task)
+{
+    vlc_preparser_req_id id = task->id = preparser->current_id++;
+    static_assert(VLC_PREPARSER_REQ_ID_INVALID == 0, "Invalid id should be 0");
+    if (unlikely(preparser->current_id == 0)) /* unsigned wrapping */
+        ++preparser->current_id;
+    return id;
+}
+
+static vlc_preparser_req_id
 PreparserAddTask(vlc_preparser_t *preparser, struct task *task)
 {
     vlc_mutex_lock(&preparser->lock);
+    vlc_preparser_req_id id = PreparserGetNextTaskIdLocked(preparser, task);
     vlc_list_append(&task->node, &preparser->submitted_tasks);
     vlc_mutex_unlock(&preparser->lock);
+    return id;
 }
 
 static void
@@ -352,16 +363,18 @@ vlc_preparser_t* vlc_preparser_New( vlc_object_t *parent, unsigned max_threads,
 
     vlc_mutex_init(&preparser->lock);
     vlc_list_init(&preparser->submitted_tasks);
+    preparser->current_id = 1;
 
     return preparser;
 }
 
-int vlc_preparser_Push( vlc_preparser_t *preparser,
-    input_item_t *item, input_item_meta_request_option_t i_options,
-    const input_item_parser_cbs_t *cbs, void *cbs_userdata, void *id )
+vlc_preparser_req_id vlc_preparser_Push( vlc_preparser_t *preparser, input_item_t *item,
+                                  input_item_meta_request_option_t i_options,
+                                  const input_item_parser_cbs_t *cbs,
+                                  void *cbs_userdata )
 {
     if( atomic_load( &preparser->deactivated ) )
-        return VLC_EGENERIC;
+        return 0;
 
     assert(i_options & META_REQUEST_OPTION_PARSE
         || i_options & META_REQUEST_OPTION_FETCH_ANY);
@@ -372,34 +385,44 @@ int vlc_preparser_Push( vlc_preparser_t *preparser,
         || preparser->fetcher != NULL);
 
     struct task *task =
-        TaskNew(preparser, item, i_options, cbs, cbs_userdata, id,
+        TaskNew(preparser, item, i_options, cbs, cbs_userdata,
                 preparser->default_timeout);
     if( !task )
-        return VLC_ENOMEM;
+        return 0;
 
     if (preparser->executor != NULL)
     {
-        PreparserAddTask(preparser, task);
+        vlc_preparser_req_id id = PreparserAddTask(preparser, task);
 
         vlc_executor_Submit(preparser->executor, &task->runnable);
 
-        return VLC_SUCCESS;
+        return id;
     }
-    return Fetch(task);
+
+    /* input_fetcher is not cancellable (for now) but we need to generate a new
+     * id anyway. */
+    vlc_mutex_lock(&preparser->lock);
+    vlc_preparser_req_id id = PreparserGetNextTaskIdLocked(preparser, task);
+    vlc_mutex_unlock(&preparser->lock);
+
+    int ret = Fetch(task);
+    return ret == VLC_SUCCESS ? id : 0;
 }
 
-void vlc_preparser_Cancel( vlc_preparser_t *preparser, void *id )
+size_t vlc_preparser_Cancel( vlc_preparser_t *preparser, vlc_preparser_req_id id )
 {
     if (preparser->executor == NULL)
-        return; /* TODO: the fetcher should be cancellable too */
+        return 0; /* TODO: the fetcher should be cancellable too */
 
     vlc_mutex_lock(&preparser->lock);
 
     struct task *task;
+    size_t count = 0;
     vlc_list_foreach(task, &preparser->submitted_tasks, node)
     {
-        if (!id || task->id == id)
+        if (id == VLC_PREPARSER_REQ_ID_INVALID || task->id == id)
         {
+            count++;
             bool canceled =
                 vlc_executor_Cancel(preparser->executor, &task->runnable);
             if (canceled)
@@ -415,12 +438,14 @@ void vlc_preparser_Cancel( vlc_preparser_t *preparser, void *id )
     }
 
     vlc_mutex_unlock(&preparser->lock);
+
+    return count;
 }
 
 void vlc_preparser_Deactivate( vlc_preparser_t* preparser )
 {
     atomic_store( &preparser->deactivated, true );
-    vlc_preparser_Cancel(preparser, NULL);
+    vlc_preparser_Cancel(preparser, 0);
 }
 
 void vlc_preparser_SetTimeout( vlc_preparser_t *preparser,
@@ -432,7 +457,7 @@ void vlc_preparser_SetTimeout( vlc_preparser_t *preparser,
 void vlc_preparser_Delete( vlc_preparser_t *preparser )
 {
     /* In case vlc_preparser_Deactivate() has not been called */
-    vlc_preparser_Cancel(preparser, NULL);
+    vlc_preparser_Cancel(preparser, 0);
 
     if (preparser->executor != NULL)
         vlc_executor_Delete(preparser->executor);


=====================================
test/libvlc/media.c
=====================================
@@ -247,13 +247,14 @@ static void test_input_metadata_timeout(libvlc_instance_t *vlc, int timeout,
                                                 1, VLC_TICK_FROM_MS(timeout),
                                                 options);
     assert(parser != NULL);
-    i_ret = vlc_preparser_Push(parser, p_item, options, &cbs, &sem, parser);
-    assert(i_ret == 0);
+    vlc_preparser_req_id id = vlc_preparser_Push(parser, p_item, options, &cbs, &sem);
+    assert(id != VLC_PREPARSER_REQ_ID_INVALID);
 
     if (wait_and_cancel > 0)
     {
         vlc_tick_sleep( VLC_TICK_FROM_MS(wait_and_cancel) );
-        vlc_preparser_Cancel(parser, parser);
+        size_t count = vlc_preparser_Cancel(parser, id);
+        assert(count == 1);
 
     }
     vlc_sem_wait(&sem);


=====================================
test/src/input/thumbnail.c
=====================================
@@ -135,27 +135,26 @@ static void test_thumbnails( libvlc_instance_t* p_vlc )
 
         vlc_mutex_lock( &ctx.lock );
 
-        vlc_thumbnailer_request_t* p_req;
+        vlc_thumbnailer_req_id id;
         if ( test_params[i].b_use_pos )
         {
-            p_req = vlc_thumbnailer_RequestByPos( p_thumbnailer, test_params[i].f_pos,
+            id = vlc_thumbnailer_RequestByPos( p_thumbnailer, test_params[i].f_pos,
                 test_params[i].b_fast_seek ?
                     VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
                 p_item, test_params[i].i_timeout, thumbnailer_callback, &ctx );
         }
         else
         {
-            p_req = vlc_thumbnailer_RequestByTime( p_thumbnailer, test_params[i].i_time,
+            id = vlc_thumbnailer_RequestByTime( p_thumbnailer, test_params[i].i_time,
                 test_params[i].b_fast_seek ?
                     VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
                 p_item, test_params[i].i_timeout, thumbnailer_callback, &ctx );
         }
-        assert( p_req != NULL );
+        assert( id != VLC_THUMBNAILER_REQ_ID_INVALID );
 
         while ( ctx.b_done == false )
             vlc_cond_wait( &ctx.cond, &ctx.lock );
 
-        vlc_thumbnailer_DestroyRequest( p_thumbnailer, p_req );
         vlc_mutex_unlock( &ctx.lock );
 
         input_item_Release( p_item );
@@ -184,11 +183,11 @@ static void test_cancel_thumbnail( libvlc_instance_t* p_vlc )
     input_item_t* p_item = input_item_New( psz_mrl, "mock item" );
     assert( p_item != NULL );
 
-    vlc_thumbnailer_request_t* p_req = vlc_thumbnailer_RequestByTime( p_thumbnailer,
+    vlc_thumbnailer_req_id id = vlc_thumbnailer_RequestByTime( p_thumbnailer,
         VLC_TICK_INVALID, VLC_THUMBNAILER_SEEK_PRECISE, p_item,
         VLC_TICK_INVALID, thumbnailer_callback_cancel, NULL );
 
-    vlc_thumbnailer_DestroyRequest( p_thumbnailer, p_req );
+    vlc_thumbnailer_Cancel( p_thumbnailer, id );
 
     /* Check that thumbnailer_callback_cancel is not called, even after the
      * normal termination of the parsing. */



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b38a4eb4ee57936a93df5a85ed0fdd7807e5f799...da2ff179f88fd9cd06f64cea38276dc4976a4240

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