Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
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-gpu
Commits
bdaa9f31
Commit
bdaa9f31
authored
Mar 07, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use picture_Export in vout_Snapshot.
It fixes a few memleaks in case of error.
parent
66603abb
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
148 additions
and
172 deletions
+148
-172
src/video_output/vout_intf.c
src/video_output/vout_intf.c
+148
-172
No files found.
src/video_output/vout_intf.c
View file @
bdaa9f31
...
@@ -459,9 +459,9 @@ void vout_IntfInit( vout_thread_t *p_vout )
...
@@ -459,9 +459,9 @@ void vout_IntfInit( vout_thread_t *p_vout )
* This function will inject a subpicture into the vout with the provided
* This function will inject a subpicture into the vout with the provided
* picture
* picture
*/
*/
static
int
VoutSnapshotPip
(
vout_thread_t
*
p_vout
,
image_handler_t
*
p_image
,
picture_t
*
p_pic
,
const
video_format_t
*
p_fmt_in
)
static
int
VoutSnapshotPip
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
{
video_format_t
fmt_in
=
*
p_fmt_in
;
video_format_t
fmt_in
=
p_pic
->
format
;
video_format_t
fmt_out
;
video_format_t
fmt_out
;
picture_t
*
p_pip
;
picture_t
*
p_pip
;
subpicture_t
*
p_subpic
;
subpicture_t
*
p_subpic
;
...
@@ -472,12 +472,19 @@ static int VoutSnapshotPip( vout_thread_t *p_vout, image_handler_t *p_image, pic
...
@@ -472,12 +472,19 @@ static int VoutSnapshotPip( vout_thread_t *p_vout, image_handler_t *p_image, pic
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'A'
);
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'A'
);
/* */
/* */
image_handler_t
*
p_image
=
image_HandlerCreate
(
p_vout
);
if
(
!
p_image
)
return
VLC_EGENERIC
;
p_pip
=
image_Convert
(
p_image
,
p_pic
,
&
fmt_in
,
&
fmt_out
);
p_pip
=
image_Convert
(
p_image
,
p_pic
,
&
fmt_in
,
&
fmt_out
);
image_HandlerDelete
(
p_image
);
if
(
!
p_pip
)
if
(
!
p_pip
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
p_subpic
=
subpicture_New
();
p_subpic
=
subpicture_New
();
if
(
p_subpic
==
NULL
)
if
(
!
p_subpic
)
{
{
picture_Release
(
p_pip
);
picture_Release
(
p_pip
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
...
@@ -577,244 +584,204 @@ static char *VoutSnapshotGetDefaultDirectory( void )
...
@@ -577,244 +584,204 @@ static char *VoutSnapshotGetDefaultDirectory( void )
return
psz_path
;
return
psz_path
;
}
}
int
vout_Snapshot
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
int
vout_Snapshot
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
ture_private
)
{
{
image_handler_t
*
p_image
=
image_HandlerCreate
(
p_vout
);
/* FIXME find why it is sometimes needed (format being wrong/invalid) */
video_format_t
fmt_in
,
fmt_out
;
picture_t
pic
=
*
p_picture_private
;
char
*
psz_filename
=
NULL
;
pic
.
format
=
p_vout
->
fmt_out
;
vlc_value_t
val
,
format
;
picture_t
*
p_pic
=
&
pic
;
DIR
*
path
;
int
i_ret
;
bool
b_embedded_snapshot
;
void
*
p_obj
;
/* */
/* */
val
.
psz_string
=
var_GetNonEmptyString
(
p_vout
,
"snapshot-path"
);
char
*
psz_path
=
var_GetNonEmptyString
(
p_vout
,
"snapshot-path"
);
/* Embedded snapshot : if snapshot-path == object:object_ptr */
/* Embedded snapshot : if snapshot-path == object:object_ptr */
if
(
val
.
psz_string
&&
sscanf
(
val
.
psz_string
,
"object:%p"
,
&
p_obj
)
>
0
)
void
*
p_obj
;
b_embedded_snapshot
=
true
;
const
bool
b_embedded_snapshot
=
psz_path
&&
sscanf
(
psz_path
,
"object:%p"
,
&
p_obj
)
>
0
;
else
b_embedded_snapshot
=
false
;
/* */
char
*
psz_format
=
NULL
;
memset
(
&
fmt_in
,
0
,
sizeof
(
video_format_t
)
);
if
(
!
b_embedded_snapshot
)
fmt_in
=
p_vout
->
fmt_out
;
if
(
fmt_in
.
i_sar_num
<=
0
||
fmt_in
.
i_sar_den
<=
0
)
{
{
fmt_in
.
i_sar_num
=
psz_format
=
var_GetNonEmptyString
(
p_vout
,
"snapshot-format"
);
fmt_in
.
i_sar_den
=
1
;
if
(
!
psz_format
)
psz_format
=
strdup
(
"png"
);
if
(
!
psz_format
)
{
free
(
psz_path
);
return
VLC_ENOMEM
;
}
}
}
/* */
vlc_fourcc_t
i_format
=
VLC_FOURCC
(
'p'
,
'n'
,
'g'
,
' '
);
memset
(
&
fmt_out
,
0
,
sizeof
(
video_format_t
)
);
if
(
psz_format
&&
image_Ext2Fourcc
(
psz_format
)
)
fmt_out
.
i_sar_num
=
i_format
=
image_Ext2Fourcc
(
psz_format
);
fmt_out
.
i_sar_den
=
1
;
fmt_out
.
i_chroma
=
b_embedded_snapshot
?
VLC_FOURCC
(
'p'
,
'n'
,
'g'
,
' '
)
:
0
;
fmt_out
.
i_width
=
var_GetInteger
(
p_vout
,
"snapshot-width"
);
fmt_out
.
i_height
=
var_GetInteger
(
p_vout
,
"snapshot-height"
);
if
(
b_embedded_snapshot
&&
int
i_override_width
=
var_GetInteger
(
p_vout
,
"snapshot-width"
);
fmt_out
.
i_width
==
0
&&
fmt_out
.
i_height
==
0
)
int
i_override_height
=
var_GetInteger
(
p_vout
,
"snapshot-height"
);
{
/* If snapshot-width and/or snapshot height were not specified for embed snapshot ,
/* If snapshot-width and/or snapshot height were not specified,
use a default snapshot width of 320.
use a default snapshot width of 320 */
TODO removed that weird behavior */
fmt_out
.
i_width
=
320
;
}
if
(
fmt_out
.
i_height
==
0
&&
fmt_out
.
i_width
>
0
)
if
(
b_embedded_snapshot
&&
!
i_override_width
&&
!
i_override_height
)
{
i_override_width
=
320
;
fmt_out
.
i_height
=
fmt_in
.
i_height
*
fmt_out
.
i_width
/
fmt_in
.
i_width
;
const
int
i_height
=
fmt_out
.
i_height
*
fmt_in
.
i_sar_den
/
fmt_in
.
i_sar_num
;
block_t
*
p_out
;
if
(
i_height
>
0
)
video_format_t
fmt_out
;
fmt_out
.
i_height
=
i_height
;
if
(
picture_Export
(
VLC_OBJECT
(
p_vout
),
&
p_out
,
&
fmt_out
,
}
p_pic
,
i_format
,
i_override_width
,
i_override_height
)
)
else
{
{
if
(
fmt_out
.
i_width
==
0
&&
fmt_out
.
i_height
>
0
)
msg_Err
(
p_vout
,
"Failed to convert image for snapshot"
);
{
p_out
=
NULL
;
fmt_out
.
i_width
=
fmt_in
.
i_width
*
fmt_out
.
i_height
/
fmt_in
.
i_height
;
}
else
{
fmt_out
.
i_width
=
fmt_in
.
i_width
;
fmt_out
.
i_height
=
fmt_in
.
i_height
;
}
const
int
i_width
=
fmt_out
.
i_width
*
fmt_in
.
i_sar_num
/
fmt_in
.
i_sar_den
;
if
(
i_width
>
0
)
fmt_out
.
i_width
=
i_width
;
}
}
/* Embedded snapshot
create a snapshot_t* and store it in
object_ptr->p_private, then unlock and signal the
waiting object.
*/
if
(
b_embedded_snapshot
)
if
(
b_embedded_snapshot
)
{
{
block_t
*
p_block
;
/* TODO fix that ugliness */
snapshot_t
*
p_snapshot
=
p_obj
;
snapshot_t
*
p_snapshot
=
p_obj
;
size_t
i_size
;
vlc_mutex_lock
(
&
p_snapshot
->
p_mutex
);
vlc_mutex_lock
(
&
p_snapshot
->
p_mutex
);
p_snapshot
->
p_data
=
NULL
;
p_snapshot
->
i_width
=
fmt_out
.
i_width
;
p_snapshot
->
i_height
=
fmt_out
.
i_height
;
p_snapshot
->
date
=
p_pic
->
date
;
/* Save the snapshot to a memory zone */
p_snapshot
->
i_datasize
=
0
;
p_
block
=
image_Write
(
p_image
,
p_pic
,
&
fmt_in
,
&
fmt_out
)
;
p_
snapshot
->
p_data
=
NULL
;
if
(
!
p_block
)
if
(
p_out
)
{
{
msg_Err
(
p_vout
,
"Could not get snapshot"
);
p_snapshot
->
p_data
=
malloc
(
p_out
->
i_buffer
);
image_HandlerDelete
(
p_image
);
if
(
p_snapshot
->
p_data
)
vlc_cond_signal
(
&
p_snapshot
->
p_condvar
);
{
vlc_mutex_unlock
(
&
p_snapshot
->
p_mutex
);
p_snapshot
->
i_datasize
=
p_out
->
i_buffer
;
return
VLC_EGENERIC
;
memcpy
(
p_snapshot
->
p_data
,
p_out
->
p_buffer
,
p_out
->
i_buffer
);
}
}
}
i_size
=
p_block
->
i_buffer
;
p_snapshot
->
i_width
=
fmt_out
.
i_width
;
p_snapshot
->
i_height
=
fmt_out
.
i_height
;
p_snapshot
->
i_datasize
=
i_size
;
p_snapshot
->
date
=
p_block
->
i_pts
;
/* FIXME ?? */
p_snapshot
->
p_data
=
malloc
(
i_size
);
if
(
!
p_snapshot
->
p_data
)
{
block_Release
(
p_block
);
image_HandlerDelete
(
p_image
);
vlc_cond_signal
(
&
p_snapshot
->
p_condvar
);
vlc_cond_signal
(
&
p_snapshot
->
p_condvar
);
vlc_mutex_unlock
(
&
p_snapshot
->
p_mutex
);
vlc_mutex_unlock
(
&
p_snapshot
->
p_mutex
);
return
VLC_ENOMEM
;
}
memcpy
(
p_snapshot
->
p_data
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
block_Release
(
p_block
);
/* Unlock the object */
free
(
psz_path
);
vlc_cond_signal
(
&
p_snapshot
->
p_condvar
);
free
(
psz_format
);
vlc_mutex_unlock
(
&
p_snapshot
->
p_mutex
);
image_HandlerDelete
(
p_image
);
if
(
!
p_out
)
return
VLC_EGENERIC
;
block_Release
(
p_out
);
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
if
(
!
p_out
)
goto
error
;
/* Get default directory if none provided */
/* Get default directory if none provided */
if
(
!
val
.
psz_string
)
if
(
!
psz_path
)
val
.
psz_string
=
VoutSnapshotGetDefaultDirectory
(
);
if
(
!
val
.
psz_string
)
{
{
msg_Err
(
p_vout
,
"no path specified for snapshots"
);
psz_path
=
VoutSnapshotGetDefaultDirectory
();
image_HandlerDelete
(
p_image
);
if
(
!
psz_path
)
return
VLC_EGENERIC
;
{
msg_Err
(
p_vout
,
"no path specified for snapshots"
);
goto
error
;
}
}
}
/* Get snapshot format, default being "png" */
/* */
format
.
psz_string
=
var_GetNonEmptyString
(
p_vout
,
"snapshot-format"
);
char
*
psz_filename
;
if
(
!
format
.
psz_string
)
DIR
*
p_path
=
utf8_opendir
(
psz_path
);
format
.
psz_string
=
strdup
(
"png"
);
if
(
p_path
!=
NULL
)
if
(
!
format
.
psz_string
)
{
{
free
(
val
.
psz_string
);
/* The use specified a directory path */
image_HandlerDelete
(
p_image
);
closedir
(
p_path
);
return
VLC_ENOMEM
;
}
/*
/* */
* Did the user specify a directory? If not, path = NULL.
*/
path
=
utf8_opendir
(
(
const
char
*
)
val
.
psz_string
);
if
(
path
!=
NULL
)
{
char
*
psz_prefix
=
var_GetNonEmptyString
(
p_vout
,
"snapshot-prefix"
);
char
*
psz_prefix
=
var_GetNonEmptyString
(
p_vout
,
"snapshot-prefix"
);
if
(
psz_prefix
==
NULL
)
if
(
psz_prefix
)
psz_prefix
=
strdup
(
"vlcsnap-"
);
else
{
{
char
*
psz_tmp
=
str_format
(
p_vout
,
psz_prefix
);
char
*
psz_tmp
=
str_format
(
p_vout
,
psz_prefix
);
filename_sanitize
(
psz_tmp
);
free
(
psz_prefix
);
free
(
psz_prefix
);
psz_prefix
=
psz_tmp
;
psz_prefix
=
psz_tmp
;
}
}
if
(
!
psz_prefix
)
{
psz_prefix
=
strdup
(
"vlcsnap-"
);
if
(
!
psz_prefix
)
goto
error
;
}
closedir
(
path
);
if
(
var_GetBool
(
p_vout
,
"snapshot-sequential"
)
==
true
)
if
(
var_GetBool
(
p_vout
,
"snapshot-sequential"
)
==
true
)
{
{
int
i_num
=
var_GetInteger
(
p_vout
,
"snapshot-num"
);
int
i_num
=
var_GetInteger
(
p_vout
,
"snapshot-num"
);
struct
stat
st
;
for
(
;
;
i_num
++
)
do
{
{
free
(
psz_filename
);
struct
stat
st
;
if
(
asprintf
(
&
psz_filename
,
"%s"
DIR_SEP
"%s%05d.%s"
,
if
(
asprintf
(
&
psz_filename
,
"%s"
DIR_SEP
"%s%05d.%s"
,
val
.
psz_string
,
psz_prefix
,
i_num
++
,
psz_path
,
psz_prefix
,
i_num
++
,
psz_format
)
<
0
)
format
.
psz_string
)
==
-
1
)
{
{
msg_Err
(
p_vout
,
"could not create snapshot"
);
free
(
psz_prefix
);
image_HandlerDelete
(
p_image
);
goto
error
;
return
VLC_EGENERIC
;
}
}
if
(
utf8_stat
(
psz_filename
,
&
st
)
)
break
;
free
(
psz_filename
);
}
}
while
(
utf8_stat
(
psz_filename
,
&
st
)
==
0
);
var_SetInteger
(
p_vout
,
"snapshot-num"
,
i_num
);
var_SetInteger
(
p_vout
,
"snapshot-num"
,
i_num
);
}
}
else
else
{
{
struct
tm
curtime
;
struct
tm
curtime
;
time_t
lcurtime
;
time_t
lcurtime
=
time
(
NULL
)
;
lcurtime
=
time
(
NULL
)
;
if
(
(
localtime_r
(
&
lcurtime
,
&
curtime
)
==
NULL
)
)
if
(
!
localtime_r
(
&
lcurtime
,
&
curtime
)
)
{
{
const
unsigned
int
i_id
=
(
p_pic
->
date
/
100000
)
&
0xFFFFFF
;
msg_Warn
(
p_vout
,
"failed to get current time. Falling back to legacy snapshot naming"
);
msg_Warn
(
p_vout
,
"failed to get current time. Falling back to legacy snapshot naming"
);
/* failed to get current time. Fallback to old format */
if
(
asprintf
(
&
psz_filename
,
"%s"
DIR_SEP
"%s%u.%s"
,
if
(
asprintf
(
&
psz_filename
,
"%s"
DIR_SEP
"%s%u.%s"
,
val
.
psz_string
,
psz_prefix
,
psz_path
,
psz_prefix
,
i_id
,
psz_format
)
<
0
)
(
unsigned
int
)(
p_pic
->
date
/
100000
)
&
0xFFFFFF
,
psz_filename
=
NULL
;
format
.
psz_string
)
==
-
1
)
{
msg_Err
(
p_vout
,
"could not create snapshot"
);
image_HandlerDelete
(
p_image
);
return
VLC_EGENERIC
;
}
}
}
else
else
{
{
char
psz_curtime
[
15
]
;
/* suffix with the last decimal digit in 10s of seconds resolution
if
(
strftime
(
psz_curtime
,
15
,
"%y%m%d-%H%M%S"
,
&
curtime
)
==
0
)
* FIXME gni ? */
{
const
int
i_id
=
(
p_pic
->
date
/
(
100
*
1000
))
&
0xFF
;
msg_Warn
(
p_vout
,
"snapshot date string truncated"
)
;
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"
,
if
(
asprintf
(
&
psz_filename
,
"%s"
DIR_SEP
"%s%s%1u.%s"
,
val
.
psz_string
,
psz_prefix
,
psz_curtime
,
psz_path
,
psz_prefix
,
psz_curtime
,
i_id
,
psz_format
)
<
0
)
/* suffix with the last decimal digit in 10s of seconds resolution */
psz_filename
=
NULL
;
(
unsigned
int
)(
p_pic
->
date
/
(
100
*
1000
))
&
0xFF
,
}
format
.
psz_string
)
==
-
1
)
}
{
msg_Err
(
p_vout
,
"could not create snapshot"
);
image_HandlerDelete
(
p_image
);
return
VLC_EGENERIC
;
}
}
//end if time() < 0
}
//end snapshot sequential
free
(
psz_prefix
);
free
(
psz_prefix
);
}
}
else
// The user specified a full path name (including file name)
else
{
{
psz_filename
=
str_format
(
p_vout
,
val
.
psz_string
);
/* The user specified a full path name (including file name) */
psz_filename
=
str_format
(
p_vout
,
psz_path
);
path_sanitize
(
psz_filename
);
path_sanitize
(
psz_filename
);
}
}
free
(
val
.
psz_string
);
if
(
!
psz_filename
)
free
(
format
.
psz_string
)
;
goto
error
;
/* Save the snapshot */
/* Save the snapshot */
i_ret
=
image_WriteUrl
(
p_image
,
p_pic
,
&
fmt_in
,
&
fmt_out
,
psz_filename
);
FILE
*
p_file
=
utf8_fopen
(
psz_filename
,
"wb"
);
if
(
i_ret
!=
VLC_SUCCESS
)
if
(
!
p_file
)
{
{
msg_Err
(
p_vout
,
"
could not create snapshot %s
"
,
psz_filename
);
msg_Err
(
p_vout
,
"
Failed to open '%s'
"
,
psz_filename
);
free
(
psz_filename
);
free
(
psz_filename
);
image_HandlerDelete
(
p_image
);
goto
error
;
return
VLC_EGENERIC
;
}
}
if
(
fwrite
(
p_out
->
p_buffer
,
p_out
->
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
);
/* */
/* */
msg_Dbg
(
p_vout
,
"snapshot taken (%s)"
,
psz_filename
);
msg_Dbg
(
p_vout
,
"snapshot taken (%s)"
,
psz_filename
);
...
@@ -824,21 +791,30 @@ int vout_Snapshot( vout_thread_t *p_vout, picture_t *p_pic )
...
@@ -824,21 +791,30 @@ int vout_Snapshot( vout_thread_t *p_vout, picture_t *p_pic )
/* Generate a media player event - Right now just trigger a global libvlc var
/* Generate a media player event - Right now just trigger a global libvlc var
CHECK: Could not find a more local object. The goal is to communicate
CHECK: Could not find a more local object. The goal is to communicate
vout_thread with libvlc_media_player or its input_thread*/
vout_thread with libvlc_media_player or its input_thread*/
va
l
.
psz_string
=
psz_filename
;
va
r_SetString
(
p_vout
->
p_libvlc
,
"vout-snapshottaken"
,
psz_filename
)
;
var_Set
(
p_vout
->
p_libvlc
,
"vout-snapshottaken"
,
val
);
/* var_Set duplicates data for transport so we can free*/
free
(
psz_filename
);
free
(
psz_filename
);
/* */
/* */
if
(
var_GetBool
(
p_vout
,
"snapshot-preview"
)
)
if
(
var_GetBool
(
p_vout
,
"snapshot-preview"
)
)
{
{
if
(
VoutSnapshotPip
(
p_vout
,
p_
image
,
p_pic
,
&
fmt_in
)
)
if
(
VoutSnapshotPip
(
p_vout
,
p_
pic
)
)
msg_Warn
(
p_vout
,
"Failed to display snapshot"
);
msg_Warn
(
p_vout
,
"Failed to display snapshot"
);
}
}
image_HandlerDelete
(
p_image
);
if
(
p_out
)
block_Release
(
p_out
);
free
(
psz_path
);
free
(
psz_format
);
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
error:
msg_Err
(
p_vout
,
"could not create snapshot"
);
if
(
p_out
)
block_Release
(
p_out
);
free
(
psz_path
);
free
(
psz_format
);
return
VLC_EGENERIC
;
}
}
/*****************************************************************************
/*****************************************************************************
...
...
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