[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