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>
35 #include <vlc_common.h>
37 #include <vlc_strings.h>
38 #include <vlc_block.h>
42 #include "vout_internal.h"
45 void vout_snapshot_Init(vout_snapshot_t
*snap
)
47 vlc_mutex_init(&snap
->lock
);
48 vlc_cond_init(&snap
->wait
);
50 snap
->is_available
= true;
51 snap
->request_count
= 0;
54 void vout_snapshot_Clean(vout_snapshot_t
*snap
)
56 picture_t
*picture
= snap
->picture
;
58 picture_t
*next
= picture
->p_next
;
59 picture_Release(picture
);
63 vlc_cond_destroy(&snap
->wait
);
64 vlc_mutex_destroy(&snap
->lock
);
67 void vout_snapshot_End(vout_snapshot_t
*snap
)
69 vlc_mutex_lock(&snap
->lock
);
71 snap
->is_available
= false;
73 vlc_cond_broadcast(&snap
->wait
);
74 vlc_mutex_unlock(&snap
->lock
);
78 picture_t
*vout_snapshot_Get(vout_snapshot_t
*snap
, mtime_t timeout
)
80 const mtime_t deadline
= mdate() + timeout
;
82 vlc_mutex_lock(&snap
->lock
);
85 snap
->request_count
++;
88 while (snap
->is_available
&& !snap
->picture
&&
89 vlc_cond_timedwait(&snap
->wait
, &snap
->lock
, deadline
) == 0);
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 input_thread_t
*input
= (input_thread_t
*)p_vout
->p
->input
;
153 prefix
= str_format(input
, cfg
->prefix_fmt
);
155 filename_sanitize(prefix
);
157 prefix
= strdup("vlcsnap-");
163 bool b_is_folder
= false;
165 if ( vlc_stat( cfg
->path
, &st
) == 0 )
166 b_is_folder
= S_ISDIR( st
.st_mode
);
168 if (cfg
->is_sequential
) {
169 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 timespec_get(&ts
, TIME_UTC
);
187 if (localtime_r(&ts
.tv_sec
, &curtime
) == NULL
)
188 gmtime_r(&ts
.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
, ts
.tv_nsec
/ 1000000,
199 filename
= strdup( cfg
->path
);
206 /* Save the snapshot */
207 FILE *file
= vlc_fopen(filename
, "wb");
209 msg_Err(p_vout
, "Failed to open '%s'", filename
);
213 if (fwrite(image
->p_buffer
, image
->i_buffer
, 1, file
) != 1) {
214 msg_Err(p_vout
, "Failed to write to '%s'", filename
);
230 msg_Err(p_vout
, "could not save snapshot");