Browse Source

thumbnailer: use a struct for seek arguments

And merge vlc_thumbnailer_RequestByTime and vlc_thumbnailer_RequestByPos
into vlc_thumbnailer_Request.
pull/171/head
Thomas Guillem 2 years ago
committed by Steve Lhomme
parent
commit
bb94b3b123
  1. 68
      include/vlc_thumbnailer.h
  2. 78
      lib/media.c
  3. 10
      modules/misc/medialibrary/Thumbnailer.cpp
  4. 75
      src/input/thumbnailer.c
  5. 3
      src/libvlccore.sym
  6. 25
      test/src/input/thumbnail.c

68
include/vlc_thumbnailer.h

@ -56,20 +56,40 @@ typedef void(*vlc_thumbnailer_cb)( void* data, picture_t* thumbnail );
VLC_API vlc_thumbnailer_t*
vlc_thumbnailer_Create(vlc_object_t* parent, vlc_tick_t timeout) VLC_USED;
enum vlc_thumbnailer_seek_speed
/**
* Thumbnailer seek argument
*/
struct vlc_thumbnailer_seek_arg
{
/** Precise, but potentially slow */
VLC_THUMBNAILER_SEEK_PRECISE,
/** Fast, but potentially imprecise */
VLC_THUMBNAILER_SEEK_FAST,
enum
{
/** Seek by time */
VLC_THUMBNAILER_SEEK_TIME,
/** Seek by position */
VLC_THUMBNAILER_SEEK_POS,
} type;
union
{
/** Seek time if type == VLC_THUMBNAILER_SEEK_TIME */
vlc_tick_t time;
/** Seek position if type == VLC_THUMBNAILER_SEEK_POS */
double pos;
};
enum
{
/** Precise, but potentially slow */
VLC_THUMBNAILER_SEEK_PRECISE,
/** Fast, but potentially imprecise */
VLC_THUMBNAILER_SEEK_FAST,
} speed;
};
/**
* \brief vlc_thumbnailer_RequestByTime Requests a thumbnailer at a given time
* \brief vlc_thumbnailer_Request Requests a thumbnailer
* \param thumbnailer A thumbnailer object
* \param time The time at which the thumbnail should be taken
* \param speed The seeking speed \sa{enum vlc_thumbnailer_seek_speed}
* \param input_item The input item to generate the thumbnail for
* \param seek_arg pointer to a seek struct, that tell at which time the
* thumbnail should be taken
* \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
@ -82,34 +102,10 @@ enum vlc_thumbnailer_seek_speed
* released safely after calling this function.
*/
VLC_API vlc_thumbnailer_req_id
vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
vlc_tick_t time,
enum vlc_thumbnailer_seek_speed speed,
input_item_t *input_item,
vlc_thumbnailer_cb cb, void* user_data );
/**
* \brief vlc_thumbnailer_RequestByTime Requests a thumbnailer at a given time
* \param thumbnailer A thumbnailer object
* \param pos The position at which the thumbnail should be taken
* \param speed The seeking speed \sa{enum vlc_thumbnailer_seek_speed}
* \param input_item The input item to generate the thumbnail for
* \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 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 safely after calling this function.
*/
VLC_API vlc_thumbnailer_req_id
vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
double pos,
enum vlc_thumbnailer_seek_speed speed,
input_item_t *input_item,
vlc_thumbnailer_cb cb, void* user_data );
vlc_thumbnailer_Request( vlc_thumbnailer_t *thumbnailer,
input_item_t *input_item,
const struct vlc_thumbnailer_seek_arg *seek_arg,
vlc_thumbnailer_cb cb, void* user_data );
/**
* \brief vlc_thumbnailer_Camcel Cancel a thumbnail request

78
lib/media.c

@ -945,13 +945,13 @@ static void media_on_thumbnail_ready( void* data, picture_t* thumbnail )
}
// Start an asynchronous thumbnail generation
libvlc_media_thumbnail_request_t*
libvlc_media_thumbnail_request_by_time( libvlc_instance_t *inst,
libvlc_media_t *md, libvlc_time_t time,
libvlc_thumbnailer_seek_speed_t speed,
unsigned int width, unsigned int height,
bool crop, libvlc_picture_type_t picture_type,
libvlc_time_t timeout )
static libvlc_media_thumbnail_request_t*
libvlc_media_thumbnail_request( libvlc_instance_t *inst,
libvlc_media_t *md,
const struct vlc_thumbnailer_seek_arg *seek_arg,
unsigned int width, unsigned int height,
bool crop, libvlc_picture_type_t picture_type,
libvlc_time_t timeout )
{
assert( md );
@ -972,12 +972,8 @@ libvlc_media_thumbnail_request_by_time( libvlc_instance_t *inst,
req->type = picture_type;
req->crop = crop;
libvlc_media_retain( md );
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,
media_on_thumbnail_ready, req );
req->id = vlc_thumbnailer_Request( thumb, md->p_input_item, seek_arg,
media_on_thumbnail_ready, req );
if ( req->id == VLC_PREPARSER_REQ_ID_INVALID )
{
free( req );
@ -988,6 +984,24 @@ libvlc_media_thumbnail_request_by_time( libvlc_instance_t *inst,
return req;
}
libvlc_media_thumbnail_request_t*
libvlc_media_thumbnail_request_by_time( libvlc_instance_t *inst,
libvlc_media_t *md, libvlc_time_t time,
libvlc_thumbnailer_seek_speed_t speed,
unsigned int width, unsigned int height,
bool crop, libvlc_picture_type_t picture_type,
libvlc_time_t timeout )
{
const struct vlc_thumbnailer_seek_arg seek_arg = {
.type = VLC_THUMBNAILER_SEEK_TIME,
.time = vlc_tick_from_libvlc_time( time ),
.speed = speed == libvlc_media_thumbnail_seek_fast ?
VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
};
return libvlc_media_thumbnail_request( inst, md, &seek_arg, width, height,
crop, picture_type, timeout );
}
// Start an asynchronous thumbnail generation
libvlc_media_thumbnail_request_t*
libvlc_media_thumbnail_request_by_pos( libvlc_instance_t *inst,
@ -997,38 +1011,14 @@ libvlc_media_thumbnail_request_by_pos( libvlc_instance_t *inst,
bool crop, libvlc_picture_type_t picture_type,
libvlc_time_t timeout )
{
assert( md );
vlc_thumbnailer_t *thumb = libvlc_get_thumbnailer(inst);
if (unlikely(thumb == NULL))
return NULL;
vlc_thumbnailer_SetTimeout( thumb, vlc_tick_from_libvlc_time( timeout ) );
libvlc_media_thumbnail_request_t *req = malloc( sizeof( *req ) );
if ( unlikely( req == NULL ) )
return NULL;
req->instance = inst;
req->md = md;
req->width = width;
req->height = height;
req->crop = crop;
req->type = picture_type;
libvlc_media_retain( md );
req->id = vlc_thumbnailer_RequestByPos( thumb, pos,
speed == libvlc_media_thumbnail_seek_fast ?
const struct vlc_thumbnailer_seek_arg seek_arg = {
.type = VLC_THUMBNAILER_SEEK_POS,
.pos = pos,
.speed = speed == libvlc_media_thumbnail_seek_fast ?
VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
md->p_input_item,
media_on_thumbnail_ready, req );
if ( req->id == VLC_PREPARSER_REQ_ID_INVALID )
{
free( req );
libvlc_media_release( md );
return NULL;
}
libvlc_retain(inst);
return req;
};
return libvlc_media_thumbnail_request( inst, md, &seek_arg, width, height,
crop, picture_type, timeout );
}
// Destroy a thumbnail request

10
modules/misc/medialibrary/Thumbnailer.cpp

@ -71,10 +71,14 @@ bool Thumbnailer::generate( const medialibrary::IMedia&, const std::string& mrl,
{
vlc::threads::mutex_locker lock( m_mutex );
m_currentContext = &ctx;
struct vlc_thumbnailer_seek_arg seek_arg = {
.type = vlc_thumbnailer_seek_arg::VLC_THUMBNAILER_SEEK_POS,
.pos = position,
.speed = vlc_thumbnailer_seek_arg::VLC_THUMBNAILER_SEEK_FAST,
};
vlc_thumbnailer_req_id requestId =
vlc_thumbnailer_RequestByPos( m_thumbnailer.get(), position,
VLC_THUMBNAILER_SEEK_FAST, item.get(),
&onThumbnailComplete, &ctx );
vlc_thumbnailer_Request( m_thumbnailer.get(), item.get(), &seek_arg,
&onThumbnailComplete, &ctx );
if (requestId == VLC_THUMBNAILER_REQ_ID_INVALID)
{

75
src/input/thumbnailer.c

@ -41,26 +41,11 @@ struct vlc_thumbnailer_t
struct vlc_list submitted_tasks; /**< list of struct task */
};
struct seek_target
{
enum
{
VLC_THUMBNAILER_SEEK_TIME,
VLC_THUMBNAILER_SEEK_POS,
} type;
union
{
vlc_tick_t time;
double pos;
};
};
typedef struct task
{
vlc_thumbnailer_t *thumbnailer;
struct seek_target seek_target;
bool fast_seek;
struct vlc_thumbnailer_seek_arg seek_arg;
input_item_t *item;
vlc_thumbnailer_cb cb;
void* userdata;
@ -83,7 +68,7 @@ static void RunnableRun(void *);
static task_t *
TaskNew(vlc_thumbnailer_t *thumbnailer, input_item_t *item,
struct seek_target seek_target, bool fast_seek,
const struct vlc_thumbnailer_seek_arg *seek_arg,
vlc_thumbnailer_cb cb, void *userdata)
{
task_t *task = malloc(sizeof(*task));
@ -92,8 +77,8 @@ TaskNew(vlc_thumbnailer_t *thumbnailer, input_item_t *item,
task->thumbnailer = thumbnailer;
task->item = item;
task->seek_target = seek_target;
task->fast_seek = fast_seek;
task->seek_arg = *seek_arg;
task->cb = cb;
task->userdata = userdata;
@ -178,12 +163,16 @@ RunnableRun(void *userdata)
if (!input)
goto error;
if (task->seek_target.type == VLC_THUMBNAILER_SEEK_TIME)
input_SetTime(input, task->seek_target.time, task->fast_seek);
assert(task->seek_arg.speed == VLC_THUMBNAILER_SEEK_PRECISE
|| task->seek_arg.speed == VLC_THUMBNAILER_SEEK_FAST);
bool fast_seek = task->seek_arg.speed == VLC_THUMBNAILER_SEEK_FAST;
if (task->seek_arg.type == VLC_THUMBNAILER_SEEK_TIME)
input_SetTime(input, task->seek_arg.time, fast_seek);
else
{
assert(task->seek_target.type == VLC_THUMBNAILER_SEEK_POS);
input_SetPosition(input, task->seek_target.pos, task->fast_seek);
assert(task->seek_arg.type == VLC_THUMBNAILER_SEEK_POS);
input_SetPosition(input, task->seek_arg.pos, fast_seek);
}
int ret = input_Start(input);
@ -228,14 +217,13 @@ error:
TaskDestroy(task);
}
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_thumbnailer_cb cb, void *userdata)
vlc_thumbnailer_req_id
vlc_thumbnailer_Request( vlc_thumbnailer_t *thumbnailer,
input_item_t *item,
const struct vlc_thumbnailer_seek_arg *seek_arg,
vlc_thumbnailer_cb cb, void* userdata )
{
bool fast_seek = speed == VLC_THUMBNAILER_SEEK_FAST;
task_t *task = TaskNew(thumbnailer, item, seek_target, fast_seek, cb,
userdata);
task_t *task = TaskNew(thumbnailer, item, seek_arg, cb, userdata);
if (!task)
return 0;
@ -252,33 +240,6 @@ RequestCommon(vlc_thumbnailer_t *thumbnailer, struct seek_target seek_target,
return id;
}
vlc_thumbnailer_req_id
vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
vlc_tick_t time,
enum vlc_thumbnailer_seek_speed speed,
input_item_t *item,
vlc_thumbnailer_cb cb, void* userdata )
{
struct seek_target seek_target = {
.type = VLC_THUMBNAILER_SEEK_TIME,
.time = time,
};
return RequestCommon(thumbnailer, seek_target, speed, item, cb, userdata);
}
vlc_thumbnailer_req_id
vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
double pos, enum vlc_thumbnailer_seek_speed speed,
input_item_t *item,
vlc_thumbnailer_cb cb, void* userdata )
{
struct seek_target seek_target = {
.type = VLC_THUMBNAILER_SEEK_POS,
.pos = pos,
};
return RequestCommon(thumbnailer, seek_target, speed, item, cb, userdata);
}
size_t vlc_thumbnailer_Cancel( vlc_thumbnailer_t* thumbnailer, vlc_thumbnailer_req_id id )
{
vlc_mutex_lock(&thumbnailer->lock);

3
src/libvlccore.sym

@ -831,8 +831,7 @@ vlc_es_id_GetStrId
vlc_es_id_IsStrIdStable
vlc_encoder_Destroy
vlc_thumbnailer_Create
vlc_thumbnailer_RequestByTime
vlc_thumbnailer_RequestByPos
vlc_thumbnailer_Request
vlc_thumbnailer_Cancel
vlc_thumbnailer_Delete
vlc_thumbnailer_SetTimeout

25
test/src/input/thumbnail.c

@ -137,20 +137,23 @@ static void test_thumbnails( libvlc_instance_t* p_vlc )
vlc_mutex_lock( &ctx.lock );
vlc_thumbnailer_req_id id;
struct vlc_thumbnailer_seek_arg seek_arg;
if ( test_params[i].b_use_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, thumbnailer_callback, &ctx );
seek_arg.type = VLC_THUMBNAILER_SEEK_POS;
seek_arg.pos = test_params[i].f_pos;
seek_arg.speed = test_params[i].b_fast_seek ?
VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE;
}
else
{
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, thumbnailer_callback, &ctx );
seek_arg.type = VLC_THUMBNAILER_SEEK_TIME;
seek_arg.time = test_params[i].i_time;
seek_arg.speed = test_params[i].b_fast_seek ?
VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE;
}
id = vlc_thumbnailer_Request( p_thumbnailer, p_item, &seek_arg,
thumbnailer_callback, &ctx );
assert( id != VLC_THUMBNAILER_REQ_ID_INVALID );
while ( ctx.b_done == false )
@ -185,9 +188,9 @@ 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_req_id id = vlc_thumbnailer_RequestByTime( p_thumbnailer,
VLC_TICK_INVALID, VLC_THUMBNAILER_SEEK_PRECISE, p_item,
thumbnailer_callback_cancel, NULL );
vlc_thumbnailer_req_id id =
vlc_thumbnailer_Request( p_thumbnailer, p_item, NULL,
thumbnailer_callback_cancel, NULL );
vlc_thumbnailer_Cancel( p_thumbnailer, id );

Loading…
Cancel
Save