From: Laurent Aimar Date: Fri, 31 Jul 2009 22:06:41 +0000 (+0200) Subject: Moved out snapshot code to a standalone file. X-Git-Tag: 1.1.0-ff~4647 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=a7a12139a54c29083e6b73f6fde96c7f673482df;p=vlc Moved out snapshot code to a standalone file. --- diff --git a/src/Makefile.am b/src/Makefile.am index 5397b55929..f4f52afb8c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -344,6 +344,8 @@ SOURCES_libvlc_common = \ input/stream_memory.c \ input/subtitles.c \ input/var.c \ + video_output/snapshot.c \ + video_output/snapshot.h \ video_output/video_output.c \ video_output/vout_pictures.c \ video_output/vout_pictures.h \ diff --git a/src/video_output/snapshot.c b/src/video_output/snapshot.c new file mode 100644 index 0000000000..f6beb19a79 --- /dev/null +++ b/src/video_output/snapshot.c @@ -0,0 +1,297 @@ +/***************************************************************************** + * snapshot.c : vout internal snapshot + ***************************************************************************** + * Copyright (C) 2009 Laurent Aimar + * $Id$ + * + * Authors: Gildas Bazin + * Laurent Aimar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 +#include +#include +#include + +#include "snapshot.h" + +#include +#include +#include +#include + +/* */ +void vout_snapshot_Init(vout_snapshot_t *snap) +{ + vlc_mutex_init(&snap->lock); + vlc_cond_init(&snap->wait); + + snap->is_available = true; + snap->request_count = 0; + snap->picture = NULL; +} +void vout_snapshot_Clean(vout_snapshot_t *snap) +{ + picture_t *picture = snap->picture; + while (picture) { + picture_t *next = picture->p_next; + picture_Release(picture); + picture = next; + } + + vlc_cond_destroy(&snap->wait); + vlc_mutex_destroy(&snap->lock); +} + +void vout_snapshot_End(vout_snapshot_t *snap) +{ + vlc_mutex_lock(&snap->lock); + + snap->is_available = false; + + vlc_cond_broadcast(&snap->wait); + vlc_mutex_unlock(&snap->lock); +} + +/* */ +picture_t *vout_snapshot_Get(vout_snapshot_t *snap, mtime_t timeout) +{ + vlc_mutex_lock(&snap->lock); + + /* */ + snap->request_count++; + + /* */ + const mtime_t deadline = mdate() + timeout; + while (snap->is_available && !snap->picture && mdate() < deadline) + vlc_cond_timedwait(&snap->wait, &snap->lock, deadline); + + /* */ + picture_t *picture = snap->picture; + if (picture) + snap->picture = picture->p_next; + else if (snap->request_count > 0) + snap->request_count--; + + vlc_mutex_unlock(&snap->lock); + + return picture; +} + +/* */ +bool vout_snapshot_IsRequested(vout_snapshot_t *snap) +{ + bool has_request = false; + if (!vlc_mutex_trylock(&snap->lock)) { + has_request = snap->request_count > 0; + vlc_mutex_unlock(&snap->lock); + } + return has_request; +} +void vout_snapshot_Set(vout_snapshot_t *snap, + const video_format_t *fmt, + const picture_t *picture) +{ + if (!fmt) + fmt = &picture->format; + + vlc_mutex_lock(&snap->lock); + while (snap->request_count > 0) { + picture_t *dup = picture_NewFromFormat(fmt); + if (!dup) + break; + + picture_Copy(dup, picture); + + dup->p_next = snap->picture; + snap->picture = dup; + snap->request_count--; + } + vlc_cond_broadcast(&snap->wait); + vlc_mutex_unlock(&snap->lock); +} +/* */ +char *vout_snapshot_GetDirectory(void) +{ + char *psz_path = NULL; +#if defined(__APPLE__) || defined(SYS_BEOS) + + if (asprintf(&psz_path, "%s/Desktop", + config_GetHomeDir()) == -1) + psz_path = NULL; + +#elif defined(WIN32) && !defined(UNDER_CE) + + /* Get the My Pictures folder path */ + char *p_mypicturesdir = NULL; + typedef HRESULT (WINAPI *SHGETFOLDERPATH)(HWND, int, HANDLE, DWORD, + LPWSTR); + #ifndef CSIDL_FLAG_CREATE + # define CSIDL_FLAG_CREATE 0x8000 + #endif + #ifndef CSIDL_MYPICTURES + # define CSIDL_MYPICTURES 0x27 + #endif + #ifndef SHGFP_TYPE_CURRENT + # define SHGFP_TYPE_CURRENT 0 + #endif + + HINSTANCE shfolder_dll; + SHGETFOLDERPATH SHGetFolderPath ; + + /* load the shfolder dll to retrieve SHGetFolderPath */ + if ((shfolder_dll = LoadLibrary(_T("SHFolder.dll"))) != NULL) + { + wchar_t wdir[PATH_MAX]; + SHGetFolderPath = (void *)GetProcAddress(shfolder_dll, + _T("SHGetFolderPathW")); + if ((SHGetFolderPath != NULL) + && SUCCEEDED (SHGetFolderPath (NULL, + CSIDL_MYPICTURES | CSIDL_FLAG_CREATE, + NULL, SHGFP_TYPE_CURRENT, + wdir))) + p_mypicturesdir = FromWide (wdir); + + FreeLibrary(shfolder_dll); + } + + if (p_mypicturesdir == NULL) + psz_path = strdup(config_GetHomeDir()); + else + psz_path = p_mypicturesdir; + +#else + + /* XXX: This saves in the data directory. Shouldn't we try saving + * to psz_homedir/Desktop or something nicer ? */ + char *psz_datadir = config_GetUserDataDir(); + if (psz_datadir) + { + if (asprintf(&psz_path, "%s", psz_datadir) == -1) + psz_path = NULL; + free(psz_datadir); + } + +#endif + return psz_path; +} +/* */ +int vout_snapshot_SaveImage(char **name, int *sequential, + const block_t *image, + vlc_object_t *object, + const vout_snapshot_save_cfg_t *cfg) +{ + /* */ + char *filename; + DIR *pathdir = utf8_opendir(cfg->path); + if (pathdir != NULL) { + /* The use specified a directory path */ + closedir(pathdir); + + /* */ + char *prefix = NULL; + if (cfg->prefix_fmt) + prefix = str_format(object, cfg->prefix_fmt); + if (!prefix) { + prefix = strdup("vlcsnap-"); + if (!prefix) + goto error; + } + + if (cfg->is_sequential) { + for (int num = cfg->sequence; ; num++) { + struct stat st; + + if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s", + cfg->path, prefix, num, cfg->format) < 0) { + free(prefix); + goto error; + } + if (utf8_stat(filename, &st)) { + *sequential = num; + break; + } + free(filename); + } + } else { + struct tm curtime; + time_t lcurtime = time(NULL) ; + + if (!localtime_r(&lcurtime, &curtime)) { + const unsigned int id = (image->i_pts / 100000) & 0xFFFFFF; + + msg_Warn(object, "failed to get current time. Falling back to legacy snapshot naming"); + + if (asprintf(&filename, "%s" DIR_SEP "%s%u.%s", + cfg->path, prefix, id, cfg->format) < 0) + filename = NULL; + } else { + /* suffix with the last decimal digit in 10s of seconds resolution + * FIXME gni ? */ + const int id = (image->i_pts / (100*1000)) & 0xFF; + char buffer[128]; + + if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss", &curtime)) + strcpy(buffer, "error"); + + if (asprintf(&filename, "%s" DIR_SEP "%s%s%1u.%s", + cfg->path, prefix, buffer, id, cfg->format) < 0) + filename = NULL; + } + } + free(prefix); + } else { + /* The user specified a full path name (including file name) */ + filename = str_format(object, cfg->path); + path_sanitize(filename); + } + + if (!filename) + goto error; + + /* Save the snapshot */ + FILE *file = utf8_fopen(filename, "wb"); + if (!file) { + msg_Err(object, "Failed to open '%s'", filename); + free(filename); + goto error; + } + if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) { + msg_Err(object, "Failed to write to '%s'", filename); + fclose(file); + free(filename); + goto error; + } + fclose(file); + + /* */ + if (name) + *name = filename; + else + free(filename); + + return VLC_SUCCESS; + +error: + msg_Err(object, "could not save snapshot"); + return VLC_EGENERIC; +} + diff --git a/src/video_output/snapshot.h b/src/video_output/snapshot.h new file mode 100644 index 0000000000..866937701f --- /dev/null +++ b/src/video_output/snapshot.h @@ -0,0 +1,88 @@ +/***************************************************************************** + * snapshot.h : vout internal snapshot + ***************************************************************************** + * Copyright (C) 2009 Laurent Aimar + * $Id$ + * + * Authors: Laurent Aimar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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. + *****************************************************************************/ + +#if defined(__PLUGIN__) || defined(__BUILTIN__) || !defined(__LIBVLC__) +# error This header file can only be included from LibVLC. +#endif + +#ifndef _VOUT_INTERNAL_SNAPSHOT_H +#define _VOUT_INTERNAL_SNAPSHOT_H + +#include + +typedef struct { + vlc_mutex_t lock; + vlc_cond_t wait; + + bool is_available; + int request_count; + picture_t *picture; + +} vout_snapshot_t; + +/* */ +void vout_snapshot_Init(vout_snapshot_t *); +void vout_snapshot_Clean(vout_snapshot_t *); + +void vout_snapshot_End(vout_snapshot_t *); + +/* */ +picture_t *vout_snapshot_Get(vout_snapshot_t *, mtime_t timeout); + +/** + * It tells if they are pending snapshot request + */ +bool vout_snapshot_IsRequested(vout_snapshot_t *); + +/** + * It set the picture used to create the snapshots. + * + * The given picture is only copied and not released. + * If p_fmt is non NULL it will override the format of the p_picture (mainly + * used because of aspect/crop problems). + */ +void vout_snapshot_Set(vout_snapshot_t *, const video_format_t *, const picture_t *); + +/** + * This function will return the directory used for snapshots + */ +char *vout_snapshot_GetDirectory(void); + +typedef struct { + bool is_sequential; + int sequence; + char *path; + char *format; + char *prefix_fmt; +} vout_snapshot_save_cfg_t; + +/** + * This function will write an image to the disk an return the file name created. + */ +int vout_snapshot_SaveImage(char **name, int *sequential, + const block_t *image, + vlc_object_t *object, + const vout_snapshot_save_cfg_t *cfg); + +#endif + diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 418c7a7f61..691e144064 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -398,11 +398,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) p_vout->p->b_picture_empty = false; p_vout->p->i_picture_qtype = QTYPE_NONE; - p_vout->p->snapshot.b_available = true; - p_vout->p->snapshot.i_request = 0; - p_vout->p->snapshot.p_picture = NULL; - vlc_mutex_init( &p_vout->p->snapshot.lock ); - vlc_cond_init( &p_vout->p->snapshot.wait ); + vout_snapshot_Init( &p_vout->p->snapshot ); /* Initialize locks */ vlc_mutex_init( &p_vout->picture_lock ); @@ -563,10 +559,7 @@ void vout_Close( vout_thread_t *p_vout ) vlc_cond_signal( &p_vout->p->change_wait ); vlc_mutex_unlock( &p_vout->change_lock ); - vlc_mutex_lock( &p_vout->p->snapshot.lock ); - p_vout->p->snapshot.b_available = false; - vlc_cond_broadcast( &p_vout->p->snapshot.wait ); - vlc_mutex_unlock( &p_vout->p->snapshot.lock ); + vout_snapshot_End( &p_vout->p->snapshot ); vlc_join( p_vout->p->thread, NULL ); module_unneed( p_vout, p_vout->p_module ); @@ -593,18 +586,7 @@ static void vout_Destructor( vlc_object_t * p_this ) vlc_mutex_destroy( &p_vout->p->vfilter_lock ); /* */ - for( ;; ) - { - picture_t *p_picture = p_vout->p->snapshot.p_picture; - if( !p_picture ) - break; - - p_vout->p->snapshot.p_picture = p_picture->p_next; - - picture_Release( p_picture ); - } - vlc_cond_destroy( &p_vout->p->snapshot.wait ); - vlc_mutex_destroy( &p_vout->p->snapshot.lock ); + vout_snapshot_Clean( &p_vout->p->snapshot ); /* */ free( p_vout->p->psz_filter_chain ); @@ -1166,13 +1148,7 @@ static void* RunThread( void *p_this ) p_filtered_picture = filter_chain_VideoFilter( p_vout->p->p_vf2_chain, p_picture ); - bool b_snapshot = false; - if( vlc_mutex_trylock( &p_vout->p->snapshot.lock ) == 0 ) - { - b_snapshot = p_vout->p->snapshot.i_request > 0 - && p_picture != NULL; - vlc_mutex_unlock( &p_vout->p->snapshot.lock ); - } + const bool b_snapshot = vout_snapshot_IsRequested( &p_vout->p->snapshot ); /* * Check for subpictures to display @@ -1200,30 +1176,8 @@ static void* RunThread( void *p_this ) * Take a snapshot if requested */ if( p_directbuffer && b_snapshot ) - { - vlc_mutex_lock( &p_vout->p->snapshot.lock ); - assert( p_vout->p->snapshot.i_request > 0 ); - while( p_vout->p->snapshot.i_request > 0 ) - { - picture_t *p_pic = picture_New( p_vout->fmt_out.i_chroma, - p_vout->fmt_out.i_width, - p_vout->fmt_out.i_height, - p_vout->fmt_out.i_aspect ); - if( !p_pic ) - break; - - picture_Copy( p_pic, p_directbuffer ); - - p_pic->format.i_sar_num = p_vout->fmt_out.i_sar_num; - p_pic->format.i_sar_den = p_vout->fmt_out.i_sar_den; - - p_pic->p_next = p_vout->p->snapshot.p_picture; - p_vout->p->snapshot.p_picture = p_pic; - p_vout->p->snapshot.i_request--; - } - vlc_cond_broadcast( &p_vout->p->snapshot.wait ); - vlc_mutex_unlock( &p_vout->p->snapshot.lock ); - } + vout_snapshot_Set( &p_vout->p->snapshot, + &p_vout->fmt_out, p_directbuffer ); /* * Call the plugin-specific rendering method if there is one diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h index 773008ee9e..12a57302b5 100644 --- a/src/video_output/vout_internal.h +++ b/src/video_output/vout_internal.h @@ -31,6 +31,7 @@ #define _VOUT_INTERNAL_H 1 #include "vout_control.h" +#include "snapshot.h" /* Number of pictures required to computes the FPS rate */ #define VOUT_FPS_SAMPLES 20 @@ -88,14 +89,7 @@ struct vout_thread_sys_t char *psz_vf2; /* Snapshot interface */ - struct - { - bool b_available; - int i_request; - picture_t *p_picture; - vlc_mutex_t lock; - vlc_cond_t wait; - } snapshot; + vout_snapshot_t snapshot; /* Show media title on videoutput */ bool b_title_show; diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c index c4ea45c9e1..f8e7db6fbd 100644 --- a/src/video_output/vout_intf.c +++ b/src/video_output/vout_intf.c @@ -400,187 +400,6 @@ static int VoutSnapshotPip( vout_thread_t *p_vout, picture_t *p_pic ) spu_DisplaySubpicture( p_vout->p_spu, p_subpic ); return VLC_SUCCESS; } -/** - * This function will return the default directory used for snapshots - */ -static char *VoutSnapshotGetDefaultDirectory( void ) -{ - char *psz_path = NULL; -#if defined(__APPLE__) || defined(SYS_BEOS) - - if( asprintf( &psz_path, "%s/Desktop", - config_GetHomeDir() ) == -1 ) - psz_path = NULL; - -#elif defined(WIN32) && !defined(UNDER_CE) - - /* Get the My Pictures folder path */ - char *p_mypicturesdir = NULL; - typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD, - LPWSTR ); - #ifndef CSIDL_FLAG_CREATE - # define CSIDL_FLAG_CREATE 0x8000 - #endif - #ifndef CSIDL_MYPICTURES - # define CSIDL_MYPICTURES 0x27 - #endif - #ifndef SHGFP_TYPE_CURRENT - # define SHGFP_TYPE_CURRENT 0 - #endif - - HINSTANCE shfolder_dll; - SHGETFOLDERPATH SHGetFolderPath ; - - /* load the shfolder dll to retrieve SHGetFolderPath */ - if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL ) - { - wchar_t wdir[PATH_MAX]; - SHGetFolderPath = (void *)GetProcAddress( shfolder_dll, - _T("SHGetFolderPathW") ); - if ((SHGetFolderPath != NULL ) - && SUCCEEDED (SHGetFolderPath (NULL, - CSIDL_MYPICTURES | CSIDL_FLAG_CREATE, - NULL, SHGFP_TYPE_CURRENT, - wdir))) - p_mypicturesdir = FromWide (wdir); - - FreeLibrary( shfolder_dll ); - } - - if( p_mypicturesdir == NULL ) - psz_path = strdup( config_GetHomeDir() ); - else - psz_path = p_mypicturesdir; - -#else - - /* XXX: This saves in the data directory. Shouldn't we try saving - * to psz_homedir/Desktop or something nicer ? */ - psz_path = config_GetUserDataDir(); - -#endif - - return psz_path; -} -/** - * This function will save a video snapshot to a file - */ -static int VoutWriteSnapshot( vout_thread_t *p_vout, char **ppsz_filename, - const block_t *p_image, - const char *psz_path, - const char *psz_format, - const char *psz_prefix_fmt ) -{ - /* */ - char *psz_filename; - DIR *p_path = utf8_opendir( psz_path ); - if( p_path != NULL ) - { - /* The use specified a directory path */ - closedir( p_path ); - - /* */ - char *psz_prefix = NULL; - if( psz_prefix_fmt ) - psz_prefix = str_format( p_vout, psz_prefix_fmt ); - if( !psz_prefix ) - { - psz_prefix = strdup( "vlcsnap-" ); - if( !psz_prefix ) - goto error; - } - - if( var_GetBool( p_vout, "snapshot-sequential" ) ) - { - int i_num = var_GetInteger( p_vout, "snapshot-num" ); - for( ; ; i_num++ ) - { - struct stat st; - - if( asprintf( &psz_filename, "%s" DIR_SEP "%s%05d.%s", - psz_path, psz_prefix, i_num++, psz_format ) < 0 ) - { - free( psz_prefix ); - goto error; - } - if( utf8_stat( psz_filename, &st ) ) - break; - free( psz_filename ); - } - - var_SetInteger( p_vout, "snapshot-num", i_num ); - } - else - { - struct tm curtime; - time_t lcurtime = time( NULL ) ; - - if( !localtime_r( &lcurtime, &curtime ) ) - { - const unsigned int i_id = (p_image->i_pts / 100000) & 0xFFFFFF; - - msg_Warn( p_vout, "failed to get current time. Falling back to legacy snapshot naming" ); - - if( asprintf( &psz_filename, "%s" DIR_SEP "%s%u.%s", - psz_path, psz_prefix, i_id, psz_format ) < 0 ) - psz_filename = NULL; - } - else - { - /* suffix with the last decimal digit in 10s of seconds resolution - * FIXME gni ? */ - const int i_id = (p_image->i_pts / (100*1000)) & 0xFF; - char psz_curtime[128]; - - if( !strftime( psz_curtime, sizeof(psz_curtime), "%Y-%m-%d-%Hh%Mm%Ss", &curtime ) ) - strcpy( psz_curtime, "error" ); - - if( asprintf( &psz_filename, "%s" DIR_SEP "%s%s%1u.%s", - psz_path, psz_prefix, psz_curtime, i_id, psz_format ) < 0 ) - psz_filename = NULL; - } - } - free( psz_prefix ); - } - else - { - /* The user specified a full path name (including file name) */ - psz_filename = str_format( p_vout, psz_path ); - path_sanitize( psz_filename ); - } - - if( !psz_filename ) - goto error; - - /* Save the snapshot */ - FILE *p_file = utf8_fopen( psz_filename, "wb" ); - if( !p_file ) - { - msg_Err( p_vout, "Failed to open '%s'", psz_filename ); - free( psz_filename ); - goto error; - } - if( fwrite( p_image->p_buffer, p_image->i_buffer, 1, p_file ) != 1 ) - { - msg_Err( p_vout, "Failed to write to '%s'", psz_filename ); - fclose( p_file ); - free( psz_filename ); - goto error; - } - fclose( p_file ); - - /* */ - if( ppsz_filename ) - *ppsz_filename = psz_filename; - else - free( psz_filename ); - - return VLC_SUCCESS; - -error: - msg_Err( p_vout, "could not save snapshot" ); - return VLC_EGENERIC; -} /** * This function will display the name and a PIP of the provided snapshot @@ -603,26 +422,7 @@ int vout_GetSnapshot( vout_thread_t *p_vout, video_format_t *p_fmt, const char *psz_format, mtime_t i_timeout ) { - vout_thread_sys_t *p_sys = p_vout->p; - - vlc_mutex_lock( &p_sys->snapshot.lock ); - p_sys->snapshot.i_request++; - - const mtime_t i_deadline = mdate() + i_timeout; - while( p_sys->snapshot.b_available && !p_sys->snapshot.p_picture ) - { - if( vlc_cond_timedwait( &p_sys->snapshot.wait, &p_sys->snapshot.lock, - i_deadline ) ) - break; - } - - picture_t *p_picture = p_sys->snapshot.p_picture; - if( p_picture ) - p_sys->snapshot.p_picture = p_picture->p_next; - else if( p_sys->snapshot.i_request > 0 ) - p_sys->snapshot.i_request--; - vlc_mutex_unlock( &p_sys->snapshot.lock ); - + picture_t *p_picture = vout_snapshot_Get( &p_vout->p->snapshot, i_timeout ); if( !p_picture ) { msg_Err( p_vout, "Failed to grab a snapshot" ); @@ -678,7 +478,7 @@ static void VoutSaveSnapshot( vout_thread_t *p_vout ) if( !psz_path ) { - psz_path = VoutSnapshotGetDefaultDirectory(); + psz_path = vout_snapshot_GetDirectory(); if( !psz_path ) { msg_Err( p_vout, "no path specified for snapshots" ); @@ -686,11 +486,21 @@ static void VoutSaveSnapshot( vout_thread_t *p_vout ) } } + vout_snapshot_save_cfg_t cfg; + memset( &cfg, 0, sizeof(cfg) ); + cfg.is_sequential = var_GetBool( p_vout, "snapshot-sequential" ); + cfg.sequence = var_GetInteger( p_vout, "snapshot-num" ); + cfg.path = psz_path; + cfg.format = psz_format; + cfg.prefix_fmt = psz_prefix; + char *psz_filename; - if( VoutWriteSnapshot( p_vout, &psz_filename, - p_image, - psz_path, psz_format, psz_prefix ) ) + int i_sequence; + if (vout_snapshot_SaveImage( &psz_filename, &i_sequence, + p_image, VLC_OBJECT(p_vout), &cfg ) ) goto exit; + if( cfg.is_sequential ) + var_SetInteger( p_vout, "snapshot-num", i_sequence + 1 ); VoutOsdSnapshot( p_vout, p_picture, psz_filename );