Commit d0682dd3 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

XCB/screen: support windows on other non-default screens

parent b69d64d4
...@@ -100,16 +100,19 @@ vlc_module_end () ...@@ -100,16 +100,19 @@ vlc_module_end ()
*/ */
static void Demux (void *); static void Demux (void *);
static int Control (demux_t *, int, va_list); static int Control (demux_t *, int, va_list);
static es_out_id_t *InitES (demux_t *, uint_fast16_t, uint_fast16_t,
uint_fast8_t);
struct demux_sys_t struct demux_sys_t
{ {
xcb_connection_t *conn; xcb_connection_t *conn;
es_out_id_t *es; es_out_id_t *es;
es_format_t fmt;
mtime_t pts, interval; mtime_t pts, interval;
xcb_window_t root, window; float rate;
xcb_window_t window;
int16_t x, y; int16_t x, y;
uint16_t w, h; uint16_t w, h;
uint16_t cur_w, cur_h;
bool follow_mouse; bool follow_mouse;
/* fmt, es and pts are protected by the lock. The rest is read-only. */ /* fmt, es and pts are protected by the lock. The rest is read-only. */
vlc_mutex_t lock; vlc_mutex_t lock;
...@@ -141,30 +144,30 @@ static int Open (vlc_object_t *obj) ...@@ -141,30 +144,30 @@ static int Open (vlc_object_t *obj)
} }
p_sys->conn = conn; p_sys->conn = conn;
/* Find configured screen */ /* Find configured screen */
const xcb_setup_t *setup = xcb_get_setup (conn); if (!strcmp (demux->psz_access, "screen"))
const xcb_screen_t *scr = NULL;
for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
i.rem > 0; xcb_screen_next (&i))
{ {
if (snum == 0) const xcb_setup_t *setup = xcb_get_setup (conn);
const xcb_screen_t *scr = NULL;
for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
i.rem > 0; xcb_screen_next (&i))
{ {
scr = i.data; if (snum == 0)
break; {
scr = i.data;
break;
}
snum--;
} }
snum--; if (scr == NULL)
} {
if (scr == NULL) msg_Err (obj, "bad X11 screen number");
{ goto error;
msg_Err (obj, "bad X11 screen number"); }
goto error; p_sys->window = scr->root;
} }
/* Determine capture window */
p_sys->root = scr->root;
if (!strcmp (demux->psz_access, "screen"))
p_sys->window = p_sys->root;
else else
/* Determine capture window */
if (!strcmp (demux->psz_access, "window")) if (!strcmp (demux->psz_access, "window"))
{ {
char *end; char *end;
...@@ -186,68 +189,17 @@ static int Open (vlc_object_t *obj) ...@@ -186,68 +189,17 @@ static int Open (vlc_object_t *obj)
p_sys->h = var_CreateGetInteger (obj, "screen-height"); p_sys->h = var_CreateGetInteger (obj, "screen-height");
p_sys->follow_mouse = var_CreateGetBool (obj, "screen-follow-mouse"); p_sys->follow_mouse = var_CreateGetBool (obj, "screen-follow-mouse");
uint32_t chroma = 0;
uint8_t bpp;
for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup),
*end = fmt + xcb_setup_pixmap_formats_length (setup);
fmt < end; fmt++)
{
if (fmt->depth != scr->root_depth)
continue;
bpp = fmt->depth;
switch (fmt->depth)
{
case 32:
if (fmt->bits_per_pixel == 32)
chroma = VLC_CODEC_RGBA;
break;
case 24:
if (fmt->bits_per_pixel == 32)
{
chroma = VLC_CODEC_RGB32;
bpp = 32;
}
else if (fmt->bits_per_pixel == 24)
chroma = VLC_CODEC_RGB24;
break;
case 16:
if (fmt->bits_per_pixel == 16)
chroma = VLC_CODEC_RGB16;
break;
case 15:
if (fmt->bits_per_pixel == 16)
chroma = VLC_CODEC_RGB15;
break;
case 8: /* XXX: screw grey scale! */
if (fmt->bits_per_pixel == 8)
chroma = VLC_CODEC_RGB8;
break;
}
if (chroma != 0)
break;
}
if (!chroma)
{
msg_Err (obj, "unsupported pixmap formats");
goto error;
}
/* Initializes format */ /* Initializes format */
float rate = var_CreateGetFloat (obj, "screen-fps"); p_sys->rate = var_CreateGetFloat (obj, "screen-fps");
if (!rate) if (!p_sys->rate)
goto error; goto error;
p_sys->interval = (float)CLOCK_FREQ / rate; p_sys->interval = (float)CLOCK_FREQ / p_sys->rate;
if (!p_sys->interval) if (!p_sys->interval)
goto error; goto error;
var_Create (obj, "screen-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT); var_Create (obj, "screen-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT);
es_format_Init (&p_sys->fmt, VIDEO_ES, chroma); p_sys->cur_w = 0;
p_sys->fmt.video.i_chroma = chroma; p_sys->cur_h = 0;
p_sys->fmt.video.i_bits_per_pixel = bpp;
p_sys->fmt.video.i_sar_num = p_sys->fmt.video.i_sar_den = 1;
p_sys->fmt.video.i_frame_rate = 1000 * rate;
p_sys->fmt.video.i_frame_rate_base = 1000;
p_sys->es = NULL; p_sys->es = NULL;
p_sys->pts = VLC_TS_INVALID; p_sys->pts = VLC_TS_INVALID;
vlc_mutex_init (&p_sys->lock); vlc_mutex_init (&p_sys->lock);
...@@ -362,24 +314,27 @@ static void Demux (void *data) ...@@ -362,24 +314,27 @@ static void Demux (void *data)
xcb_connection_t *conn = p_sys->conn; xcb_connection_t *conn = p_sys->conn;
/* Update capture region (if needed) */ /* Update capture region (if needed) */
xcb_get_geometry_cookie_t gc = xcb_get_geometry (conn, p_sys->window);
xcb_get_geometry_reply_t *geo =
xcb_get_geometry_reply (conn,
xcb_get_geometry (conn, p_sys->window), NULL);
if (geo == NULL)
{
msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, p_sys->window);
return;
}
xcb_window_t root = geo->root;
int16_t x = p_sys->x, y = p_sys->y; int16_t x = p_sys->x, y = p_sys->y;
xcb_translate_coordinates_cookie_t tc; xcb_translate_coordinates_cookie_t tc;
xcb_query_pointer_cookie_t qc; xcb_query_pointer_cookie_t qc;
if (p_sys->window != p_sys->root) if (p_sys->window != root)
tc = xcb_translate_coordinates (conn, p_sys->window, p_sys->root, tc = xcb_translate_coordinates (conn, p_sys->window, root,
x, y); x, y);
if (p_sys->follow_mouse) if (p_sys->follow_mouse)
qc = xcb_query_pointer (conn, p_sys->window); qc = xcb_query_pointer (conn, p_sys->window);
xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL);
if (geo == NULL)
{
msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, p_sys->window);
return;
}
uint16_t ow = geo->width - x; uint16_t ow = geo->width - x;
uint16_t oh = geo->height - y; uint16_t oh = geo->height - y;
uint16_t w = p_sys->w; uint16_t w = p_sys->w;
...@@ -388,9 +343,10 @@ static void Demux (void *data) ...@@ -388,9 +343,10 @@ static void Demux (void *data)
w = ow; w = ow;
if (h == 0 || h > oh) if (h == 0 || h > oh)
h = oh; h = oh;
uint8_t depth = geo->depth;
free (geo); free (geo);
if (p_sys->window != p_sys->root) if (p_sys->window != root)
{ {
xcb_translate_coordinates_reply_t *coords = xcb_translate_coordinates_reply_t *coords =
xcb_translate_coordinates_reply (conn, tc, NULL); xcb_translate_coordinates_reply (conn, tc, NULL);
...@@ -429,7 +385,7 @@ static void Demux (void *data) ...@@ -429,7 +385,7 @@ static void Demux (void *data)
xcb_get_image_reply_t *img; xcb_get_image_reply_t *img;
img = xcb_get_image_reply (conn, img = xcb_get_image_reply (conn,
xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, p_sys->root, xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, root,
x, y, w, h, ~0), NULL); x, y, w, h, ~0), NULL);
if (img == NULL) if (img == NULL)
return; return;
...@@ -441,14 +397,16 @@ static void Demux (void *data) ...@@ -441,14 +397,16 @@ static void Demux (void *data)
return; return;
vlc_mutex_lock (&p_sys->lock); vlc_mutex_lock (&p_sys->lock);
if (w != p_sys->fmt.video.i_visible_width if (w != p_sys->cur_w || h != p_sys->cur_h)
|| h != p_sys->fmt.video.i_visible_height)
{ {
if (p_sys->es != NULL) if (p_sys->es != NULL)
es_out_Del (demux->out, p_sys->es); es_out_Del (demux->out, p_sys->es);
p_sys->fmt.video.i_visible_width = p_sys->fmt.video.i_width = w; p_sys->es = InitES (demux, w, h, depth);
p_sys->fmt.video.i_visible_height = p_sys->fmt.video.i_height = h; if (p_sys->es != NULL)
p_sys->es = es_out_Add (demux->out, &p_sys->fmt); {
p_sys->cur_w = w;
p_sys->cur_h = h;
}
} }
/* Capture screen */ /* Capture screen */
...@@ -464,3 +422,70 @@ static void Demux (void *data) ...@@ -464,3 +422,70 @@ static void Demux (void *data)
} }
vlc_mutex_unlock (&p_sys->lock); vlc_mutex_unlock (&p_sys->lock);
} }
static es_out_id_t *InitES (demux_t *demux, uint_fast16_t width,
uint_fast16_t height, uint_fast8_t depth)
{
demux_sys_t *p_sys = demux->p_sys;
const xcb_setup_t *setup = xcb_get_setup (p_sys->conn);
uint32_t chroma = 0;
uint8_t bpp;
for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup),
*end = fmt + xcb_setup_pixmap_formats_length (setup);
fmt < end; fmt++)
{
if (fmt->depth != depth)
continue;
bpp = fmt->depth;
switch (fmt->depth)
{
case 32:
if (fmt->bits_per_pixel == 32)
chroma = VLC_CODEC_RGBA;
break;
case 24:
if (fmt->bits_per_pixel == 32)
{
chroma = VLC_CODEC_RGB32;
bpp = 32;
}
else if (fmt->bits_per_pixel == 24)
chroma = VLC_CODEC_RGB24;
break;
case 16:
if (fmt->bits_per_pixel == 16)
chroma = VLC_CODEC_RGB16;
break;
case 15:
if (fmt->bits_per_pixel == 16)
chroma = VLC_CODEC_RGB15;
break;
case 8: /* XXX: screw grey scale! */
if (fmt->bits_per_pixel == 8)
chroma = VLC_CODEC_RGB8;
break;
}
if (chroma != 0)
break;
}
if (!chroma)
{
msg_Err (demux, "unsupported pixmap formats");
return NULL;
}
es_format_t fmt;
es_format_Init (&fmt, VIDEO_ES, chroma);
fmt.video.i_chroma = chroma;
fmt.video.i_bits_per_pixel = bpp;
fmt.video.i_sar_num = fmt.video.i_sar_den = 1;
fmt.video.i_frame_rate = 1000 * p_sys->rate;
fmt.video.i_frame_rate_base = 1000;
fmt.video.i_visible_width = fmt.video.i_width = width;
fmt.video.i_visible_height = fmt.video.i_height = height;
return es_out_Add (demux->out, &fmt);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment