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
*);
123 /* Everything is read-only when timer is armed. */
135 void (*detach
) (demux_sys_t
*);
138 static int Open (vlc_object_t
*obj
)
140 demux_t
*demux
= (demux_t
*)obj
;
141 demux_sys_t
*sys
= vlc_malloc(obj
, sizeof (*sys
));
142 if (unlikely(sys
== NULL
))
146 uint16_t width
= 0, height
= 0;
148 switch (var_InheritInteger (demux
, "shm-depth"))
151 chroma
= VLC_CODEC_RGB32
; bpp
= 32;
154 chroma
= VLC_CODEC_RGB24
; bpp
= 24;
157 chroma
= VLC_CODEC_RGB16
; bpp
= 16;
160 chroma
= VLC_CODEC_RGB15
; bpp
= 16;
163 chroma
= VLC_CODEC_RGB8
; bpp
= 8;
166 chroma
= VLC_CODEC_XWD
; bpp
= 0;
173 width
= var_InheritInteger (demux
, "shm-width");
174 height
= var_InheritInteger (demux
, "shm-height");
177 static void (*Demux
) (void *);
179 char *path
= var_InheritString (demux
, "shm-file");
182 sys
->fd
= vlc_open (path
, O_RDONLY
);
184 msg_Err (demux
, "cannot open file %s: %s", path
,
185 vlc_strerror_c(errno
));
190 sys
->detach
= CloseFile
;
195 #ifdef HAVE_SYS_SHM_H
196 sys
->mem
.length
= width
* height
* (bpp
>> 3);
197 if (sys
->mem
.length
== 0)
200 int id
= var_InheritInteger (demux
, "shm-id");
201 if (id
== IPC_PRIVATE
)
203 void *mem
= shmat (id
, NULL
, SHM_RDONLY
);
205 if (mem
== (const void *)(-1))
207 msg_Err (demux
, "cannot attach segment %d: %s", id
,
208 vlc_strerror_c(errno
));
212 sys
->detach
= CloseIPC
;
219 /* Initializes format */
220 float rate
= var_InheritFloat (obj
, "shm-fps");
224 mtime_t interval
= llroundf((float)CLOCK_FREQ
/ rate
);
229 es_format_Init (&fmt
, VIDEO_ES
, chroma
);
230 fmt
.video
.i_chroma
= chroma
;
231 fmt
.video
.i_bits_per_pixel
= bpp
;
232 fmt
.video
.i_sar_num
= fmt
.video
.i_sar_den
= 1;
233 fmt
.video
.i_frame_rate
= 1000 * rate
;
234 fmt
.video
.i_frame_rate_base
= 1000;
235 fmt
.video
.i_visible_width
= fmt
.video
.i_width
= width
;
236 fmt
.video
.i_visible_height
= fmt
.video
.i_height
= height
;
238 sys
->es
= es_out_Add (demux
->out
, &fmt
);
240 /* Initializes demux */
241 if (vlc_timer_create (&sys
->timer
, Demux
, demux
))
243 vlc_timer_schedule (sys
->timer
, false, 1, interval
);
246 demux
->pf_demux
= NULL
;
247 demux
->pf_control
= Control
;
259 static void Close (vlc_object_t
*obj
)
261 demux_t
*demux
= (demux_t
*)obj
;
262 demux_sys_t
*sys
= demux
->p_sys
;
264 vlc_timer_destroy (sys
->timer
);
271 static int Control (demux_t
*demux
, int query
, va_list args
)
275 case DEMUX_GET_POSITION
:
277 float *v
= va_arg (args
, float *);
282 case DEMUX_GET_LENGTH
:
285 int64_t *v
= va_arg (args
, int64_t *);
290 case DEMUX_GET_PTS_DELAY
:
292 int64_t *v
= va_arg (args
, int64_t *);
293 *v
= INT64_C(1000) * var_InheritInteger (demux
, "live-caching");
297 case DEMUX_CAN_PAUSE
:
298 case DEMUX_CAN_CONTROL_PACE
:
299 case DEMUX_CAN_CONTROL_RATE
:
302 bool *v
= va_arg (args
, bool *);
307 case DEMUX_SET_PAUSE_STATE
:
308 return VLC_SUCCESS
; /* should not happen */
315 * Processing callback
317 static void DemuxFile (void *data
)
319 demux_t
*demux
= data
;
320 demux_sys_t
*sys
= demux
->p_sys
;
323 block_t
*block
= block_File(sys
->fd
, true);
326 block
->i_pts
= block
->i_dts
= mdate ();
329 es_out_Control (demux
->out
, ES_OUT_SET_PCR
, block
->i_pts
);
330 es_out_Send (demux
->out
, sys
->es
, block
);
333 static void CloseFile (demux_sys_t
*sys
)
338 #ifdef HAVE_SYS_SHM_H
339 static void DemuxIPC (void *data
)
341 demux_t
*demux
= data
;
342 demux_sys_t
*sys
= demux
->p_sys
;
345 block_t
*block
= block_Alloc (sys
->mem
.length
);
348 memcpy (block
->p_buffer
, sys
->mem
.addr
, sys
->mem
.length
);
349 block
->i_pts
= block
->i_dts
= mdate ();
352 es_out_Control (demux
->out
, ES_OUT_SET_PCR
, block
->i_pts
);
353 es_out_Send (demux
->out
, sys
->es
, block
);
356 static void CloseIPC (demux_sys_t
*sys
)
358 shmdt (sys
->mem
.addr
);