vlc | branch: master | Hugo Beauzée-Luyssen <[email protected]> | Thu Oct 4 17:10:16 2018 +0200| [946b67f964396056caba8cb3b62bdf9a976abfae] | committer: Hugo Beauzée-Luyssen
core: Add a thumbnailing API ref #17368 > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=946b67f964396056caba8cb3b62bdf9a976abfae --- include/vlc_input.h | 11 ++ include/vlc_thumbnailer.h | 133 +++++++++++++++++++++ src/Makefile.am | 2 + src/input/decoder.c | 45 +++++++- src/input/es_out.c | 5 +- src/input/input.c | 19 ++- src/input/input_internal.h | 1 + src/input/thumbnailer.c | 281 +++++++++++++++++++++++++++++++++++++++++++++ src/input/var.c | 2 + src/libvlc.c | 5 + src/libvlccore.sym | 6 + 11 files changed, 502 insertions(+), 8 deletions(-) diff --git a/include/vlc_input.h b/include/vlc_input.h index 5d9fd5fadf..713066d962 100644 --- a/include/vlc_input.h +++ b/include/vlc_input.h @@ -395,6 +395,9 @@ typedef enum input_event_type_e /* subs_fps has changed */ INPUT_EVENT_SUBS_FPS, + + /* Thumbnail generation */ + INPUT_EVENT_THUMBNAIL_READY, } input_event_type_e; #define VLC_INPUT_CAPABILITIES_SEEKABLE (1<<0) @@ -528,6 +531,8 @@ struct vlc_input_event bool vbi_transparent; /* INPUT_EVENT_SUBS_FPS */ float subs_fps; + /* INPUT_EVENT_THUMBNAIL_READY */ + picture_t *thumbnail; }; }; @@ -621,6 +626,12 @@ VLC_API input_thread_t *input_CreatePreparser(vlc_object_t *obj, void *events_data, input_item_t *item) VLC_USED; +VLC_API +input_thread_t *input_CreateThumbnailer(vlc_object_t *obj, + input_thread_events_cb events_cb, + void *events_data, input_item_t *item) +VLC_USED; + VLC_API int input_Start( input_thread_t * ); VLC_API void input_Stop( input_thread_t * ); diff --git a/include/vlc_thumbnailer.h b/include/vlc_thumbnailer.h new file mode 100644 index 0000000000..39c23cd727 --- /dev/null +++ b/include/vlc_thumbnailer.h @@ -0,0 +1,133 @@ +/***************************************************************************** + * vlc_thumbnailer.h: Thumbnailing API + ***************************************************************************** + * Copyright (C) 2018 VLC authors and VideoLAN + * + * Authors: Hugo Beauzée-Luyssen <[email protected]> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifndef VLC_THUMBNAILER_H +#define VLC_THUMBNAILER_H + +#include <vlc_common.h> + +typedef struct vlc_thumbnailer_t vlc_thumbnailer_t; +typedef struct vlc_thumbnailer_request_t vlc_thumbnailer_request_t; + +/** + * \brief vlc_thumbnailer_cb defines a callback invoked on thumbnailing completion or error + * + * This callback will always be called, provided vlc_thumbnailer_Request returned + * a non NULL request, and provided the request is not cancelled before its + * completion. + * In case of failure, p_thumbnail will be NULL. + * The picture, if any, is owned by the thumbnailer, and must be acquired by using + * \link picture_Hold \endlink to use it pass the callback's scope. + * + * \param data Is the opaque pointer passed as vlc_thumbnailer_Request last parameter + * \param thumbnail The generated thumbnail, or NULL in case of failure or timeout + */ +typedef void(*vlc_thumbnailer_cb)( void* data, picture_t* thumbnail ); + + +/** + * \brief vlc_thumbnailer_Create Creates a thumbnailer object + * \param parent A VLC object + * \return A thumbnailer object, or NULL in case of failure + */ +VLC_API vlc_thumbnailer_t* +vlc_thumbnailer_Create( vlc_object_t* p_parent ) +VLC_USED; + +enum vlc_thumbnailer_seek_speed +{ + /** Precise, but potentially slow */ + VLC_THUMBNAILER_SEEK_PRECISE, + /** Fast, but potentially imprecise */ + VLC_THUMBNAILER_SEEK_FAST, +}; + +/** + * \brief vlc_thumbnailer_RequestByTime Requests a thumbnailer at a given time + * \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 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. + * The returned request object must not be used after the callback has been + * invoked. That request object is owned by the thumbnailer, and must not be + * released. + * 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_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer, + vlc_tick_t time, + enum vlc_thumbnailer_seek_speed speed, + input_item_t *input_item, vlc_tick_t timeout, + 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 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. + * The returned request object must not be used after the callback has been + * invoked. That request object is owned by the thumbnailer, and must not be + * released. + * The provided input_item will be held by the thumbnailer and can safely be + * released after calling this function. + */ +VLC_API vlc_thumbnailer_request_t* +vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer, + float pos, + enum vlc_thumbnailer_seek_speed speed, + input_item_t *input_item, vlc_tick_t timeout, + vlc_thumbnailer_cb cb, void* user_data ); + +/** + * \brief vlc_thumbnailer_Cancel Cancel a thumbnail request + * \param thumbnailer A thumbnailer object + * \param request An opaque thumbnail request object + * + * Cancelling a request will *not* invoke the completion callback. + * The behavior is undefined if the request is cancelled after its completion. + */ +VLC_API void +vlc_thumbnailer_Cancel( vlc_thumbnailer_t* thumbnailer, + vlc_thumbnailer_request_t* request ); + +/** + * \brief vlc_thumbnailer_Release releases a thumbnailer and cancel all pending requests + * \param thumbnailer A thumbnailer object + */ +VLC_API void vlc_thumbnailer_Release( vlc_thumbnailer_t* thumbnailer ); + +#endif // VLC_THUMBNAILER_H diff --git a/src/Makefile.am b/src/Makefile.am index c64592a11b..4c7f7a6f98 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,6 +94,7 @@ pluginsinclude_HEADERS = \ ../include/vlc_threads.h \ ../include/vlc_tick.h \ ../include/vlc_timestamp_helper.h \ + ../include/vlc_thumbnailer.h \ ../include/vlc_tls.h \ ../include/vlc_url.h \ ../include/vlc_variables.h \ @@ -267,6 +268,7 @@ libvlccore_la_SOURCES = \ input/stream_filter.c \ input/stream_memory.c \ input/subtitles.c \ + input/thumbnailer.c \ input/var.c \ audio_output/aout_internal.h \ audio_output/common.c \ diff --git a/src/input/decoder.c b/src/input/decoder.c index 7ca4c87fcf..5ce154678e 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -1210,6 +1210,37 @@ static void DecoderQueueVideo( decoder_t *p_dec, picture_t *p_pic ) p_owner->pf_update_stat( p_owner, 1, i_lost ); } +static int thumbnailer_update_format( decoder_t *p_dec ) +{ + VLC_UNUSED(p_dec); + return 0; +} + +static picture_t *thumbnailer_buffer_new( decoder_t *p_dec ) +{ + struct decoder_owner *p_owner = dec_get_owner( p_dec ); + /* Avoid decoding more than one frame when a thumbnail was + * already generated */ + if( !p_owner->b_first ) + return NULL; + return picture_NewFromFormat( &p_dec->fmt_out.video ); +} + +static void DecoderQueueThumbnail( decoder_t *p_dec, picture_t *p_pic ) +{ + struct decoder_owner *p_owner = dec_get_owner( p_dec ); + if( p_owner->b_first ) + { + input_SendEvent(p_owner->p_input, &(struct vlc_input_event) { + .type = INPUT_EVENT_THUMBNAIL_READY, + .thumbnail = p_pic + }); + p_owner->b_first = false; + } + picture_Release( p_pic ); + +} + static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio, unsigned *restrict pi_lost_sum ) { @@ -1779,6 +1810,15 @@ static const struct decoder_owner_callbacks dec_video_cbs = }, .get_attachments = DecoderGetInputAttachments, }; +static const struct decoder_owner_callbacks dec_thumbnailer_cbs = +{ + .video = { + .format_update = thumbnailer_update_format, + .buffer_new = thumbnailer_buffer_new, + .queue = DecoderQueueThumbnail, + }, + .get_attachments = DecoderGetInputAttachments, +}; static const struct decoder_owner_callbacks dec_audio_cbs = { .audio = { @@ -1894,7 +1934,10 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent, switch( fmt->i_cat ) { case VIDEO_ES: - p_dec->cbs = &dec_video_cbs; + if( !input_priv( p_input )->b_thumbnailing ) + p_dec->cbs = &dec_video_cbs; + else + p_dec->cbs = &dec_thumbnailer_cbs; p_owner->pf_update_stat = DecoderUpdateStatVideo; break; case AUDIO_ES: diff --git a/src/input/es_out.c b/src/input/es_out.c index 21ba6137eb..0cdd08cfe2 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -1821,6 +1821,7 @@ static void EsOutSelectEs( es_out_t *out, es_out_id_t *es ) { es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out); input_thread_t *p_input = p_sys->p_input; + bool b_thumbnailing = input_priv(p_input)->b_thumbnailing; if( EsIsSelected( es ) ) { @@ -1859,7 +1860,7 @@ static void EsOutSelectEs( es_out_t *out, es_out_id_t *es ) } else if( es->fmt.i_cat == AUDIO_ES ) { - if( !var_GetBool( p_input, b_sout ? "sout-audio" : "audio" ) ) + if( !var_GetBool( p_input, b_sout ? "sout-audio" : "audio" ) || b_thumbnailing ) { msg_Dbg( p_input, "audio is disabled, not selecting ES 0x%x", es->fmt.i_id ); @@ -1868,7 +1869,7 @@ static void EsOutSelectEs( es_out_t *out, es_out_id_t *es ) } if( es->fmt.i_cat == SPU_ES ) { - if( !var_GetBool( p_input, b_sout ? "sout-spu" : "spu" ) ) + if( !var_GetBool( p_input, b_sout ? "sout-spu" : "spu" ) || b_thumbnailing ) { msg_Dbg( p_input, "spu is disabled, not selecting ES 0x%x", es->fmt.i_id ); diff --git a/src/input/input.c b/src/input/input.c index 7265ac6cd6..6999d75eb5 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -63,7 +63,7 @@ static void *Run( void * ); static void *Preparse( void * ); static input_thread_t * Create ( vlc_object_t *, input_thread_events_cb, void *, - input_item_t *, const char *, bool, + input_item_t *, const char *, bool, bool, input_resource_t *, vlc_renderer_item_t * ); static int Init ( input_thread_t *p_input ); static void End ( input_thread_t *p_input ); @@ -132,7 +132,7 @@ input_thread_t *input_Create( vlc_object_t *p_parent, vlc_renderer_item_t *p_renderer ) { return Create( p_parent, events_cb, events_data, p_item, psz_log, false, - p_resource, p_renderer ); + false, p_resource, p_renderer ); } #undef input_Read @@ -147,7 +147,7 @@ int input_Read( vlc_object_t *p_parent, input_item_t *p_item, input_thread_events_cb events_cb, void *events_data ) { input_thread_t *p_input = Create( p_parent, events_cb, events_data, p_item, - NULL, false, NULL, NULL ); + NULL, false, false, NULL, NULL ); if( !p_input ) return VLC_EGENERIC; @@ -165,7 +165,14 @@ input_thread_t *input_CreatePreparser( vlc_object_t *parent, input_thread_events_cb events_cb, void *events_data, input_item_t *item ) { - return Create( parent, events_cb, events_data, item, NULL, true, NULL, NULL ); + return Create( parent, events_cb, events_data, item, NULL, true, false, NULL, NULL ); +} + +input_thread_t *input_CreateThumbnailer(vlc_object_t *obj, + input_thread_events_cb events_cb, + void *events_data, input_item_t *item) +{ + return Create( obj, events_cb, events_data, item, NULL, false, true, NULL, NULL ); } /** @@ -308,7 +315,8 @@ input_item_t *input_GetItem( input_thread_t *p_input ) static input_thread_t *Create( vlc_object_t *p_parent, input_thread_events_cb events_cb, void *events_data, input_item_t *p_item, const char *psz_header, - bool b_preparsing, input_resource_t *p_resource, + bool b_preparsing, bool b_thumbnailing, + input_resource_t *p_resource, vlc_renderer_item_t *p_renderer ) { /* Allocate descriptor */ @@ -345,6 +353,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, priv->is_running = false; priv->is_stopped = false; priv->b_recording = false; + priv->b_thumbnailing = b_thumbnailing; priv->i_rate = INPUT_RATE_DEFAULT; memset( &priv->bookmark, 0, sizeof(priv->bookmark) ); TAB_INIT( priv->i_bookmark, priv->pp_bookmark ); diff --git a/src/input/input_internal.h b/src/input/input_internal.h index 95d09528cf..82eb5f64bd 100644 --- a/src/input/input_internal.h +++ b/src/input/input_internal.h @@ -132,6 +132,7 @@ typedef struct input_thread_private_t bool is_running; bool is_stopped; bool b_recording; + bool b_thumbnailing; int i_rate; /* Playtime configuration and state */ diff --git a/src/input/thumbnailer.c b/src/input/thumbnailer.c new file mode 100644 index 0000000000..bd10032d53 --- /dev/null +++ b/src/input/thumbnailer.c @@ -0,0 +1,281 @@ +/***************************************************************************** + * thumbnailer.c: Thumbnailing API + ***************************************************************************** + * Copyright (C) 2018 VLC authors and VideoLAN + * + * Authors: Hugo Beauzée-Luyssen <[email protected]> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vlc_thumbnailer.h> +#include <vlc_input.h> +#include "misc/background_worker.h" + +struct vlc_thumbnailer_t +{ + vlc_object_t* parent; + struct background_worker* worker; +}; + +typedef struct vlc_thumbnailer_params_t +{ + union + { + vlc_tick_t time; + float pos; + }; + enum + { + VLC_THUMBNAILER_SEEK_TIME, + VLC_THUMBNAILER_SEEK_POS, + } type; + bool fast_seek; + input_item_t* input_item; + /** + * A positive value will be used as the timeout duration + * VLC_TICK_INVALID means no timeout + */ + vlc_tick_t timeout; + vlc_thumbnailer_cb cb; + void* user_data; +} vlc_thumbnailer_params_t; + +struct vlc_thumbnailer_request_t +{ + vlc_thumbnailer_t *thumbnailer; + input_thread_t *input_thread; + + vlc_thumbnailer_params_t params; + + vlc_mutex_t lock; + bool done; +}; + +static void +on_thumbnailer_input_event( input_thread_t *input, + const struct vlc_input_event *event, void *userdata ) +{ + VLC_UNUSED(input); + if ( event->type != INPUT_EVENT_THUMBNAIL_READY && + ( event->type != INPUT_EVENT_STATE || ( event->state != ERROR_S && + event->state != END_S ) ) ) + return; + + vlc_thumbnailer_request_t* request = userdata; + picture_t *pic = NULL; + + if ( event->type == INPUT_EVENT_THUMBNAIL_READY ) + { + /* + * Stop the input thread ASAP, delegate its release to + * thumbnailer_request_Release + */ + input_Stop( request->input_thread ); + pic = event->thumbnail; + } + vlc_mutex_lock( &request->lock ); + request->done = true; + /* + * If the request has not been cancelled, we can invoke the completion + * callback. + */ + if ( request->params.cb ) + { + request->params.cb( request->params.user_data, pic ); + request->params.cb = NULL; + } + vlc_mutex_unlock( &request->lock ); + background_worker_RequestProbe( request->thumbnailer->worker ); +} + +static void thumbnailer_request_Hold( void* data ) +{ + VLC_UNUSED(data); +} + +static void thumbnailer_request_Release( void* data ) +{ + vlc_thumbnailer_request_t* request = data; + if ( request->input_thread ) + input_Close( request->input_thread ); + + input_item_Release( request->params.input_item ); + vlc_mutex_destroy( &request->lock ); + free( request ); +} + +static int thumbnailer_request_Start( void* owner, void* entity, void** out ) +{ + vlc_thumbnailer_t* thumbnailer = owner; + vlc_thumbnailer_request_t* request = entity; + input_thread_t* input = request->input_thread = + input_CreateThumbnailer( thumbnailer->parent, + on_thumbnailer_input_event, request, + request->params.input_item ); + if ( unlikely( input == NULL ) ) + return VLC_EGENERIC; + if ( request->params.type == VLC_THUMBNAILER_SEEK_TIME ) + { + input_SetTime( input, request->params.time, + request->params.fast_seek ); + } + else + { + assert( request->params.type == VLC_THUMBNAILER_SEEK_POS ); + input_SetPosition( input, request->params.pos, + request->params.fast_seek ); + } + if ( input_Start( input ) != VLC_SUCCESS ) + return VLC_EGENERIC; + *out = request; + return VLC_SUCCESS; +} + +static void thumbnailer_request_Stop( void* owner, void* handle ) +{ + VLC_UNUSED(owner); + + vlc_thumbnailer_request_t *request = handle; + vlc_mutex_lock( &request->lock ); + /* + * If the callback hasn't been invoked yet, we assume a timeout and + * signal it back to the user + */ + if ( request->params.cb != NULL ) + { + request->params.cb( request->params.user_data, NULL ); + request->params.cb = NULL; + } + vlc_mutex_unlock( &request->lock ); + assert( request->input_thread != NULL ); + input_Stop( request->input_thread ); +} + +static int thumbnailer_request_Probe( void* owner, void* handle ) +{ + VLC_UNUSED(owner); + vlc_thumbnailer_request_t *request = handle; + vlc_mutex_lock( &request->lock ); + int res = request->done; + vlc_mutex_unlock( &request->lock ); + return res; +} + +static vlc_thumbnailer_request_t* +thumbnailer_RequestCommon( vlc_thumbnailer_t* thumbnailer, + const vlc_thumbnailer_params_t* params ) +{ + vlc_thumbnailer_request_t *request = malloc( sizeof( *request ) ); + if ( unlikely( request == NULL ) ) + return NULL; + request->thumbnailer = thumbnailer; + request->input_thread = NULL; + request->params = *(vlc_thumbnailer_params_t*)params; + request->done = false; + input_item_Hold( request->params.input_item ); + vlc_mutex_init( &request->lock ); + + int timeout = params->timeout == VLC_TICK_INVALID ? + 0 : MS_FROM_VLC_TICK( params->timeout ); + if ( background_worker_Push( thumbnailer->worker, request, request, + timeout ) != VLC_SUCCESS ) + { + thumbnailer_request_Release( request ); + return NULL; + } + return request; +} + +vlc_thumbnailer_request_t* +vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer, + vlc_tick_t time, + enum vlc_thumbnailer_seek_speed speed, + input_item_t *input_item, vlc_tick_t timeout, + vlc_thumbnailer_cb cb, void* user_data ) +{ + return thumbnailer_RequestCommon( thumbnailer, + &(const vlc_thumbnailer_params_t){ + .time = time, + .type = VLC_THUMBNAILER_SEEK_TIME, + .fast_seek = speed == VLC_THUMBNAILER_SEEK_FAST, + .input_item = input_item, + .timeout = timeout, + .cb = cb, + .user_data = user_data, + }); +} + +vlc_thumbnailer_request_t* +vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer, + float pos, enum vlc_thumbnailer_seek_speed speed, + input_item_t *input_item, vlc_tick_t timeout, + vlc_thumbnailer_cb cb, void* user_data ) +{ + return thumbnailer_RequestCommon( thumbnailer, + &(const vlc_thumbnailer_params_t){ + .pos = pos, + .type = VLC_THUMBNAILER_SEEK_POS, + .fast_seek = speed == VLC_THUMBNAILER_SEEK_FAST, + .input_item = input_item, + .timeout = timeout, + .cb = cb, + .user_data = user_data, + }); +} + +void vlc_thumbnailer_Cancel( vlc_thumbnailer_t* thumbnailer, + vlc_thumbnailer_request_t* req ) +{ + vlc_mutex_lock( &req->lock ); + /* Ensure we won't invoke the callback if the input was running. */ + req->params.cb = NULL; + vlc_mutex_unlock( &req->lock ); + background_worker_Cancel( thumbnailer->worker, req ); +} + +vlc_thumbnailer_t *vlc_thumbnailer_Create( vlc_object_t* parent) +{ + vlc_thumbnailer_t *thumbnailer = malloc( sizeof( *thumbnailer ) ); + if ( unlikely( thumbnailer == NULL ) ) + return NULL; + thumbnailer->parent = parent; + struct background_worker_config cfg = { + .default_timeout = -1, + .max_threads = 1, + .pf_release = thumbnailer_request_Release, + .pf_hold = thumbnailer_request_Hold, + .pf_start = thumbnailer_request_Start, + .pf_probe = thumbnailer_request_Probe, + .pf_stop = thumbnailer_request_Stop, + }; + thumbnailer->worker = background_worker_New( thumbnailer, &cfg ); + if ( unlikely( thumbnailer->worker == NULL ) ) + { + free( thumbnailer ); + return NULL; + } + return thumbnailer; +} + +void vlc_thumbnailer_Release( vlc_thumbnailer_t *thumbnailer ) +{ + background_worker_Delete( thumbnailer->worker ); + free( thumbnailer ); +} diff --git a/src/input/var.c b/src/input/var.c index 895e373b23..6038c883c1 100644 --- a/src/input/var.c +++ b/src/input/var.c @@ -425,6 +425,8 @@ void input_LegacyEvents( input_thread_t *p_input, break; case INPUT_EVENT_SUBITEMS: break; + case INPUT_EVENT_THUMBNAIL_READY: + break; } Trigger( p_input, event->type ); } diff --git a/src/libvlc.c b/src/libvlc.c index f12f980936..18d55004d1 100644 --- a/src/libvlc.c +++ b/src/libvlc.c @@ -63,6 +63,7 @@ #include <vlc_url.h> #include <vlc_modules.h> #include <vlc_media_library.h> +#include <vlc_thumbnailer.h> #include "libvlc.h" #include "playlist/playlist_internal.h" @@ -225,6 +226,10 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, msg_Warn( p_libvlc, "Media library initialization failed" ); } + priv->p_thumbnailer = vlc_thumbnailer_Create( VLC_OBJECT( p_libvlc ) ); + if ( priv->p_thumbnailer == NULL ) + msg_Warn( p_libvlc, "Failed to instantiate VLC thumbnailer" ); + /* * Initialize hotkey handling */ diff --git a/src/libvlccore.sym b/src/libvlccore.sym index c1b2b1ea7b..c87f11c69f 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -155,6 +155,7 @@ input_Control input_Create input_CreateFilename input_CreatePreparser +input_CreateThumbnailer input_DecoderCreate input_DecoderDelete input_DecoderDecode @@ -786,3 +787,8 @@ vlc_es_id_Hold vlc_es_id_Release vlc_es_id_GetInputId vlc_es_id_GetCat +vlc_thumbnailer_Create +vlc_thumbnailer_RequestByTime +vlc_thumbnailer_RequestByPos +vlc_thumbnailer_Cancel +vlc_thumbnailer_Release _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
