Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
a7a12139
Commit
a7a12139
authored
Aug 01, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved out snapshot code to a standalone file.
parent
5174ad04
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
410 additions
and
265 deletions
+410
-265
src/Makefile.am
src/Makefile.am
+2
-0
src/video_output/snapshot.c
src/video_output/snapshot.c
+297
-0
src/video_output/snapshot.h
src/video_output/snapshot.h
+88
-0
src/video_output/video_output.c
src/video_output/video_output.c
+6
-52
src/video_output/vout_internal.h
src/video_output/vout_internal.h
+2
-8
src/video_output/vout_intf.c
src/video_output/vout_intf.c
+15
-205
No files found.
src/Makefile.am
View file @
a7a12139
...
...
@@ -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
\
...
...
src/video_output/snapshot.c
0 → 100644
View file @
a7a12139
/*****************************************************************************
* snapshot.c : vout internal snapshot
*****************************************************************************
* Copyright (C) 2009 Laurent Aimar
* $Id$
*
* Authors: Gildas Bazin <gbazin _AT_ videolan _DOT_ org>
* Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* 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 <vlc_common.h>
#include <vlc_charset.h>
#include <vlc_strings.h>
#include <vlc_block.h>
#include "snapshot.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <time.h>
/* */
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
;
}
src/video_output/snapshot.h
0 → 100644
View file @
a7a12139
/*****************************************************************************
* snapshot.h : vout internal snapshot
*****************************************************************************
* Copyright (C) 2009 Laurent Aimar
* $Id$
*
* Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* 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 <vlc_picture.h>
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
src/video_output/video_output.c
View file @
a7a12139
...
...
@@ -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
...
...
src/video_output/vout_internal.h
View file @
a7a12139
...
...
@@ -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
;
...
...
src/video_output/vout_intf.c
View file @
a7a12139
...
...
@@ -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
=
VoutSnapshotGetDefaul
tDirectory
();
psz_path
=
vout_snapshot_Ge
tDirectory
();
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
;
i
f
(
VoutWriteSnapshot
(
p_vout
,
&
psz_filename
,
p_imag
e
,
psz_path
,
psz_format
,
psz_prefix
)
)
i
nt
i_sequence
;
if
(
vout_snapshot_SaveImage
(
&
psz_filename
,
&
i_sequenc
e
,
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
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment