67#include <X11/extensions/Xfixes.h>
71#define MOD_NAME "[screen capture] "
72#define QUEUE_SIZE_MAX 3
80 printf(
"Screen capture\n");
82 printf(
"\t-t screen[:fps=<fps>][:display=<d>][:geometry=WxH[+x[+y]]|:size=WxH]\n");
83 printf(
"\t\t<fps> - preferred grabbing fps (otherwise unlimited)\n");
84 printf(
"\t\tdisplay - display to capture (including the colon!)\n");
85 printf(
"\t\tgeomoetry | size - viewport to use (both option mean the same - size is just a convenient name)\n");
128 XWindowAttributes wa;
136 s->
root = DefaultRootWindow(s->
dpy);
142 XGetWindowAttributes(s->
dpy, DefaultRootWindow(s->
dpy), &wa);
148 pthread_mutex_init(&s->
lock, NULL);
149 pthread_cond_init(&s->
boss_cv, NULL);
185 XFixesCursorImage *cursor =
186 XFixesGetCursorImage (s->
dpy);
189 assert(new_item->
data != NULL);
193 uint32_t *image_data = (uint32_t *)(
void *) new_item->
data->data;
194 for(
int x = 0; x < cursor->width; ++x) {
195 for(
int y = 0; y < cursor->height; ++y) {
196 if(cursor->x + x >= (
int) s->
tile->
width ||
200 uint_fast32_t cursor_pix = cursor->pixels[x + y * cursor->width];
202 int alpha = cursor_pix >> 24 & 0xff;
203 int r1 = cursor_pix >> 16 & 0xff,
204 g1 = cursor_pix >> 8 & 0xff,
205 b1 = cursor_pix >> 0 & 0xff;
206 uint_fast32_t image_pix = image_data[cursor->x + x + (cursor->y + y) * s->
tile->
width];
207 int r2 = image_pix >> 16 & 0xff,
208 g2 = image_pix >> 8 & 0xff,
209 b2 = image_pix >> 0 & 0xff;
210 float scale_image = (float) (255 - alpha)/ 255;
211 float scale_cursor = (float) alpha / 255;
213 image_data[cursor->x + x + (cursor->y + y) * s->
tile->
width] =
214 ((
int) (r1 * scale_cursor + r2 * scale_image) & 0xff) << 16 |
215 ((int) (g1 * scale_cursor + g2 * scale_image) & 0xff) << 8 |
216 ((
int) (b1 * scale_cursor + b2 * scale_image) & 0xff) << 0;
224 new_item->
next = NULL;
226 pthread_mutex_lock(&s->
lock);
243 pthread_cond_signal(&s->
boss_cv);
246 pthread_mutex_unlock(&s->
lock);
258 snprintf((*available_devices)[0].
name,
sizeof (*available_devices)[0].
name,
"Screen capture X11");
260 int framerates[] = {24, 30, 60};
262 snprintf((*available_devices)[0].modes[0].
name,
263 sizeof (*available_devices)[0].modes[0].
name,
265 snprintf((*available_devices)[0].modes[0].
id,
266 sizeof (*available_devices)[0].modes[0].
id,
269 for(
unsigned i = 0; i <
sizeof(framerates) /
sizeof(framerates[0]); i++){
270 snprintf((*available_devices)[0].modes[i + 1].
name,
271 sizeof (*available_devices)[0].modes[0].
name,
274 snprintf((*available_devices)[0].modes[i + 1].
id,
275 sizeof (*available_devices)[0].modes[0].
id,
282 char *tok, *save_ptr;
283 while ((tok = strtok_r(
fmt,
":", &save_ptr)) != NULL) {
285 if (strstr(tok,
"fps=") == tok) {
286 s->
fps = atoi(strchr(tok,
'=') + 1);
287 }
else if (strstr(tok,
"display=") == tok) {
288 char *
val = strchr(tok,
'=') + 1;
290 tok = strtok_r(NULL,
":", &save_ptr);
298 }
else if (strstr(tok,
"geometry=") == tok || strstr(tok,
"size=") == tok) {
299 char *
val = strchr(tok,
'=') + 1;
301 val = strchr(
val,
'x') + 1;
307 if (strchr(
val,
'+')) {
308 val = strchr(
val,
'+') + 1;
311 if (strchr(
val,
'+')) {
312 val = strchr(
val,
'+') + 1;
325 printf(
"vidcap_screen_init\n");
332 if (strcmp(
fmt,
"help") == 0) {
339 printf(
"Unable to allocate screen capture state\n");
345 fprintf(stderr,
"[Screen capture] Compiled without XFixes library, cursor won't be shown!\n");
348 char *fmt_cpy = strdup(
fmt);
365 pthread_mutex_lock(&s->
lock);
367 pthread_cond_signal(&s->
boss_cv);
375 pthread_mutex_unlock(&s->
lock);
390 pthread_mutex_lock(&s->
lock);
395 XDestroyImage(
item->data);
400 pthread_mutex_unlock(&s->
lock);
417 fprintf(stderr,
"Cannot capture screen - unable to initialize!\n");
427 pthread_mutex_lock(&s->
lock);
443 pthread_mutex_unlock(&s->
lock);
453 &
item->data->data[0],
457 XDestroyImage(
item->data);
461 struct timeval cur_time;
463 gettimeofday(&cur_time, NULL);
465 gettimeofday(&cur_time, NULL);
struct audio_frame ** audio
int void(** deleter)(void *))
struct video_frame * vf_alloc(int count)
Allocates blank video frame.
void vf_free(struct video_frame *buf)
Frees video_frame structure.
int vc_get_linesize(unsigned int width, codec_t codec)
This file contains definition of some common audio types.
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_ERROR
general errors
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
#define VIDCAP_INIT_AUDIO_NOT_SUPPORTED
card does not support audio
@ LIBRARY_CLASS_VIDEO_CAPTURE
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
#define IF_NOT_NULL_ELSE(val, default_val)
int get_cpu_core_count(void)
void parallel_pix_conv(int height, char *out, int out_linesize, const char *in, int in_linesize, decoder_t decode, int threads)
decoder_func_t vc_copylineBGRAtoRGB
static _Bool parse_fmt(struct vidcap_screen_x11_state *s, char *fmt)
static int vidcap_screen_x11_init(struct vidcap_params *params, void **state)
static const struct video_capture_info vidcap_screen_x11_info
static void vidcap_screen_x11_finish(void *state)
static void vidcap_screen_x11_probe(struct device_info **available_devices, int *count, void(**deleter)(void *))
static void * grab_thread(void *args)
static void vidcap_screen_x11_done(void *state)
static bool initialize(struct vidcap_screen_x11_state *s)
static struct video_frame * vidcap_screen_x11_grab(void *state, struct audio_frame **audio)
static void show_help(void)
struct used to comunicate with audio capture/playback device
struct grabbed_data * next
Struct tile is an area of video_frame.
char * data
Raw tile data. Pointer must be at least 4B aligned.
unsigned int data_len
length of the data
struct grabbed_data *volatile head
volatile bool should_exit_worker
struct video_frame * frame
volatile bool boss_waiting
volatile bool worker_waiting
struct grabbed_data *volatile *volatile tail
Struct video_frame represents a video frame and contains video description.
enum interlacing_t interlacing
uint32_t tv_diff_usec(struct timeval curr_time, struct timeval prev_time)
@ PROGRESSIVE
progressive frame
@ RGB
RGB 8-bit (packed into 24-bit word)
@ RGBA
RGBA 8-bit, big-endian.
This is an umbrella header for video functions.
const char * vidcap_params_get_fmt(const struct vidcap_params *params)
unsigned int vidcap_params_get_flags(const struct vidcap_params *params)
#define VIDCAP_FLAG_AUDIO_ANY
struct tile * vf_get_tile(struct video_frame *buf, int pos)
Returns pointer to n-th tile from video frame Equivalent to &video_frame::tiles[pos].