Browse Source

preparser: add vlc_preparser_req_Release API

Explicit API to release vlc_preparser_req* from user side.
Safe to call this from within the on_ended callback.
pull/188/head
Ayush Dey 10 months ago
committed by Steve Lhomme
parent
commit
52c61546c2
  1. 26
      include/vlc_preparser.h
  2. 5
      lib/media.c
  3. 1
      modules/gui/qt/player/player_controller.cpp
  4. 3
      modules/misc/medialibrary/Thumbnailer.cpp
  5. 1
      src/libvlccore.sym
  6. 1
      src/media_source/media_tree.c
  7. 1
      src/playlist/preparse.c
  8. 37
      src/preparser/preparser.c
  9. 4
      test/libvlc/media.c
  10. 4
      test/src/preparser/thumbnail.c
  11. 3
      test/src/preparser/thumbnail_to_files.c

26
include/vlc_preparser.h

@ -49,6 +49,13 @@ typedef struct vlc_preparser_t vlc_preparser_t;
* Identifies a request submitted via vlc_preparser_Push(),
* vlc_preparser_GenerateThumbnail(), or vlc_preparser_GenerateThumbnailToFiles().
* It can be passed to vlc_preparser_Cancel() to cancel that request.
*
* @note
* - Validity starts when a submit function returns a non-NULL handle and ends
* with vlc_preparser_req_Release().
*
* - The user must ensure that callbacks and their context remain valid
* until request termination.
*/
typedef struct vlc_preparser_req vlc_preparser_req;
@ -426,6 +433,25 @@ VLC_API size_t vlc_preparser_Cancel( vlc_preparser_t *preparser,
*/
VLC_API input_item_t *vlc_preparser_req_GetItem(vlc_preparser_req *req);
/**
* Release a preparser request handle.
*
* @param req the preparser request handle
*
* @note
* - The request handle is retained when returned by a submit function.
*
* - Mandatory to call to avoid memory leaks.
*
* - It is safe to call this API from within the on_ended callback.
*
* - The request handle should not be used after calling this function.
*
* - If called on an active request, it doesn't cancel the preparsing request,
* use vlc_preparser_Cancel() for that.
*/
VLC_API void vlc_preparser_req_Release( vlc_preparser_req *req );
/**
* This function destroys the preparser object and thread.
*

5
lib/media.c

@ -307,7 +307,6 @@ static void send_parsed_changed( libvlc_media_t *p_md,
static void input_item_preparse_ended(vlc_preparser_req *req,
int status, void *user_data)
{
VLC_UNUSED(req);
libvlc_media_t * p_md = user_data;
libvlc_media_parsed_status_t new_status;
@ -329,6 +328,7 @@ static void input_item_preparse_ended(vlc_preparser_req *req,
vlc_assert_unreachable();
}
send_parsed_changed( p_md, new_status );
vlc_preparser_req_Release( req );
p_md->req = NULL;
if (atomic_fetch_sub_explicit(&p_md->worker_count, 1,
@ -934,7 +934,6 @@ struct libvlc_media_thumbnail_request_t
static void media_on_thumbnail_ready( vlc_preparser_req *request, int status,
picture_t* thumbnail, void* data )
{
(void) request;
(void) status;
libvlc_media_thumbnail_request_t *req = data;
@ -950,6 +949,8 @@ static void media_on_thumbnail_ready( vlc_preparser_req *request, int status,
libvlc_event_send( &p_media->event_manager, &event );
if ( pic != NULL )
libvlc_picture_release( pic );
vlc_preparser_req_Release( request );
}
// Start an asynchronous thumbnail generation

1
modules/gui/qt/player/player_controller.cpp

@ -1026,6 +1026,7 @@ static void on_preparse_ended_callback(vlc_preparser_req *req,
input_item_t *p_item = vlc_preparser_req_GetItem(req);
PlayerControllerPrivate *me = reinterpret_cast<PlayerControllerPrivate *>(userdata);
me->onArtFetchEnded(p_item, input_item_IsArtFetched(p_item));
vlc_preparser_req_Release(req);
}

3
modules/misc/medialibrary/Thumbnailer.cpp

@ -49,7 +49,7 @@ Thumbnailer::Thumbnailer( vlc_medialibrary_module_t* ml )
throw std::runtime_error( "Failed to instantiate a vlc_preparser_t" );
}
void Thumbnailer::onThumbnailToFilesComplete(vlc_preparser_req *, int ,
void Thumbnailer::onThumbnailToFilesComplete(vlc_preparser_req *req, int ,
const bool *result_array,
size_t result_count, void *data)
{
@ -64,6 +64,7 @@ void Thumbnailer::onThumbnailToFilesComplete(vlc_preparser_req *, int ,
}
ctx->thumbnailer->m_currentContext = nullptr;
ctx->thumbnailer->m_cond.broadcast();
vlc_preparser_req_Release( req );
}
bool Thumbnailer::generate( const medialibrary::IMedia&, const std::string& mrl,

1
src/libvlccore.sym

@ -1055,5 +1055,6 @@ vlc_preparser_GenerateThumbnail
vlc_preparser_GenerateThumbnailToFiles
vlc_preparser_Cancel
vlc_preparser_req_GetItem
vlc_preparser_req_Release
vlc_preparser_Delete
vlc_preparser_SetTimeout

1
src/media_source/media_tree.c

@ -177,6 +177,7 @@ media_subtree_preparse_ended(vlc_preparser_req *req, int status, void *user_data
}
vlc_media_tree_Notify(tree, on_preparse_end, subtree_root, status);
vlc_media_tree_Unlock(tree);
vlc_preparser_req_Release(req);
}
static inline void

1
src/playlist/preparse.c

@ -103,6 +103,7 @@ on_preparse_ended(vlc_preparser_req *req, int status, void *userdata)
vlc_playlist_Notify(playlist, on_items_updated, index,
&playlist->items.data[index], 1);
vlc_playlist_Unlock(playlist);
vlc_preparser_req_Release(req);
}
static const struct vlc_preparser_cbs preparser_callbacks = {

37
src/preparser/preparser.c

@ -87,6 +87,8 @@ struct vlc_preparser_req
struct vlc_runnable runnable; /**< to be passed to the executor */
struct vlc_list node; /**< node of vlc_preparser_t.submitted_tasks */
vlc_atomic_rc_t rc;
};
static struct vlc_preparser_req *
@ -106,6 +108,7 @@ PreparserRequestNew(vlc_preparser_t *preparser, void (*run)(void *), input_item_
req->pic = NULL;
req->outputs = NULL;
req->output_count = 0;
vlc_atomic_rc_init(&req->rc);
if (thumb_arg == NULL)
req->thumb_arg = (struct vlc_thumbnailer_arg) {
@ -220,7 +223,7 @@ OnArtFetchEnded(input_item_t *item, bool fetched, void *userdata)
struct vlc_preparser_req *req = userdata;
NotifyPreparseEnded(req);
PreparserRequestDelete(req);
vlc_preparser_req_Release(req);
}
static const input_fetcher_callbacks_t input_fetcher_callbacks = {
@ -312,7 +315,7 @@ ParserRun(void *userdata)
end:
NotifyPreparseEnded(req);
PreparserRequestDelete(req);
vlc_preparser_req_Release(req);
}
static bool
@ -429,7 +432,7 @@ error:
req->cbs.thumbnailer_to_files->on_ended(req, req->preparse_status,
NULL, 0, req->userdata);
picture_Release(pic);
PreparserRequestDelete(req);
vlc_preparser_req_Release(req);
free(result_array);
}
@ -542,7 +545,7 @@ ThumbnailerRun(void *userdata)
error:
if (req != NULL)
PreparserRequestDelete(req);
vlc_preparser_req_Release(req);
}
static void
@ -555,6 +558,13 @@ Interrupt(struct vlc_preparser_req *req)
vlc_sem_post(&req->preparse_ended);
}
static struct vlc_preparser_req *
PreparserRequestRetain(struct vlc_preparser_req *req)
{
vlc_atomic_rc_inc(&req->rc);
return req;
}
vlc_preparser_t* vlc_preparser_New( vlc_object_t *parent,
const struct vlc_preparser_cfg *cfg )
{
@ -670,11 +680,11 @@ vlc_preparser_Push( vlc_preparser_t *preparser, input_item_t *item,
vlc_executor_Submit(preparser->parser, &req->runnable);
return req;
return PreparserRequestRetain(req);
}
int ret = Fetch(req);
return ret == VLC_SUCCESS ? req : NULL;
return ret == VLC_SUCCESS ? PreparserRequestRetain(req) : NULL;
}
vlc_preparser_req *
@ -700,7 +710,7 @@ vlc_preparser_GenerateThumbnail( vlc_preparser_t *preparser, input_item_t *item,
vlc_executor_Submit(preparser->thumbnailer, &req->runnable);
return req;
return PreparserRequestRetain(req);
}
static int
@ -834,7 +844,7 @@ vlc_preparser_GenerateThumbnailToFiles( vlc_preparser_t *preparser, input_item_t
vlc_executor_Submit(preparser->thumbnailer, &req->runnable);
return req;
return PreparserRequestRetain(req);
}
size_t vlc_preparser_Cancel( vlc_preparser_t *preparser, vlc_preparser_req *req )
@ -900,7 +910,7 @@ size_t vlc_preparser_Cancel( vlc_preparser_t *preparser, vlc_preparser_req *req
NULL, 0,
req_itr->userdata);
}
PreparserRequestDelete(req_itr);
vlc_preparser_req_Release(req_itr);
/* Small optimisation in the likely case where the user cancel
* only one task */
@ -931,6 +941,15 @@ void vlc_preparser_SetTimeout( vlc_preparser_t *preparser,
preparser->timeout = timeout;
}
void vlc_preparser_req_Release( vlc_preparser_req *req )
{
assert(req != NULL);
if (!vlc_atomic_rc_dec(&req->rc))
return;
PreparserRequestDelete(req);
}
void vlc_preparser_Delete( vlc_preparser_t *preparser )
{
/* In case vlc_preparser_Deactivate() has not been called */

4
test/libvlc/media.c

@ -211,21 +211,21 @@ static void test_media_tracks(libvlc_instance_t *vlc)
static void input_item_preparse_timeout( vlc_preparser_req *req,
int status, void *user_data )
{
VLC_UNUSED(req);
vlc_sem_t *p_sem = user_data;
assert( status == VLC_ETIMEOUT );
vlc_sem_post(p_sem);
vlc_preparser_req_Release(req);
}
static void input_item_preparse_cancel( vlc_preparser_req *req,
int status, void *user_data )
{
VLC_UNUSED(req);
vlc_sem_t *p_sem = user_data;
assert( status == -EINTR );
vlc_sem_post(p_sem);
vlc_preparser_req_Release(req);
}
static void test_input_metadata_timeout(libvlc_instance_t *vlc, int timeout,

4
test/src/preparser/thumbnail.c

@ -71,7 +71,6 @@ struct test_ctx
static void thumbnailer_callback( vlc_preparser_req *req, int status,
picture_t* thumbnail, void *data )
{
(void) req;
struct test_ctx* p_ctx = data;
vlc_mutex_lock( &p_ctx->lock );
@ -113,6 +112,7 @@ static void thumbnailer_callback( vlc_preparser_req *req, int status,
p_ctx->b_done = true;
vlc_cond_signal( &p_ctx->cond );
vlc_mutex_unlock( &p_ctx->lock );
vlc_preparser_req_Release( req );
}
static void test_thumbnails( libvlc_instance_t* p_vlc )
@ -189,12 +189,12 @@ static void test_thumbnails( libvlc_instance_t* p_vlc )
static void thumbnailer_callback_cancel( vlc_preparser_req *req, int status,
picture_t* p_thumbnail, void *data )
{
(void) req;
assert( p_thumbnail == NULL );
assert( status == -EINTR );
vlc_sem_t *sem = data;
vlc_sem_post(sem);
vlc_preparser_req_Release(req);
}
static void test_cancel_thumbnail( libvlc_instance_t* p_vlc )

3
test/src/preparser/thumbnail_to_files.c

@ -112,13 +112,13 @@ static void parser_on_ended(vlc_preparser_req *req, int status, void *userdata)
assert(es_fmt->video.i_height == test_entry->out_height);
vlc_sem_post(&context->sem);
vlc_preparser_req_Release(req);
}
static void on_ended(vlc_preparser_req *req, int status,
const bool *result_array, size_t result_count, void *data)
{
struct context *context = data;
(void) req;
assert(status == VLC_SUCCESS);
assert(context->test_count == result_count);
@ -163,6 +163,7 @@ static void on_ended(vlc_preparser_req *req, int status,
input_item_Release(thumb);
}
}
vlc_preparser_req_Release(req);
}
static int get_formats(enum vlc_thumbnailer_format *out_format,

Loading…
Cancel
Save