3 * @brief Shared memory frame buffer capture module for VLC media player
5 /*****************************************************************************
6 * Copyright © 2011 Rémi Denis-Courmont
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 ****************************************************************************/
37 #include <vlc_common.h>
38 #include <vlc_demux.h>
40 #include <vlc_plugin.h>
42 #define FPS_TEXT N_("Frame rate")
43 #define FPS_LONGTEXT N_( \
44 "How many times the screen content should be refreshed per second.")
46 #define DEPTH_TEXT N_("Frame buffer depth")
47 #define DEPTH_LONGTEXT N_( \
48 "Pixel depth of the frame buffer, or zero for XWD file")
50 #define WIDTH_TEXT N_("Frame buffer width")
51 #define WIDTH_LONGTEXT N_( \
52 "Pixel width of the frame buffer (ignored for XWD file)")
54 #define HEIGHT_TEXT N_("Frame buffer height")
55 #define HEIGHT_LONGTEXT N_( \
56 "Pixel height of the frame buffer (ignored for XWD file)")
58 #define ID_TEXT N_("Frame buffer segment ID")
59 #define ID_LONGTEXT N_( \
60 "System V shared memory segment ID of the frame buffer " \
61 "(this is ignored if --shm-file is specified).")
63 #define FILE_TEXT N_("Frame buffer file")
64 #define FILE_LONGTEXT N_( \
65 "Path of the memory mapped file of the frame buffer")
67 static int Open (vlc_object_t
*);
68 static void Close (vlc_object_t
*);
70 static const int depths
[] = {
74 static const char *const depth_texts
[] = {
75 N_("XWD file (autodetect)"),
76 N_("8 bits"), N_("15 bits"), N_("16 bits"), N_("24 bits"), N_("32 bits"),
83 set_shortname (N_("Framebuffer input"))
84 set_description (N_("Shared memory framebuffer"))
85 set_category (CAT_INPUT
)
86 set_subcategory (SUBCAT_INPUT_ACCESS
)
87 set_capability ("access_demux", 0)
88 set_callbacks (Open
, Close
)
90 add_float ("shm-fps", 10.0, FPS_TEXT
, FPS_LONGTEXT
, true)
91 add_integer ("shm-depth", 0, DEPTH_TEXT
, DEPTH_LONGTEXT
, true)
92 change_integer_list (depths
, depth_texts
)
94 add_integer ("shm-width", 800, WIDTH_TEXT
, WIDTH_LONGTEXT
, false)
95 change_integer_range (0, 65535)
97 add_integer ("shm-height", 480, HEIGHT_TEXT
, HEIGHT_LONGTEXT
, false)
98 change_integer_range (0, 65535)
101 /* We need to "trust" the memory segment. If it were shrunk while we copy
102 * its content our process may crash - or worse. So we pass the shared
103 * memory location via an unsafe variable rather than the URL. */
104 add_string ("shm-file", NULL
, FILE_TEXT
, FILE_LONGTEXT
, false)
106 #ifdef HAVE_SYS_SHM_H
107 add_integer ("shm-id", (int64_t)IPC_PRIVATE
, ID_TEXT
, ID_LONGTEXT
, false)
113 static int Control (demux_t
*, int, va_list);
114 static void DemuxFile (void *);
115 static void CloseFile (demux_sys_t
*);
116 #ifdef HAVE_SYS_SHM_H
117 static void DemuxIPC (void *);
118 static void CloseIPC (demux_sys_t
*);
120 static void no_detach (demux_sys_t
*);
124 /* Everything is read-only when timer is armed. */
136 void (*detach
) (demux_sys_t
*);
139 static int Open (vlc_object_t
*obj
)
141 demux_t
*demux
= (demux_t
*)obj
;
142 demux_sys_t
*sys
= malloc (sizeof (*sys
));
143 if (unlikely(sys
== NULL
))
145 sys
->detach
= no_detach
;
148 uint16_t width
= 0, height
= 0;
150 switch (var_InheritInteger (demux
, "shm-depth"))
153 chroma
= VLC_CODEC_RGB32
; bpp
= 32;
156 chroma
= VLC_CODEC_RGB24
; bpp
= 24;
159 chroma
= VLC_CODEC_RGB16
; bpp
= 16;
162 chroma
= VLC_CODEC_RGB15
; bpp
= 16;
165 chroma
= VLC_CODEC_RGB8
; bpp
= 8;
168 chroma
= VLC_CODEC_XWD
; bpp
= 0;
175 width
= var_InheritInteger (demux
, "shm-width");
176 height
= var_InheritInteger (demux
, "shm-height");
179 static void (*Demux
) (void *);
181 char *path
= var_InheritString (demux
, "shm-file");
184 sys
->fd
= vlc_open (path
, O_RDONLY
);
186 msg_Err (demux
, "cannot open file %s: %s", path
,
187 vlc_strerror_c(errno
));
192 sys
->detach
= CloseFile
;
197 #ifdef HAVE_SYS_SHM_H
198 sys
->mem
.length
= width
* height
* (bpp
>> 3);
199 if (sys
->mem
.length
== 0)
202 int id
= var_InheritInteger (demux
, "shm-id");
203 if (id
== IPC_PRIVATE
)
205 void *mem
= shmat (id
, NULL
, SHM_RDONLY
);
207 if (mem
== (const void *)(-1))
209 msg_Err (demux
, "cannot attach segment %d: %s", id
,
210 vlc_strerror_c(errno
));
214 sys
->detach
= CloseIPC
;
221 /* Initializes format */
222 float rate
= var_InheritFloat (obj
, "shm-fps");
226 mtime_t interval
= llroundf((float)CLOCK_FREQ
/ rate
);
231 es_format_Init (&fmt
, VIDEO_ES
, chroma
);
232 fmt
.video
.i_chroma
= chroma
;
233 fmt
.video
.i_bits_per_pixel
= bpp
;
234 fmt
.video
.i_sar_num
= fmt
.video
.i_sar_den
= 1;
235 fmt
.video
.i_frame_rate
= 1000 * rate
;
236 fmt
.video
.i_frame_rate_base
= 1000;
237 fmt
.video
.i_visible_width
= fmt
.video
.i_width
= width
;
238 fmt
.video
.i_visible_height
= fmt
.video
.i_height
= height
;
240 sys
->es
= es_out_Add (demux
->out
, &fmt
);
242 /* Initializes demux */
243 if (vlc_timer_create (&sys
->timer
, Demux
, demux
))
245 vlc_timer_schedule (sys
->timer
, false, 1, interval
);
248 demux
->pf_demux
= NULL
;
249 demux
->pf_control
= Control
;
262 static void Close (vlc_object_t
*obj
)
264 demux_t
*demux
= (demux_t
*)obj
;
265 demux_sys_t
*sys
= demux
->p_sys
;
267 vlc_timer_destroy (sys
->timer
);
272 static void no_detach (demux_sys_t
*sys
)
280 static int Control (demux_t
*demux
, int query
, va_list args
)
284 case DEMUX_GET_POSITION
:
286 float *v
= va_arg (args
, float *);
291 case DEMUX_GET_LENGTH
:
294 int64_t *v
= va_arg (args
, int64_t *);
299 case DEMUX_GET_PTS_DELAY
:
301 int64_t *v
= va_arg (args
, int64_t *);
302 *v
= INT64_C(1000) * var_InheritInteger (demux
, "live-caching");
306 case DEMUX_CAN_PAUSE
:
307 case DEMUX_CAN_CONTROL_PACE
:
308 case DEMUX_CAN_CONTROL_RATE
:
311 bool *v
= va_arg (args
, bool *);
316 case DEMUX_SET_PAUSE_STATE
:
317 return VLC_SUCCESS
; /* should not happen */
324 * Processing callback
326 static void DemuxFile (void *data
)
328 demux_t
*demux
= data
;
329 demux_sys_t
*sys
= demux
->p_sys
;
332 block_t
*block
= block_File (sys
->fd
);
335 block
->i_pts
= block
->i_dts
= mdate ();
338 es_out_Control (demux
->out
, ES_OUT_SET_PCR
, block
->i_pts
);
339 es_out_Send (demux
->out
, sys
->es
, block
);
342 static void CloseFile (demux_sys_t
*sys
)
347 #ifdef HAVE_SYS_SHM_H
348 static void DemuxIPC (void *data
)
350 demux_t
*demux
= data
;
351 demux_sys_t
*sys
= demux
->p_sys
;
354 block_t
*block
= block_Alloc (sys
->mem
.length
);
357 memcpy (block
->p_buffer
, sys
->mem
.addr
, sys
->mem
.length
);
358 block
->i_pts
= block
->i_dts
= mdate ();
361 es_out_Control (demux
->out
, ES_OUT_SET_PCR
, block
->i_pts
);
362 es_out_Send (demux
->out
, sys
->es
, block
);
365 static void CloseIPC (demux_sys_t
*sys
)
367 shmdt (sys
->mem
.addr
);