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, NULL
, WIDTH_TEXT
, WIDTH_LONGTEXT
, false)
80 add_integer("vout-snapshot-height", 200, NULL
, 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, NULL
, 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
*);
95 static int Control(vout_display_t
*, int, va_list);
96 static void Manage (vout_display_t
*);
99 mtime_t date
; /* Presentation time */
100 int width
; /* In pixels */
101 int height
; /* In pixels */
102 int data_size
; /* In bytes */
103 uint8_t *data
; /* Data area */
106 struct vout_display_sys_t
{
107 int count
; /* Size of the cache */
108 snapshot_t
**snapshot
; /* List of available snapshots */
109 int index
; /* Index of the next available list member */
110 int data_size
; /* Size of an image */
111 picture_pool_t
*pool
;
113 input_thread_t
*input
; /* The input thread */
117 static int Open(vlc_object_t
*object
)
119 vout_display_t
*vd
= (vout_display_t
*)object
;
120 vout_display_sys_t
*sys
;
122 /* Allocate instance and initialize some members */
123 vd
->sys
= sys
= malloc(sizeof(*sys
));
127 char *chroma_fmt
= var_InheritString(vd
, "vout-snapshot-chroma");
128 const vlc_fourcc_t chroma
= vlc_fourcc_GetCodecFromString(VIDEO_ES
, chroma_fmt
);
132 msg_Err(vd
, "snapshot-chroma should be 4 characters long");
137 const int width
= var_InheritInteger(vd
, "vout-snapshot-width");
138 const int height
= var_InheritInteger(vd
, "vout-snapshot-height");
139 if (width
<= 0 || height
<= 0) {
140 msg_Err(vd
, "snapshot-width/height are invalid");
146 video_format_t fmt
= vd
->fmt
;
147 fmt
.i_chroma
= chroma
;
149 fmt
.i_height
= height
;
153 video_format_FixRgb(&fmt
);
155 picture_t
*picture
= picture_NewFromFormat(&fmt
);
160 sys
->pool
= picture_pool_New(1, &picture
);
162 picture_Release(picture
);
167 for (int i
= 0; i
< picture
->i_planes
; i
++) {
168 const plane_t
*plane
= &picture
->p
[i
];
169 sys
->data_size
+= plane
->i_visible_pitch
*
170 plane
->i_visible_lines
*
171 plane
->i_pixel_pitch
;
175 sys
->count
= var_InheritInteger(vd
, "vout-snapshot-cache-size");
177 /* FIXME following code leaks in case of error */
179 if (sys
->count
< 2) {
180 msg_Err(vd
, "vout-snapshot-cache-size must be at least 1.");
184 sys
->snapshot
= calloc(sys
->count
, sizeof(*sys
->snapshot
));
189 /* Initialize the structures for the circular buffer */
190 for (int index
= 0; index
< sys
->count
; index
++) {
191 snapshot_t
*snapshot
= malloc(sizeof(*snapshot
));
196 snapshot
->date
= VLC_TS_INVALID
;
197 snapshot
->width
= fmt
.i_width
;
198 snapshot
->height
= fmt
.i_height
;
199 snapshot
->data_size
= sys
->data_size
;
200 snapshot
->data
= malloc(sys
->data_size
);
201 if (!snapshot
->data
) {
205 sys
->snapshot
[index
] = snapshot
;
209 var_Create(vd
, "vout-snapshot-width", VLC_VAR_INTEGER
);
210 var_Create(vd
, "vout-snapshot-height", VLC_VAR_INTEGER
);
211 var_Create(vd
, "vout-snapshot-datasize", VLC_VAR_INTEGER
);
212 var_Create(vd
, "vout-snapshot-cache-size", VLC_VAR_INTEGER
);
213 var_Create(vd
, "vout-snapshot-list-pointer", VLC_VAR_ADDRESS
);
215 var_SetInteger(vd
, "vout-snapshot-width", fmt
.i_width
);
216 var_SetInteger(vd
, "vout-snapshot-height", fmt
.i_height
);
217 var_SetInteger(vd
, "vout-snapshot-datasize", sys
->data_size
);
218 var_SetInteger(vd
, "vout-snapshot-cache-size", sys
->count
);
219 var_SetAddress(vd
, "vout-snapshot-list-pointer", sys
->snapshot
);
221 /* Get the p_input pointer (to access video times) */
222 sys
->input
= vlc_object_find(vd
, VLC_OBJECT_INPUT
, FIND_PARENT
);
226 if (var_Create(sys
->input
, "vout-snapshot-id", VLC_VAR_ADDRESS
)) {
227 msg_Err(vd
, "Cannot create vout-snapshot-id variable in p_input(%p).",
232 /* Register the snapshot vout module at the input level */
233 if (var_SetAddress(sys
->input
, "vout-snapshot-id", vd
)) {
234 msg_Err(vd
, "Cannot register vout-snapshot-id in p_input(%p).",
240 vout_display_info_t info
= vd
->info
;
241 info
.has_hide_mouse
= true;
248 vd
->display
= Display
;
249 vd
->control
= Control
;
253 vout_display_SendEventFullscreen(vd
, false);
258 static void Close(vlc_object_t
*object
)
260 vout_display_t
*vd
= (vout_display_t
*)object
;
261 vout_display_sys_t
*sys
= vd
->sys
;
263 var_Destroy(sys
->input
, "vout-snapshot-id");
265 vlc_object_release(sys
->input
);
266 var_Destroy(vd
, "vout-snapshot-width");
267 var_Destroy(vd
, "vout-snapshot-height");
268 var_Destroy(vd
, "vout-snapshot-datasize");
270 for (int index
= 0 ; index
< sys
->count
; index
++) {
271 free(sys
->snapshot
[index
]->data
);
272 free(sys
->snapshot
[index
]);
276 picture_pool_Delete(sys
->pool
);
281 /*****************************************************************************
283 *****************************************************************************/
284 static picture_pool_t
*Pool(vout_display_t
*vd
, unsigned count
)
287 return vd
->sys
->pool
;
290 /* Return the position in ms from the start of the movie */
291 static mtime_t
snapshot_GetMovietime(vout_display_t
*vd
)
293 vout_display_sys_t
*sys
= vd
->sys
;
296 return VLC_TS_INVALID
;
297 return var_GetTime(sys
->input
, "time") / 1000;
300 static void Display(vout_display_t
*vd
, picture_t
*picture
)
302 vout_display_sys_t
*sys
= vd
->sys
;
304 const int index
= sys
->index
;
306 /* FIXME a lock or an event of some sort would be needed to protect
307 * the content of sys->snapshot vs external users */
308 uint8_t *p_dst
= sys
->snapshot
[index
]->data
;
309 for (int i
= 0; i
< picture
->i_planes
; i
++) {
310 const plane_t
*plane
= &picture
->p
[i
];
311 for( int y
= 0; y
< plane
->i_visible_lines
; y
++) {
312 vlc_memcpy(p_dst
, &plane
->p_pixels
[y
*plane
->i_pitch
],
313 plane
->i_visible_pitch
);
314 p_dst
+= plane
->i_visible_pitch
;
317 sys
->snapshot
[index
]->date
= snapshot_GetMovietime(vd
);
319 sys
->index
= (index
+ 1) % sys
->count
;
322 static int Control(vout_display_t
*vd
, int query
, va_list args
)
326 case VOUT_DISPLAY_CHANGE_FULLSCREEN
: {
327 const vout_display_cfg_t
*cfg
= va_arg(args
, const vout_display_cfg_t
*);
328 if (cfg
->is_fullscreen
)
337 static void Manage (vout_display_t
*vd
)