1 /*****************************************************************************
2 * snapshot.c : snapshot plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 the VideoLAN team
7 * Authors: Olivier Aubert <oaubert@lisi.univ-lyon1.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
25 * This module is a pseudo video output that offers the possibility to
26 * keep a cache of low-res snapshots.
27 * The snapshot structure is defined in include/snapshot.h
28 * In order to access the current snapshot cache, object variables are used:
29 * vout-snapshot-list-pointer : the pointer on the first element in the list
30 * vout-snapshot-datasize : size of a snapshot
31 * (also available in snapshot_t->i_datasize)
32 * vout-snapshot-cache-size : size of the cache list
34 * It is used for the moment by the CORBA module and a specialized
36 *****************************************************************************/
38 /*****************************************************************************
40 *****************************************************************************/
46 #include <vlc_common.h>
47 #include <vlc_plugin.h>
48 #include <vlc_vout_display.h>
49 #include <vlc_picture_pool.h>
50 #include <vlc_input.h>
52 /*****************************************************************************
54 *****************************************************************************/
55 #define WIDTH_TEXT N_("Snapshot width")
56 #define WIDTH_LONGTEXT N_("Width of the snapshot image.")
58 #define HEIGHT_TEXT N_("Snapshot height")
59 #define HEIGHT_LONGTEXT N_("Height of the snapshot image.")
61 #define CHROMA_TEXT N_("Chroma")
62 #define CHROMA_LONGTEXT N_("Output chroma for the snapshot image " \
63 "(a 4 character string, like \"RV32\").")
65 #define CACHE_TEXT N_("Cache size (number of images)")
66 #define CACHE_LONGTEXT N_("Snapshot cache size (number of images to keep).")
68 static int Open (vlc_object_t
*);
69 static void Close(vlc_object_t
*);
72 set_description(N_("Snapshot output"))
73 set_shortname(N_("Snapshot"))
75 set_category(CAT_VIDEO
)
76 set_subcategory(SUBCAT_VIDEO_VOUT
)
77 set_capability("vout display", 0)
79 add_integer("vout-snapshot-width", 320, WIDTH_TEXT
, WIDTH_LONGTEXT
, false)
80 add_integer("vout-snapshot-height", 200, HEIGHT_TEXT
, HEIGHT_LONGTEXT
, false)
81 add_string("vout-snapshot-chroma", "RV32", CHROMA_TEXT
, CHROMA_LONGTEXT
, true)
82 add_deprecated_alias("snapshot-chroma")
83 add_integer("vout-snapshot-cache-size", 50, CACHE_TEXT
, CACHE_LONGTEXT
, true)
84 add_deprecated_alias("snapshot-cache-size")
86 set_callbacks(Open
, Close
)
90 /*****************************************************************************
92 *****************************************************************************/
93 static picture_pool_t
*Pool (vout_display_t
*, unsigned);
94 static void Display(vout_display_t
*, picture_t
*, subpicture_t
*);
95 static int Control(vout_display_t
*, int, va_list);
98 mtime_t date
; /* Presentation time */
99 int width
; /* In pixels */
100 int height
; /* In pixels */
101 int data_size
; /* In bytes */
102 uint8_t *data
; /* Data area */
105 struct vout_display_sys_t
{
106 int count
; /* Size of the cache */
107 snapshot_t
**snapshot
; /* List of available snapshots */
108 int index
; /* Index of the next available list member */
109 int data_size
; /* Size of an image */
110 picture_pool_t
*pool
;
112 input_thread_t
*input
; /* The input thread */
116 static int Open(vlc_object_t
*object
)
118 vout_display_t
*vd
= (vout_display_t
*)object
;
119 vout_display_sys_t
*sys
;
121 /* Allocate instance and initialize some members */
122 vd
->sys
= sys
= malloc(sizeof(*sys
));
126 char *chroma_fmt
= var_InheritString(vd
, "vout-snapshot-chroma");
127 const vlc_fourcc_t chroma
= vlc_fourcc_GetCodecFromString(VIDEO_ES
, chroma_fmt
);
131 msg_Err(vd
, "snapshot-chroma should be 4 characters long");
136 const int width
= var_InheritInteger(vd
, "vout-snapshot-width");
137 const int height
= var_InheritInteger(vd
, "vout-snapshot-height");
138 if (width
<= 0 || height
<= 0) {
139 msg_Err(vd
, "snapshot-width/height are invalid");
145 video_format_t fmt
= vd
->fmt
;
146 fmt
.i_chroma
= chroma
;
148 fmt
.i_height
= height
;
152 video_format_FixRgb(&fmt
);
154 picture_t
*picture
= picture_NewFromFormat(&fmt
);
159 sys
->pool
= picture_pool_New(1, &picture
);
161 picture_Release(picture
);
166 for (int i
= 0; i
< picture
->i_planes
; i
++) {
167 const plane_t
*plane
= &picture
->p
[i
];
168 sys
->data_size
+= plane
->i_visible_pitch
*
169 plane
->i_visible_lines
*
170 plane
->i_pixel_pitch
;
174 sys
->count
= var_InheritInteger(vd
, "vout-snapshot-cache-size");
176 /* FIXME following code leaks in case of error */
178 if (sys
->count
< 2) {
179 msg_Err(vd
, "vout-snapshot-cache-size must be at least 1.");
183 sys
->snapshot
= calloc(sys
->count
, sizeof(*sys
->snapshot
));
188 /* Initialize the structures for the circular buffer */
189 for (int index
= 0; index
< sys
->count
; index
++) {
190 snapshot_t
*snapshot
= malloc(sizeof(*snapshot
));
195 snapshot
->date
= VLC_TS_INVALID
;
196 snapshot
->width
= fmt
.i_width
;
197 snapshot
->height
= fmt
.i_height
;
198 snapshot
->data_size
= sys
->data_size
;
199 snapshot
->data
= malloc(sys
->data_size
);
200 if (!snapshot
->data
) {
204 sys
->snapshot
[index
] = snapshot
;
208 var_Create(vd
, "vout-snapshot-width", VLC_VAR_INTEGER
);
209 var_Create(vd
, "vout-snapshot-height", VLC_VAR_INTEGER
);
210 var_Create(vd
, "vout-snapshot-datasize", VLC_VAR_INTEGER
);
211 var_Create(vd
, "vout-snapshot-cache-size", VLC_VAR_INTEGER
);
212 var_Create(vd
, "vout-snapshot-list-pointer", VLC_VAR_ADDRESS
);
214 var_SetInteger(vd
, "vout-snapshot-width", fmt
.i_width
);
215 var_SetInteger(vd
, "vout-snapshot-height", fmt
.i_height
);
216 var_SetInteger(vd
, "vout-snapshot-datasize", sys
->data_size
);
217 var_SetInteger(vd
, "vout-snapshot-cache-size", sys
->count
);
218 var_SetAddress(vd
, "vout-snapshot-list-pointer", sys
->snapshot
);
220 /* Get the p_input pointer (to access video times) */
221 sys
->input
= vlc_object_find(vd
, VLC_OBJECT_INPUT
, FIND_PARENT
);
225 if (var_Create(sys
->input
, "vout-snapshot-id", VLC_VAR_ADDRESS
)) {
226 msg_Err(vd
, "Cannot create vout-snapshot-id variable in p_input(%p).",
231 /* Register the snapshot vout module at the input level */
232 if (var_SetAddress(sys
->input
, "vout-snapshot-id", vd
)) {
233 msg_Err(vd
, "Cannot register vout-snapshot-id in p_input(%p).",
239 vout_display_info_t info
= vd
->info
;
240 info
.has_hide_mouse
= true;
247 vd
->display
= Display
;
248 vd
->control
= Control
;
252 vout_display_SendEventFullscreen(vd
, false);
257 static void Close(vlc_object_t
*object
)
259 vout_display_t
*vd
= (vout_display_t
*)object
;
260 vout_display_sys_t
*sys
= vd
->sys
;
262 var_Destroy(sys
->input
, "vout-snapshot-id");
264 vlc_object_release(sys
->input
);
265 var_Destroy(vd
, "vout-snapshot-width");
266 var_Destroy(vd
, "vout-snapshot-height");
267 var_Destroy(vd
, "vout-snapshot-datasize");
269 for (int index
= 0 ; index
< sys
->count
; index
++) {
270 free(sys
->snapshot
[index
]->data
);
271 free(sys
->snapshot
[index
]);
275 picture_pool_Delete(sys
->pool
);
280 /*****************************************************************************
282 *****************************************************************************/
283 static picture_pool_t
*Pool(vout_display_t
*vd
, unsigned count
)
286 return vd
->sys
->pool
;
289 /* Return the position in ms from the start of the movie */
290 static mtime_t
snapshot_GetMovietime(vout_display_t
*vd
)
292 vout_display_sys_t
*sys
= vd
->sys
;
295 return VLC_TS_INVALID
;
296 return var_GetTime(sys
->input
, "time") / 1000;
299 static void Display(vout_display_t
*vd
, picture_t
*picture
, subpicture_t
*subpicture
)
301 vout_display_sys_t
*sys
= vd
->sys
;
303 const int index
= sys
->index
;
305 /* FIXME a lock or an event of some sort would be needed to protect
306 * the content of sys->snapshot vs external users */
307 uint8_t *p_dst
= sys
->snapshot
[index
]->data
;
308 for (int i
= 0; i
< picture
->i_planes
; i
++) {
309 const plane_t
*plane
= &picture
->p
[i
];
310 for( int y
= 0; y
< plane
->i_visible_lines
; y
++) {
311 vlc_memcpy(p_dst
, &plane
->p_pixels
[y
*plane
->i_pitch
],
312 plane
->i_visible_pitch
);
313 p_dst
+= plane
->i_visible_pitch
;
316 sys
->snapshot
[index
]->date
= snapshot_GetMovietime(vd
);
318 sys
->index
= (index
+ 1) % sys
->count
;
320 picture_Release(picture
);
323 static int Control(vout_display_t
*vd
, int query
, va_list args
)
327 case VOUT_DISPLAY_CHANGE_FULLSCREEN
: {
328 const vout_display_cfg_t
*cfg
= va_arg(args
, const vout_display_cfg_t
*);
329 if (cfg
->is_fullscreen
)