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%03u.%s",
194 cfg->path, prefix, buffer,
195 (unsigned)tv.tv_usec / 1000, cfg->format) < 0)
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");