1 /*****************************************************************************
2 * snapshot.c : vout internal snapshot
3 *****************************************************************************
4 * Copyright (C) 2009 Laurent Aimar
7 * Authors: Gildas Bazin <gbazin _AT_ videolan _DOT_ org>
8 * Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
31 #include <sys/types.h>
36 #include <vlc_common.h>
38 #include <vlc_strings.h>
39 #include <vlc_block.h>
43 #include "vout_internal.h"
46 void vout_snapshot_Init(vout_snapshot_t
*snap
)
48 vlc_mutex_init(&snap
->lock
);
49 vlc_cond_init(&snap
->wait
);
51 snap
->is_available
= true;
52 snap
->request_count
= 0;
55 void vout_snapshot_Clean(vout_snapshot_t
*snap
)
57 picture_t
*picture
= snap
->picture
;
59 picture_t
*next
= picture
->p_next
;
60 picture_Release(picture
);
64 vlc_cond_destroy(&snap
->wait
);
65 vlc_mutex_destroy(&snap
->lock
);
68 void vout_snapshot_End(vout_snapshot_t
*snap
)
70 vlc_mutex_lock(&snap
->lock
);
72 snap
->is_available
= false;
74 vlc_cond_broadcast(&snap
->wait
);
75 vlc_mutex_unlock(&snap
->lock
);
79 picture_t
*vout_snapshot_Get(vout_snapshot_t
*snap
, mtime_t timeout
)
81 vlc_mutex_lock(&snap
->lock
);
84 snap
->request_count
++;
87 const mtime_t deadline
= mdate() + timeout
;
88 while (snap
->is_available
&& !snap
->picture
&& mdate() < deadline
)
89 vlc_cond_timedwait(&snap
->wait
, &snap
->lock
, deadline
);
92 picture_t
*picture
= snap
->picture
;
94 snap
->picture
= picture
->p_next
;
95 else if (snap
->request_count
> 0)
96 snap
->request_count
--;
98 vlc_mutex_unlock(&snap
->lock
);
104 bool vout_snapshot_IsRequested(vout_snapshot_t
*snap
)
106 bool has_request
= false;
107 if (!vlc_mutex_trylock(&snap
->lock
)) {
108 has_request
= snap
->request_count
> 0;
109 vlc_mutex_unlock(&snap
->lock
);
113 void vout_snapshot_Set(vout_snapshot_t
*snap
,
114 const video_format_t
*fmt
,
115 const picture_t
*picture
)
118 fmt
= &picture
->format
;
120 vlc_mutex_lock(&snap
->lock
);
121 while (snap
->request_count
> 0) {
122 picture_t
*dup
= picture_NewFromFormat(fmt
);
126 picture_Copy(dup
, picture
);
128 dup
->p_next
= snap
->picture
;
130 snap
->request_count
--;
132 vlc_cond_broadcast(&snap
->wait
);
133 vlc_mutex_unlock(&snap
->lock
);
136 char *vout_snapshot_GetDirectory(void)
138 return config_GetUserDir(VLC_PICTURES_DIR
);
141 int vout_snapshot_SaveImage(char **name
, int *sequential
,
142 const block_t
*image
,
143 vout_thread_t
*p_vout
,
144 const vout_snapshot_save_cfg_t
*cfg
)
148 DIR *pathdir
= vlc_opendir(cfg
->path
);
149 input_thread_t
*input
= (input_thread_t
*)p_vout
->p
->input
;
150 if (pathdir
!= NULL
) {
151 /* The use specified a directory path */
157 prefix
= str_format(input
, cfg
->prefix_fmt
);
159 filename_sanitize(prefix
);
161 prefix
= strdup("vlcsnap-");
166 if (cfg
->is_sequential
) {
167 for (int num
= cfg
->sequence
; ; num
++) {
170 if (asprintf(&filename
, "%s" DIR_SEP
"%s%05d.%s",
171 cfg
->path
, prefix
, num
, cfg
->format
) < 0) {
175 if (vlc_stat(filename
, &st
)) {
186 gettimeofday(&tv
, NULL
);
187 if (localtime_r(&tv
.tv_sec
, &curtime
) == NULL
)
188 gmtime_r(&tv
.tv_sec
, &curtime
);
189 if (strftime(buffer
, sizeof(buffer
), "%Y-%m-%d-%Hh%Mm%Ss",
191 strcpy(buffer
, "error");
193 if (asprintf(&filename
, "%s" DIR_SEP
"%s%s%03lu.%s",
194 cfg
->path
, prefix
, buffer
, tv
.tv_usec
/ 1000,
200 /* The user specified a full path name (including file name) */
201 filename
= str_format(input
, cfg
->path
);
202 path_sanitize(filename
);
208 /* Save the snapshot */
209 FILE *file
= vlc_fopen(filename
, "wb");
211 msg_Err(p_vout
, "Failed to open '%s'", filename
);
215 if (fwrite(image
->p_buffer
, image
->i_buffer
, 1, file
) != 1) {
216 msg_Err(p_vout
, "Failed to write to '%s'", filename
);
232 msg_Err(p_vout
, "could not save snapshot");