Added missing picture_Release() in snapshot.c
[vlc/vlc-skelet.git] / modules / video_output / snapshot.c
blob358a90f24aa7f4e323b53815183c13579b0b3132
1 /*****************************************************************************
2 * snapshot.c : snapshot plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 the VideoLAN team
5 * $Id$
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
35 * python-vlc binding.
36 *****************************************************************************/
38 /*****************************************************************************
39 * Preamble
40 *****************************************************************************/
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
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 /*****************************************************************************
53 * Module descriptor
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 *);
71 vlc_module_begin ()
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)
87 vlc_module_end ()
90 /*****************************************************************************
91 * Local prototypes
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);
97 typedef struct {
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 */
103 } snapshot_t;
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 */
115 /* */
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));
123 if (!sys)
124 return VLC_ENOMEM;
126 char *chroma_fmt = var_InheritString(vd, "vout-snapshot-chroma");
127 const vlc_fourcc_t chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma_fmt);
128 free(chroma_fmt);
130 if (!chroma) {
131 msg_Err(vd, "snapshot-chroma should be 4 characters long");
132 free(sys);
133 return VLC_EGENERIC;
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");
140 free(sys);
141 return VLC_EGENERIC;
144 /* */
145 video_format_t fmt = vd->fmt;
146 fmt.i_chroma = chroma;
147 fmt.i_width = width;
148 fmt.i_height = height;
149 fmt.i_rmask = 0;
150 fmt.i_gmask = 0;
151 fmt.i_bmask = 0;
152 video_format_FixRgb(&fmt);
154 picture_t *picture = picture_NewFromFormat(&fmt);
155 if (!picture) {
156 free(sys);
157 return VLC_EGENERIC;
159 sys->pool = picture_pool_New(1, &picture);
160 if (!sys->pool) {
161 picture_Release(picture);
162 free(sys);
163 return VLC_EGENERIC;
165 sys->data_size = 0;
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;
173 sys->index = 0;
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.");
180 return VLC_EGENERIC;
183 sys->snapshot = calloc(sys->count, sizeof(*sys->snapshot));
185 if (!sys->snapshot)
186 return VLC_ENOMEM;
188 /* Initialize the structures for the circular buffer */
189 for (int index = 0; index < sys->count; index++) {
190 snapshot_t *snapshot = malloc(sizeof(*snapshot));
192 if (!snapshot)
193 return VLC_ENOMEM;
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) {
201 free(snapshot);
202 return VLC_ENOMEM;
204 sys->snapshot[index] = snapshot;
207 /* */
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);
222 if (!sys->input)
223 return VLC_ENOOBJ;
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).",
227 sys->input);
228 return VLC_EGENERIC;
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).",
234 sys->input);
235 return VLC_EGENERIC;
238 /* */
239 vout_display_info_t info = vd->info;
240 info.has_hide_mouse = true;
242 /* */
243 vd->fmt = fmt;
244 vd->info = info;
245 vd->pool = Pool;
246 vd->prepare = NULL;
247 vd->display = Display;
248 vd->control = Control;
249 vd->manage = NULL;
251 /* */
252 vout_display_SendEventFullscreen(vd, false);
253 return VLC_SUCCESS;
256 /* */
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]);
273 free(sys->snapshot);
275 picture_pool_Delete(sys->pool);
277 free(sys);
280 /*****************************************************************************
282 *****************************************************************************/
283 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
285 VLC_UNUSED(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;
294 if (!sys->input)
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)
325 VLC_UNUSED(vd);
326 switch (query) {
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)
330 return VLC_EGENERIC;
331 return VLC_SUCCESS;
333 default:
334 return VLC_EGENERIC;