Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
e8534473
Commit
e8534473
authored
Aug 09, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Converted vout xcb to "vout display" API.
parent
c48d9cfc
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
694 additions
and
590 deletions
+694
-590
modules/video_output/xcb/common.c
modules/video_output/xcb/common.c
+48
-73
modules/video_output/xcb/events.c
modules/video_output/xcb/events.c
+66
-48
modules/video_output/xcb/x11.c
modules/video_output/xcb/x11.c
+219
-158
modules/video_output/xcb/xcb_vlc.h
modules/video_output/xcb/xcb_vlc.h
+19
-11
modules/video_output/xcb/xvideo.c
modules/video_output/xcb/xvideo.c
+342
-300
No files found.
modules/video_output/xcb/common.c
View file @
e8534473
...
...
@@ -34,11 +34,27 @@
#include <xcb/shm.h>
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_vout_window.h>
#include <vlc_vout_display.h>
#include "xcb_vlc.h"
/**
* Check for an error
*/
int
CheckError
(
vout_display_t
*
vd
,
xcb_connection_t
*
conn
,
const
char
*
str
,
xcb_void_cookie_t
ck
)
{
xcb_generic_error_t
*
err
;
err
=
xcb_request_check
(
conn
,
ck
);
if
(
err
)
{
msg_Err
(
vd
,
"%s: X11 error %d"
,
str
,
err
->
error_code
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/**
* Connect to the X server.
*/
...
...
@@ -62,7 +78,7 @@ xcb_connection_t *Connect (vlc_object_t *obj)
* Create a VLC video X window object, find the corresponding X server screen,
* and probe the MIT-SHM extension.
*/
vout_window_t
*
GetWindow
(
vout_
thread_t
*
obj
,
vout_window_t
*
GetWindow
(
vout_
display_t
*
vd
,
xcb_connection_t
*
conn
,
const
xcb_screen_t
**
restrict
pscreen
,
bool
*
restrict
pshm
)
...
...
@@ -73,14 +89,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
memset
(
&
wnd_cfg
,
0
,
sizeof
(
wnd_cfg
)
);
wnd_cfg
.
type
=
VOUT_WINDOW_TYPE_XID
;
wnd_cfg
.
width
=
obj
->
i_window_width
;
wnd_cfg
.
height
=
obj
->
i_window_height
;
vout_window_t
*
wnd
=
vout_window_New
(
VLC_OBJECT
(
obj
),
NULL
,
&
wnd_cfg
);
wnd_cfg
.
width
=
vd
->
cfg
->
display
.
width
;
wnd_cfg
.
height
=
vd
->
cfg
->
display
.
height
;
vout_window_t
*
wnd
=
vout_display_NewWindow
(
vd
,
&
wnd_cfg
);
if
(
wnd
==
NULL
)
{
msg_Err
(
obj
,
"parent window not available"
);
msg_Err
(
vd
,
"parent window not available"
);
return
NULL
;
}
else
...
...
@@ -92,7 +107,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
geo
=
xcb_get_geometry_reply
(
conn
,
ck
,
NULL
);
if
(
geo
==
NULL
)
{
msg_Err
(
obj
,
"parent window not valid"
);
msg_Err
(
vd
,
"parent window not valid"
);
goto
error
;
}
root
=
geo
->
root
;
...
...
@@ -116,13 +131,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
if
(
screen
==
NULL
)
{
msg_Err
(
obj
,
"parent window screen not found"
);
msg_Err
(
vd
,
"parent window screen not found"
);
goto
error
;
}
msg_Dbg
(
obj
,
"using screen 0x%"
PRIx32
,
root
);
msg_Dbg
(
vd
,
"using screen 0x%"
PRIx32
,
root
);
/* Check MIT-SHM shared memory support */
bool
shm
=
var_CreateGetBool
(
obj
,
"x11-shm"
)
>
0
;
bool
shm
=
var_CreateGetBool
(
vd
,
"x11-shm"
)
>
0
;
if
(
shm
)
{
xcb_shm_query_version_cookie_t
ck
;
...
...
@@ -132,8 +147,8 @@ vout_window_t *GetWindow (vout_thread_t *obj,
r
=
xcb_shm_query_version_reply
(
conn
,
ck
,
NULL
);
if
(
!
r
)
{
msg_Err
(
obj
,
"shared memory (MIT-SHM) not available"
);
msg_Warn
(
obj
,
"display will be slow"
);
msg_Err
(
vd
,
"shared memory (MIT-SHM) not available"
);
msg_Warn
(
vd
,
"display will be slow"
);
shm
=
false
;
}
free
(
r
);
...
...
@@ -144,7 +159,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
return
wnd
;
error:
vout_
window_Delete
(
wnd
);
vout_
display_DeleteWindow
(
vd
,
wnd
);
return
NULL
;
}
...
...
@@ -168,19 +183,22 @@ int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn,
/**
* Initialize a picture buffer as shared memory, according to the video output
* format. If a
XCB connection pointer is supplied
, the segment is attached to
* format. If a
attach is true
, the segment is attached to
* the X server (MIT-SHM extension).
*/
int
Picture
Alloc
(
vout_thread_t
*
vout
,
picture_t
*
pic
,
size_t
size
,
xcb_connection_t
*
conn
)
int
Picture
ResourceAlloc
(
vout_display_t
*
vd
,
picture_resource_t
*
res
,
size_t
size
,
xcb_connection_t
*
conn
,
bool
attach
)
{
assert
(
pic
->
i_status
==
FREE_PICTURE
);
res
->
p_sys
=
malloc
(
sizeof
(
*
res
->
p_sys
));
if
(
!
res
->
p_sys
)
return
VLC_EGENERIC
;
/* Allocate shared memory segment */
int
id
=
shmget
(
IPC_PRIVATE
,
size
,
IPC_CREAT
|
0700
);
if
(
id
==
-
1
)
{
msg_Err
(
vout
,
"shared memory allocation error: %m"
);
msg_Err
(
vd
,
"shared memory allocation error: %m"
);
free
(
res
->
p_sys
);
return
VLC_EGENERIC
;
}
...
...
@@ -188,13 +206,14 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
void
*
shm
=
shmat
(
id
,
NULL
,
0
/* read/write */
);
if
(
-
1
==
(
intptr_t
)
shm
)
{
msg_Err
(
v
out
,
"shared memory attachment error: %m"
);
msg_Err
(
v
d
,
"shared memory attachment error: %m"
);
shmctl
(
id
,
IPC_RMID
,
0
);
free
(
res
->
p_sys
);
return
VLC_EGENERIC
;
}
xcb_shm_seg_t
segment
;
if
(
conn
!=
NULL
)
if
(
attach
)
{
/* Attach the segment to X */
xcb_void_cookie_t
ck
;
...
...
@@ -202,9 +221,9 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
segment
=
xcb_generate_id
(
conn
);
ck
=
xcb_shm_attach_checked
(
conn
,
segment
,
id
,
1
);
if
(
CheckError
(
v
out
,
"shared memory server-side error"
,
ck
))
if
(
CheckError
(
v
d
,
conn
,
"shared memory server-side error"
,
ck
))
{
msg_Info
(
v
out
,
"using buggy X11 server - SSH proxying?"
);
msg_Info
(
v
d
,
"using buggy X11 server - SSH proxying?"
);
segment
=
0
;
}
}
...
...
@@ -212,67 +231,23 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
segment
=
0
;
shmctl
(
id
,
IPC_RMID
,
0
);
pic
->
p_sys
=
(
void
*
)(
uintptr_t
)
segment
;
pic
->
p
->
p_pixels
=
shm
;
pic
->
i_status
=
DESTROYED_PICTURE
;
pic
->
i_type
=
DIRECT_PICTURE
;
res
->
p_sys
->
segment
=
segment
;
res
->
p
->
p_pixels
=
shm
;
return
VLC_SUCCESS
;
}
/**
* Release picture private data: detach the shared memory segment.
*/
void
Picture
Free
(
picture_t
*
pic
,
xcb_connection_t
*
conn
)
void
Picture
ResourceFree
(
picture_resource_t
*
res
,
xcb_connection_t
*
conn
)
{
xcb_shm_seg_t
segment
=
(
uintptr_t
)
pic
->
p_sys
;
xcb_shm_seg_t
segment
=
res
->
p_sys
->
segment
;
if
(
segment
!=
0
)
{
assert
(
conn
!=
NULL
);
xcb_shm_detach
(
conn
,
segment
);
}
shmdt
(
pic
->
p
->
p_pixels
);
shmdt
(
res
->
p
->
p_pixels
);
}
/**
* Video output thread management stuff.
* FIXME: Much of this should move to core
*/
void
CommonManage
(
vout_thread_t
*
vout
)
{
if
(
vout
->
i_changes
&
VOUT_SCALE_CHANGE
)
{
vout
->
b_autoscale
=
var_GetBool
(
vout
,
"autoscale"
);
vout
->
i_zoom
=
ZOOM_FP_FACTOR
;
vout
->
i_changes
&=
~
VOUT_SCALE_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
if
(
vout
->
i_changes
&
VOUT_ZOOM_CHANGE
)
{
vout
->
b_autoscale
=
false
;
vout
->
i_zoom
=
var_GetFloat
(
vout
,
"scale"
)
*
ZOOM_FP_FACTOR
;
vout
->
i_changes
&=
~
VOUT_ZOOM_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
if
(
vout
->
i_changes
&
VOUT_CROP_CHANGE
)
{
vout
->
fmt_out
.
i_x_offset
=
vout
->
fmt_in
.
i_x_offset
;
vout
->
fmt_out
.
i_y_offset
=
vout
->
fmt_in
.
i_y_offset
;
vout
->
fmt_out
.
i_visible_width
=
vout
->
fmt_in
.
i_visible_width
;
vout
->
fmt_out
.
i_visible_height
=
vout
->
fmt_in
.
i_visible_height
;
vout
->
i_changes
&=
~
VOUT_CROP_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
if
(
vout
->
i_changes
&
VOUT_ASPECT_CHANGE
)
{
vout
->
fmt_out
.
i_aspect
=
vout
->
fmt_in
.
i_aspect
;
vout
->
fmt_out
.
i_sar_num
=
vout
->
fmt_in
.
i_sar_num
;
vout
->
fmt_out
.
i_sar_den
=
vout
->
fmt_in
.
i_sar_den
;
vout
->
output
.
i_aspect
=
vout
->
fmt_in
.
i_aspect
;
vout
->
i_changes
&=
~
VOUT_ASPECT_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
}
modules/video_output/xcb/events.c
View file @
e8534473
...
...
@@ -30,7 +30,7 @@
#include <xcb/xcb.h>
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_vout
_display
.h>
#include "xcb_vlc.h"
...
...
@@ -39,76 +39,67 @@
* Otherwise, we'd var_OrInteger() and var_NandInteger() functions...
*/
static
void
HandleButtonPress
(
vout_thread_t
*
vout
,
/* FIXME we assume direct mapping between XCB and VLC */
static
void
HandleButtonPress
(
vout_display_t
*
vd
,
xcb_button_press_event_t
*
ev
)
{
unsigned
buttons
=
var_GetInteger
(
vout
,
"mouse-button-down"
);
buttons
|=
(
1
<<
(
ev
->
detail
-
1
));
var_SetInteger
(
vout
,
"mouse-button-down"
,
buttons
);
vout_display_SendEventMousePressed
(
vd
,
ev
->
detail
-
1
);
}
static
void
HandleButtonRelease
(
vout_
thread_t
*
vout
,
static
void
HandleButtonRelease
(
vout_
display_t
*
vd
,
xcb_button_release_event_t
*
ev
)
{
unsigned
buttons
=
var_GetInteger
(
vout
,
"mouse-button-down"
);
buttons
&=
~
(
1
<<
(
ev
->
detail
-
1
));
var_SetInteger
(
vout
,
"mouse-button-down"
,
buttons
);
switch
(
ev
->
detail
)
{
case
1
:
/* left mouse button */
var_SetBool
(
vout
,
"mouse-clicked"
,
true
);
var_SetBool
(
vout
->
p_libvlc
,
"intf-popupmenu"
,
false
);
break
;
case
3
:
var_SetBool
(
vout
->
p_libvlc
,
"intf-popupmenu"
,
true
);
break
;
}
vout_display_SendEventMouseReleased
(
vd
,
ev
->
detail
-
1
);
}
static
void
HandleMotionNotify
(
vout_
thread_t
*
vout
,
static
void
HandleMotionNotify
(
vout_
display_t
*
vd
,
xcb_motion_notify_event_t
*
ev
)
{
unsigned
x
,
y
,
width
,
height
;
int
v
;
vout_PlacePicture
(
vout
,
vout
->
output
.
i_width
,
vout
->
output
.
i_height
,
&
x
,
&
y
,
&
width
,
&
height
);
v
=
vout
->
fmt_in
.
i_x_offset
+
((
ev
->
event_x
-
x
)
*
vout
->
fmt_in
.
i_visible_width
/
width
);
if
(
v
<
0
)
v
=
0
;
/* to the left of the picture */
else
if
((
unsigned
)
v
>
vout
->
fmt_in
.
i_width
)
v
=
vout
->
fmt_in
.
i_width
;
/* to the right of the picture */
var_SetInteger
(
vout
,
"mouse-x"
,
v
);
v
=
vout
->
fmt_in
.
i_y_offset
+
((
ev
->
event_y
-
y
)
*
vout
->
fmt_in
.
i_visible_height
/
height
);
if
(
v
<
0
)
v
=
0
;
/* above the picture */
else
if
((
unsigned
)
v
>
vout
->
fmt_in
.
i_height
)
v
=
vout
->
fmt_in
.
i_height
;
/* below the picture */
var_SetInteger
(
vout
,
"mouse-y"
,
v
);
vout_display_place_t
place
;
/* TODO it could be saved */
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
if
(
place
.
width
<=
0
||
place
.
height
<=
0
)
return
;
const
int
x
=
vd
->
source
.
i_x_offset
+
(
int64_t
)(
ev
->
event_x
-
0
*
place
.
x
)
*
vd
->
source
.
i_visible_width
/
place
.
width
;
const
int
y
=
vd
->
source
.
i_y_offset
+
(
int64_t
)(
ev
->
event_y
-
0
*
place
.
y
)
*
vd
->
source
.
i_visible_height
/
place
.
height
;
/* TODO show the cursor ? */
if
(
x
>=
vd
->
source
.
i_x_offset
&&
x
<
vd
->
source
.
i_x_offset
+
vd
->
source
.
i_visible_width
&&
y
>=
vd
->
source
.
i_y_offset
&&
y
<
vd
->
source
.
i_y_offset
+
vd
->
source
.
i_visible_height
)
vout_display_SendEventMouseMoved
(
vd
,
x
,
y
);
}
static
void
HandleParentStructure
(
vout_display_t
*
vd
,
xcb_configure_notify_event_t
*
ev
)
{
if
(
ev
->
width
!=
vd
->
cfg
->
display
.
width
||
ev
->
height
!=
vd
->
cfg
->
display
.
height
)
vout_display_SendEventDisplaySize
(
vd
,
ev
->
width
,
ev
->
height
);
}
/**
* Process an X11 event.
*/
int
ProcessEvent
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
static
int
ProcessEvent
(
vout_display_t
*
vd
,
xcb_window_t
window
,
xcb_generic_event_t
*
ev
)
{
switch
(
ev
->
response_type
&
0x7f
)
{
case
XCB_BUTTON_PRESS
:
HandleButtonPress
(
v
out
,
(
xcb_button_press_event_t
*
)
ev
);
HandleButtonPress
(
v
d
,
(
xcb_button_press_event_t
*
)
ev
);
break
;
case
XCB_BUTTON_RELEASE
:
HandleButtonRelease
(
v
out
,
(
xcb_button_release_event_t
*
)
ev
);
HandleButtonRelease
(
v
d
,
(
xcb_button_release_event_t
*
)
ev
);
break
;
case
XCB_MOTION_NOTIFY
:
HandleMotionNotify
(
v
out
,
(
xcb_motion_notify_event_t
*
)
ev
);
HandleMotionNotify
(
v
d
,
(
xcb_motion_notify_event_t
*
)
ev
);
break
;
case
XCB_CONFIGURE_NOTIFY
:
...
...
@@ -117,14 +108,41 @@ int ProcessEvent (vout_thread_t *vout, xcb_connection_t *conn,
(
xcb_configure_notify_event_t
*
)
ev
;
assert
(
cn
->
window
!=
window
);
HandleParentStructure
(
v
out
,
conn
,
window
,
cn
);
HandleParentStructure
(
v
d
,
cn
);
break
;
}
/* FIXME I am not sure it is the right one */
case
XCB_DESTROY_NOTIFY
:
vout_display_SendEventClose
(
vd
);
break
;
default:
msg_Dbg
(
v
out
,
"unhandled event %"
PRIu8
,
ev
->
response_type
);
msg_Dbg
(
v
d
,
"unhandled event %"
PRIu8
,
ev
->
response_type
);
}
free
(
ev
);
return
VLC_SUCCESS
;
}
/**
* Process incoming X events.
*/
int
ManageEvent
(
vout_display_t
*
vd
,
xcb_connection_t
*
conn
,
xcb_window_t
window
)
{
xcb_generic_event_t
*
ev
;
while
((
ev
=
xcb_poll_for_event
(
conn
))
!=
NULL
)
ProcessEvent
(
vd
,
window
,
ev
);
if
(
xcb_connection_has_error
(
conn
))
{
msg_Err
(
vd
,
"X server failure"
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
modules/video_output/xcb/x11.c
View file @
e8534473
...
...
@@ -32,8 +32,8 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout.h>
#include <vlc_
vout_window
.h>
#include <vlc_vout
_display
.h>
#include <vlc_
picture_pool
.h>
#include "xcb_vlc.h"
...
...
@@ -57,7 +57,7 @@ vlc_module_begin ()
set_description
(
N_
(
"(Experimental) XCB video output"
))
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_capability
(
"v
ideo output
"
,
0
)
set_capability
(
"v
out display
"
,
0
)
set_callbacks
(
Open
,
Close
)
add_string
(
"x11-display"
,
NULL
,
NULL
,
...
...
@@ -65,7 +65,13 @@ vlc_module_begin ()
add_bool
(
"x11-shm"
,
true
,
NULL
,
SHM_TEXT
,
SHM_LONGTEXT
,
true
)
vlc_module_end
()
struct
vout_sys_t
/* It must be large enough to absorb the server display jitter but it is
* useless to used a too large value, direct rendering cannot be used with
* xcb x11
*/
#define MAX_PICTURES (3)
struct
vout_display_sys_t
{
xcb_connection_t
*
conn
;
vout_window_t
*
embed
;
/* VLC window (when windowed) */
...
...
@@ -77,40 +83,29 @@ struct vout_sys_t
uint8_t
pad
;
/* scanline pad */
uint8_t
depth
;
/* useful bits per pixel */
uint8_t
byte_order
;
/* server byte order */
};
static
int
Init
(
vout_thread_t
*
);
static
void
Deinit
(
vout_thread_t
*
);
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
static
int
Manage
(
vout_thread_t
*
);
static
int
Control
(
vout_thread_t
*
,
int
,
va_list
);
int
CheckError
(
vout_thread_t
*
vout
,
const
char
*
str
,
xcb_void_cookie_t
ck
)
{
xcb_generic_error_t
*
err
;
picture_pool_t
*
pool
;
/* picture pool */
picture_resource_t
resource
[
MAX_PICTURES
];
};
err
=
xcb_request_check
(
vout
->
p_sys
->
conn
,
ck
);
if
(
err
)
{
msg_Err
(
vout
,
"%s: X11 error %d"
,
str
,
err
->
error_code
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
static
picture_t
*
Get
(
vout_display_t
*
);
static
void
Display
(
vout_display_t
*
,
picture_t
*
);
static
int
Control
(
vout_display_t
*
,
int
,
va_list
);
static
void
Manage
(
vout_display_t
*
);
#define p_vout vout
static
void
ResetPictures
(
vout_display_t
*
);
/**
* Probe the X server.
*/
static
int
Open
(
vlc_object_t
*
obj
)
{
vout_
thread_t
*
vout
=
(
vout_thread
_t
*
)
obj
;
vout_sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
vout_
display_t
*
vd
=
(
vout_display
_t
*
)
obj
;
vout_
display_
sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
v
out
->
p_
sys
=
p_sys
;
v
d
->
sys
=
p_sys
;
/* Connect to X */
p_sys
->
conn
=
Connect
(
obj
);
...
...
@@ -122,7 +117,7 @@ static int Open (vlc_object_t *obj)
/* Get window */
const
xcb_screen_t
*
scr
;
p_sys
->
embed
=
GetWindow
(
v
out
,
p_sys
->
conn
,
&
scr
,
&
p_sys
->
shm
);
p_sys
->
embed
=
GetWindow
(
v
d
,
p_sys
->
conn
,
&
scr
,
&
p_sys
->
shm
);
if
(
p_sys
->
embed
==
NULL
)
{
xcb_disconnect
(
p_sys
->
conn
);
...
...
@@ -133,6 +128,9 @@ static int Open (vlc_object_t *obj)
const
xcb_setup_t
*
setup
=
xcb_get_setup
(
p_sys
->
conn
);
p_sys
->
byte_order
=
setup
->
image_byte_order
;
/* */
video_format_t
fmt_pic
=
vd
->
fmt
;
/* Determine our video format. Normally, this is done in pf_init(), but
* this plugin always uses the same format for a given X11 screen. */
xcb_visualid_t
vid
=
0
;
...
...
@@ -213,12 +211,12 @@ static int Open (vlc_object_t *obj)
if
(
!
vid
)
continue
;
/* The screen does not *really* support this depth */
vout
->
fmt_out
.
i_chroma
=
vout
->
output
.
i_chroma
=
chroma
;
fmt_pic
.
i_chroma
=
chroma
;
if
(
!
gray
)
{
vout
->
fmt_out
.
i_rmask
=
vout
->
output
.
i_rmask
=
vt
->
red_mask
;
vout
->
fmt_out
.
i_gmask
=
vout
->
output
.
i_gmask
=
vt
->
green_mask
;
vout
->
fmt_out
.
i_bmask
=
vout
->
output
.
i_bmask
=
vt
->
blue_mask
;
fmt_pic
.
i_rmask
=
vt
->
red_mask
;
fmt_pic
.
i_gmask
=
vt
->
green_mask
;
fmt_pic
.
i_bmask
=
vt
->
blue_mask
;
}
p_sys
->
bpp
=
fmt
->
bits_per_pixel
;
p_sys
->
pad
=
fmt
->
scanline_pad
;
...
...
@@ -227,12 +225,12 @@ static int Open (vlc_object_t *obj)
if
(
depth
==
0
)
{
msg_Err
(
v
out
,
"no supported pixmap formats or visual types"
);
msg_Err
(
v
d
,
"no supported pixmap formats or visual types"
);
goto
error
;
}
msg_Dbg
(
v
out
,
"using X11 visual ID 0x%"
PRIx32
,
vid
);
msg_Dbg
(
v
out
,
" %"
PRIu8
" bits per pixels, %"
PRIu8
" bits line pad"
,
msg_Dbg
(
v
d
,
"using X11 visual ID 0x%"
PRIx32
,
vid
);
msg_Dbg
(
v
d
,
" %"
PRIu8
" bits per pixels, %"
PRIu8
" bits line pad"
,
p_sys
->
bpp
,
p_sys
->
pad
);
/* Create colormap (needed to select non-default visual) */
...
...
@@ -263,23 +261,41 @@ static int Open (vlc_object_t *obj)
p_sys
->
embed
->
handle
.
xid
,
0
,
0
,
1
,
1
,
0
,
XCB_WINDOW_CLASS_INPUT_OUTPUT
,
vid
,
mask
,
values
);
if
(
CheckError
(
v
out
,
"cannot create X11 window"
,
c
))
if
(
CheckError
(
v
d
,
p_sys
->
conn
,
"cannot create X11 window"
,
c
))
goto
error
;
p_sys
->
window
=
window
;
msg_Dbg
(
v
out
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
msg_Dbg
(
v
d
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
xcb_map_window
(
p_sys
->
conn
,
window
);
}
/* Create graphic context (I wonder why the heck do we need this) */
p_sys
->
gc
=
xcb_generate_id
(
p_sys
->
conn
);
xcb_create_gc
(
p_sys
->
conn
,
p_sys
->
gc
,
p_sys
->
window
,
0
,
NULL
);
msg_Dbg
(
vout
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
msg_Dbg
(
vd
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
/* */
p_sys
->
pool
=
NULL
;
/* */
vout_display_info_t
info
=
vd
->
info
;
info
.
has_pictures_invalid
=
true
;
/* Setup vout_display_t once everything is fine */
vd
->
fmt
=
fmt_pic
;
vd
->
info
=
info
;
vd
->
get
=
Get
;
vd
->
prepare
=
NULL
;
vd
->
display
=
Display
;
vd
->
control
=
Control
;
vd
->
manage
=
Manage
;
/* */
unsigned
width
,
height
;
if
(
!
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
vout_display_SendEventDisplaySize
(
vd
,
width
,
height
);
vout_display_SendEventFullscreen
(
vd
,
false
);
vout
->
pf_init
=
Init
;
vout
->
pf_end
=
Deinit
;
vout
->
pf_display
=
Display
;
vout
->
pf_manage
=
Manage
;
vout
->
pf_control
=
Control
;
return
VLC_SUCCESS
;
error:
...
...
@@ -293,174 +309,219 @@ error:
*/
static
void
Close
(
vlc_object_t
*
obj
)
{
vout_
thread_t
*
vout
=
(
vout_thread
_t
*
)
obj
;
vout_
sys_t
*
p_sys
=
vout
->
p_
sys
;
vout_
display_t
*
vd
=
(
vout_display
_t
*
)
obj
;
vout_
display_sys_t
*
p_sys
=
vd
->
sys
;
vout_window_Delete
(
p_sys
->
embed
);
ResetPictures
(
vd
);
vout_display_DeleteWindow
(
vd
,
p_sys
->
embed
);
/* colormap and window are garbage-collected by X */
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
}
/**
*
Allocate drawable window and picture buffers.
*
Return a direct buffer
*/
static
int
Init
(
vout_thread_t
*
vout
)
static
picture_t
*
Get
(
vout_display_t
*
vd
)
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
unsigned
x
,
y
,
width
,
height
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
return
VLC_EGENERIC
;
vout_PlacePicture
(
vout
,
width
,
height
,
&
x
,
&
y
,
&
width
,
&
height
);
if
(
!
p_sys
->
pool
)
{
vout_display_place_t
place
;
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
/* */
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
,
place
.
width
,
place
.
height
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
/* FIXME: I don't get the subtlety between output and fmt_out here */
vout
->
fmt_out
.
i_visible_width
=
width
;
vout
->
fmt_out
.
i_visible_height
=
height
;
vout
->
fmt_out
.
i_sar_num
=
vout
->
fmt_out
.
i_sar_den
=
1
;
vout
->
output
.
i_width
=
vout
->
fmt_out
.
i_width
=
width
*
vout
->
fmt_in
.
i_width
/
vout
->
fmt_in
.
i_visible_width
;
vout
->
output
.
i_height
=
vout
->
fmt_out
.
i_height
=
height
*
vout
->
fmt_in
.
i_height
/
vout
->
fmt_in
.
i_visible_height
;
vout
->
fmt_out
.
i_x_offset
=
width
*
vout
->
fmt_in
.
i_x_offset
/
vout
->
fmt_in
.
i_visible_width
;
p_vout
->
fmt_out
.
i_y_offset
=
height
*
vout
->
fmt_in
.
i_y_offset
/
vout
->
fmt_in
.
i_visible_height
;
assert
(
height
>
0
);
vout
->
output
.
i_aspect
=
vout
->
fmt_out
.
i_aspect
=
width
*
VOUT_ASPECT_FACTOR
/
height
;
/* Allocate picture buffers */
I_OUTPUTPICTURES
=
0
;
for
(
size_t
index
=
0
;
I_OUTPUTPICTURES
<
2
;
index
++
)
picture_t
*
pic
=
picture_NewFromFormat
(
&
vd
->
fmt
);
if
(
!
pic
)
return
NULL
;
assert
(
pic
->
i_planes
==
1
);
memset
(
p_sys
->
resource
,
0
,
sizeof
(
p_sys
->
resource
));
unsigned
count
;
picture_t
*
pic_array
[
MAX_PICTURES
];
for
(
count
=
0
;
count
<
MAX_PICTURES
;
count
++
)
{
picture_t
*
pic
=
vout
->
p_picture
+
index
;
picture_resource_t
*
res
=
&
p_sys
->
resource
[
count
]
;
if
(
index
>
sizeof
(
vout
->
p_picture
)
/
sizeof
(
pic
))
res
->
p
->
i_lines
=
pic
->
p
->
i_lines
;
res
->
p
->
i_pitch
=
pic
->
p
->
i_pitch
;
if
(
PictureResourceAlloc
(
vd
,
res
,
res
->
p
->
i_pitch
*
res
->
p
->
i_lines
,
p_sys
->
conn
,
p_sys
->
shm
))
break
;
if
(
pic
->
i_status
!=
FREE_PICTURE
)
continue
;
picture_Setup
(
pic
,
vout
->
output
.
i_chroma
,
vout
->
output
.
i_width
,
vout
->
output
.
i_height
,
vout
->
output
.
i_aspect
);
if
(
PictureAlloc
(
vout
,
pic
,
pic
->
p
->
i_pitch
*
pic
->
p
->
i_lines
,
p_sys
->
shm
?
p_sys
->
conn
:
NULL
))
pic_array
[
count
]
=
picture_NewFromResource
(
&
vd
->
fmt
,
res
);
if
(
!
pic_array
[
count
])
{
PictureResourceFree
(
res
,
p_sys
->
conn
);
memset
(
res
,
0
,
sizeof
(
*
res
));
break
;
PP_OUTPUTPICTURE
[
I_OUTPUTPICTURES
++
]
=
pic
;
}
}
picture_Release
(
pic
);
if
(
count
==
0
)
return
NULL
;
p_sys
->
pool
=
picture_pool_New
(
count
,
pic_array
);
if
(
!
p_sys
->
pool
)
{
/* TODO release picture resources */
return
NULL
;
}
/* FIXME should also do it in case of error ? */
xcb_flush
(
p_sys
->
conn
);
return
VLC_SUCCESS
;
}
}
/**
* Free picture buffers.
*/
static
void
Deinit
(
vout_thread_t
*
vout
)
{
for
(
int
i
=
0
;
i
<
I_OUTPUTPICTURES
;
i
++
)
PictureFree
(
PP_OUTPUTPICTURE
[
i
],
vout
->
p_sys
->
conn
);
return
picture_pool_Get
(
p_sys
->
pool
);
}
/**
* Sends an image to the X server.
*/
static
void
Display
(
vout_
thread_t
*
vout
,
picture_t
*
pic
)
static
void
Display
(
vout_
display_t
*
vd
,
picture_t
*
pic
)
{
vout_
sys_t
*
p_sys
=
vout
->
p_
sys
;
xcb_shm_seg_t
segment
=
(
uintptr_t
)
pic
->
p_sys
;
vout_
display_sys_t
*
p_sys
=
vd
->
sys
;
xcb_shm_seg_t
segment
=
pic
->
p_sys
->
segment
;
if
(
segment
!=
0
)
xcb_shm_put_image
(
p_sys
->
conn
,
p_sys
->
window
,
p_sys
->
gc
,
/* real width */
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
/* real height */
pic
->
p
->
i_lines
,
/* x */
v
out
->
fmt_ou
t
.
i_x_offset
,
/* y */
v
out
->
fmt_ou
t
.
i_y_offset
,
/* width */
v
out
->
fmt_ou
t
.
i_visible_width
,
/* height */
v
out
->
fmt_ou
t
.
i_visible_height
,
/* x */
v
d
->
fm
t
.
i_x_offset
,
/* y */
v
d
->
fm
t
.
i_y_offset
,
/* width */
v
d
->
fm
t
.
i_visible_width
,
/* height */
v
d
->
fm
t
.
i_visible_height
,
0
,
0
,
p_sys
->
depth
,
XCB_IMAGE_FORMAT_Z_PIXMAP
,
0
,
segment
,
0
);
else
{
const
size_t
offset
=
v
out
->
fmt_ou
t
.
i_y_offset
*
pic
->
p
->
i_pitch
;
const
unsigned
lines
=
pic
->
p
->
i_lines
-
v
out
->
fmt_ou
t
.
i_y_offset
;
const
size_t
offset
=
v
d
->
fm
t
.
i_y_offset
*
pic
->
p
->
i_pitch
;
const
unsigned
lines
=
pic
->
p
->
i_lines
-
v
d
->
fm
t
.
i_y_offset
;
xcb_put_image
(
p_sys
->
conn
,
XCB_IMAGE_FORMAT_Z_PIXMAP
,
p_sys
->
window
,
p_sys
->
gc
,
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
lines
,
-
v
out
->
fmt_ou
t
.
i_x_offset
,
0
,
0
,
p_sys
->
depth
,
lines
,
-
v
d
->
fm
t
.
i_x_offset
,
0
,
0
,
p_sys
->
depth
,
pic
->
p
->
i_pitch
*
lines
,
pic
->
p
->
p_pixels
+
offset
);
}
xcb_flush
(
p_sys
->
conn
);
/* FIXME might be WAY better to wait in some case (be carefull with
* VOUT_DISPLAY_RESET_PICTURES if done) + does not work with
* vout_display wrapper. */
picture_Release
(
pic
);
}
/**
* Process incoming X events.
*/
static
int
Manage
(
vout_thread_t
*
vout
)
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
ap
)
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
xcb_generic_event_t
*
ev
;
while
((
ev
=
xcb_poll_for_event
(
p_sys
->
conn
))
!=
NULL
)
ProcessEvent
(
vout
,
p_sys
->
conn
,
p_sys
->
window
,
ev
);
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
xcb_connection_has_error
(
p_sys
->
conn
)
)
switch
(
query
)
{
msg_Err
(
vout
,
"X server failure"
);
return
VLC_EGENERIC
;
}
case
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
{
const
vout_display_cfg_t
*
p_cfg
=
(
const
vout_display_cfg_t
*
)
va_arg
(
ap
,
const
vout_display_cfg_t
*
);
CommonManage
(
vout
);
/* FIXME: <-- move that to core */
return
VLC_SUCCESS
;
}
if
(
vout_window_SetSize
(
p_sys
->
embed
,
p_cfg
->
display
.
width
,
p_cfg
->
display
.
height
))
return
VLC_EGENERIC
;
void
HandleParentStructure
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
xcb_window_t
xid
,
xcb_configure_notify_event_t
*
ev
)
{
unsigned
width
,
height
,
x
,
y
;
vout_display_place_t
place
;
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
p_cfg
,
false
);
vout_PlacePicture
(
vout
,
ev
->
width
,
ev
->
height
,
&
x
,
&
y
,
&
width
,
&
height
);
if
(
width
!=
vout
->
fmt_out
.
i_visible_width
||
height
!=
vout
->
fmt_out
.
i_visible_height
)
if
(
place
.
width
!=
vd
->
fmt
.
i_visible_width
||
place
.
height
!=
vd
->
fmt
.
i_visible_height
)
{
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
return
;
/* vout will be reinitialized */
vout_display_SendEventPicturesInvalid
(
vd
)
;
return
VLC_SUCCESS
;
}
/* Move the picture within the window */
const
uint32_t
values
[]
=
{
x
,
y
,
};
xcb_configure_window
(
conn
,
xid
,
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
,
values
);
}
static
int
Control
(
vout_thread_t
*
vout
,
int
query
,
va_list
ap
)
{
switch
(
query
)
{
case
VOUT_SET_SIZE
:
return
VLC_SUCCESS
;
}
case
VOUT_DISPLAY_CHANGE_ON_TOP
:
{
const
unsigned
width
=
va_arg
(
ap
,
unsigned
);
const
unsigned
height
=
va_arg
(
ap
,
unsigned
);
return
vout_window_SetSize
(
vout
->
p_sys
->
embed
,
width
,
height
);
int
b_on_top
=
(
int
)
va_arg
(
ap
,
int
);
return
vout_window_SetOnTop
(
p_sys
->
embed
,
b_on_top
);
}
case
VOUT_SET_STAY_ON_TOP
:
case
VOUT_DISPLAY_CHANGE_ZOOM
:
case
VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
case
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
case
VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
/* I am not sure it is always necessary, but it is way simpler ... */
vout_display_SendEventPicturesInvalid
(
vd
);
return
VLC_SUCCESS
;
case
VOUT_DISPLAY_RESET_PICTURES
:
{
const
bool
is_on_top
=
va_arg
(
ap
,
int
);
return
vout_window_SetOnTop
(
vout
->
p_sys
->
embed
,
is_on_top
);
ResetPictures
(
vd
);
vout_display_place_t
place
;
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
vd
->
fmt
.
i_width
=
vd
->
source
.
i_width
*
place
.
width
/
vd
->
source
.
i_visible_width
;
vd
->
fmt
.
i_height
=
vd
->
source
.
i_height
*
place
.
height
/
vd
->
source
.
i_visible_height
;
vd
->
fmt
.
i_visible_width
=
place
.
width
;
vd
->
fmt
.
i_visible_height
=
place
.
height
;
vd
->
fmt
.
i_x_offset
=
vd
->
source
.
i_x_offset
*
place
.
width
/
vd
->
source
.
i_visible_width
;
vd
->
fmt
.
i_y_offset
=
vd
->
source
.
i_y_offset
*
place
.
height
/
vd
->
source
.
i_visible_height
;
return
VLC_SUCCESS
;
}
/* TODO */
#if 0
/* Hide the mouse. It will be send when
* vout_display_t::info.b_hide_mouse is false */
VOUT_DISPLAY_HIDE_MOUSE,
/* Ask the module to acknowledge/refuse the fullscreen state change after
* being requested (externaly or by VOUT_DISPLAY_EVENT_FULLSCREEN */
VOUT_DISPLAY_CHANGE_FULLSCREEN, /* const vout_display_cfg_t *p_cfg */
#endif
default:
msg_Err
(
vd
,
"Unknown request in XCB vout display"
);
return
VLC_EGENERIC
;
}
}
static
void
Manage
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
ManageEvent
(
vd
,
p_sys
->
conn
,
p_sys
->
window
);
}
static
void
ResetPictures
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
!
p_sys
->
pool
)
return
;
for
(
unsigned
i
=
0
;
i
<
MAX_PICTURES
;
i
++
)
{
picture_resource_t
*
res
=
&
p_sys
->
resource
[
i
];
if
(
!
res
->
p
->
p_pixels
)
break
;
PictureResourceFree
(
res
,
p_sys
->
conn
);
}
picture_pool_Delete
(
p_sys
->
pool
);
p_sys
->
pool
=
NULL
;
}
modules/video_output/xcb/xcb_vlc.h
View file @
e8534473
...
...
@@ -26,12 +26,10 @@
# define ORDER XCB_IMAGE_ORDER_LSB_FIRST
#endif
int
CheckError
(
vout_thread_t
*
,
const
char
*
str
,
xcb_void_cookie_t
);
int
ProcessEvent
(
vout_thread_t
*
,
xcb_connection_t
*
,
xcb_window_t
,
xcb_generic_event_t
*
);
void
HandleParentStructure
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
xcb_window_t
xid
,
xcb_configure_notify_event_t
*
ev
);
#include <vlc_picture.h>
#include <vlc_vout_display.h>
int
ManageEvent
(
vout_display_t
*
vd
,
xcb_connection_t
*
conn
,
xcb_window_t
window
);
/* keys.c */
typedef
struct
key_handler_t
key_handler_t
;
...
...
@@ -40,15 +38,25 @@ void DestroyKeyHandler (key_handler_t *);
int
ProcessKeyEvent
(
key_handler_t
*
,
xcb_generic_event_t
*
);
/* common.c */
struct
vout_window_t
;
xcb_connection_t
*
Connect
(
vlc_object_t
*
obj
);
struct
vout_window_t
*
GetWindow
(
vout_
thread
_t
*
obj
,
struct
vout_window_t
*
GetWindow
(
vout_
display
_t
*
obj
,
xcb_connection_t
*
pconn
,
const
xcb_screen_t
**
restrict
pscreen
,
bool
*
restrict
pshm
);
int
GetWindowSize
(
struct
vout_window_t
*
wnd
,
xcb_connection_t
*
conn
,
unsigned
*
restrict
width
,
unsigned
*
restrict
height
);
int
PictureAlloc
(
vout_thread_t
*
,
picture_t
*
,
size_t
,
xcb_connection_t
*
);
void
PictureFree
(
picture_t
*
pic
,
xcb_connection_t
*
conn
);
void
CommonManage
(
vout_thread_t
*
);
int
CheckError
(
vout_display_t
*
,
xcb_connection_t
*
conn
,
const
char
*
str
,
xcb_void_cookie_t
);
/* FIXME
* maybe it would be better to split this header in 2 */
#include <xcb/shm.h>
struct
picture_sys_t
{
xcb_shm_seg_t
segment
;
};
int
PictureResourceAlloc
(
vout_display_t
*
vd
,
picture_resource_t
*
res
,
size_t
size
,
xcb_connection_t
*
conn
,
bool
attach
);
void
PictureResourceFree
(
picture_resource_t
*
res
,
xcb_connection_t
*
conn
);
modules/video_output/xcb/xvideo.c
View file @
e8534473
...
...
@@ -33,8 +33,8 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout.h>
#include <vlc_
vout_window
.h>
#include <vlc_vout
_display
.h>
#include <vlc_
picture_pool
.h>
#include "xcb_vlc.h"
...
...
@@ -58,7 +58,7 @@ vlc_module_begin ()
set_description
(
N_
(
"(Experimental) XVideo output"
))
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_capability
(
"v
ideo output
"
,
0
)
set_capability
(
"v
out display
"
,
0
)
set_callbacks
(
Open
,
Close
)
add_string
(
"x11-display"
,
NULL
,
NULL
,
...
...
@@ -67,7 +67,9 @@ vlc_module_begin ()
add_shortcut
(
"xcb-xv"
)
vlc_module_end
()
struct
vout_sys_t
#define MAX_PICTURES (VOUT_MAX_PICTURES)
struct
vout_display_sys_t
{
xcb_connection_t
*
conn
;
xcb_xv_query_adaptors_reply_t
*
adaptors
;
...
...
@@ -81,31 +83,21 @@ struct vout_sys_t
uint16_t
height
;
/* display height */
uint32_t
data_size
;
/* picture byte size (for non-SHM) */
bool
shm
;
/* whether to use MIT-SHM */
xcb_xv_query_image_attributes_reply_t
*
att
;
picture_pool_t
*
pool
;
/* picture pool */
picture_resource_t
resource
[
MAX_PICTURES
];
};
static
int
Init
(
vout_thread_t
*
);
static
void
Deinit
(
vout_thread_t
*
);
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
static
int
Manage
(
vout_thread_t
*
);
static
int
Control
(
vout_thread_t
*
,
int
,
va_list
);
int
CheckError
(
vout_thread_t
*
vout
,
const
char
*
str
,
xcb_void_cookie_t
ck
)
{
xcb_generic_error_t
*
err
;
err
=
xcb_request_check
(
vout
->
p_sys
->
conn
,
ck
);
if
(
err
)
{
msg_Err
(
vout
,
"%s: X11 error %d"
,
str
,
err
->
error_code
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
static
picture_t
*
Get
(
vout_display_t
*
);
static
void
Display
(
vout_display_t
*
,
picture_t
*
);
static
int
Control
(
vout_display_t
*
,
int
,
va_list
);
static
void
Manage
(
vout_display_t
*
);
/**
* Check that the X server supports the XVideo extension.
*/
static
bool
CheckXVideo
(
vout_
thread_t
*
vout
,
xcb_connection_t
*
conn
)
static
bool
CheckXVideo
(
vout_
display_t
*
vd
,
xcb_connection_t
*
conn
)
{
xcb_xv_query_extension_reply_t
*
r
;
xcb_xv_query_extension_cookie_t
ck
=
xcb_xv_query_extension
(
conn
);
...
...
@@ -116,129 +108,21 @@ static bool CheckXVideo (vout_thread_t *vout, xcb_connection_t *conn)
{
/* We need XVideo 2.2 for PutImage */
if
((
r
->
major
>
2
)
||
(
r
->
major
==
2
&&
r
->
minor
>=
2
))
{
msg_Dbg
(
v
out
,
"using XVideo extension v%"
PRIu8
".%"
PRIu8
,
msg_Dbg
(
v
d
,
"using XVideo extension v%"
PRIu8
".%"
PRIu8
,
r
->
major
,
r
->
minor
);
ok
=
true
;
}
else
msg_Dbg
(
v
out
,
"XVideo extension too old (v%"
PRIu8
".%"
PRIu8
,
msg_Dbg
(
v
d
,
"XVideo extension too old (v%"
PRIu8
".%"
PRIu8
,
r
->
major
,
r
->
minor
);
free
(
r
);
}
else
msg_Dbg
(
v
out
,
"XVideo extension not available"
);
msg_Dbg
(
v
d
,
"XVideo extension not available"
);
return
ok
;
}
/**
* Get a list of XVideo adaptors for a given window.
*/
static
xcb_xv_query_adaptors_reply_t
*
GetAdaptors
(
vout_window_t
*
wnd
,
xcb_connection_t
*
conn
)
{
xcb_xv_query_adaptors_cookie_t
ck
;
ck
=
xcb_xv_query_adaptors
(
conn
,
wnd
->
handle
.
xid
);
return
xcb_xv_query_adaptors_reply
(
conn
,
ck
,
NULL
);
}
#define p_vout vout
/**
* Probe the X server.
*/
static
int
Open
(
vlc_object_t
*
obj
)
{
vout_thread_t
*
vout
=
(
vout_thread_t
*
)
obj
;
vout_sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
vout
->
p_sys
=
p_sys
;
/* Connect to X */
p_sys
->
conn
=
Connect
(
obj
);
if
(
p_sys
->
conn
==
NULL
)
{
free
(
p_sys
);
return
VLC_EGENERIC
;
}
if
(
!
CheckXVideo
(
vout
,
p_sys
->
conn
))
{
msg_Warn
(
vout
,
"Please enable XVideo 2.2 for faster video display"
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
const
xcb_screen_t
*
screen
;
p_sys
->
embed
=
GetWindow
(
vout
,
p_sys
->
conn
,
&
screen
,
&
p_sys
->
shm
);
if
(
p_sys
->
embed
==
NULL
)
{
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
/* Cache adaptors infos */
p_sys
->
adaptors
=
GetAdaptors
(
p_sys
->
embed
,
p_sys
->
conn
);
if
(
p_sys
->
adaptors
==
NULL
)
goto
error
;
/* Create window */
{
const
uint32_t
mask
=
/* XCB_CW_EVENT_MASK */
XCB_EVENT_MASK_BUTTON_PRESS
|
XCB_EVENT_MASK_BUTTON_RELEASE
|
XCB_EVENT_MASK_POINTER_MOTION
;
xcb_void_cookie_t
c
;
xcb_window_t
window
=
xcb_generate_id
(
p_sys
->
conn
);
c
=
xcb_create_window_checked
(
p_sys
->
conn
,
screen
->
root_depth
,
window
,
p_sys
->
embed
->
handle
.
xid
,
0
,
0
,
1
,
1
,
0
,
XCB_WINDOW_CLASS_INPUT_OUTPUT
,
screen
->
root_visual
,
XCB_CW_EVENT_MASK
,
&
mask
);
if
(
CheckError
(
vout
,
"cannot create X11 window"
,
c
))
goto
error
;
p_sys
->
window
=
window
;
msg_Dbg
(
vout
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
xcb_map_window
(
p_sys
->
conn
,
window
);
}
p_sys
->
gc
=
xcb_generate_id
(
p_sys
->
conn
);
xcb_create_gc
(
p_sys
->
conn
,
p_sys
->
gc
,
p_sys
->
window
,
0
,
NULL
);
msg_Dbg
(
vout
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
vout
->
pf_init
=
Init
;
vout
->
pf_end
=
Deinit
;
vout
->
pf_display
=
Display
;
vout
->
pf_manage
=
Manage
;
vout
->
pf_control
=
Control
;
return
VLC_SUCCESS
;
error:
Close
(
obj
);
return
VLC_EGENERIC
;
}
/**
* Disconnect from the X server.
*/
static
void
Close
(
vlc_object_t
*
obj
)
{
vout_thread_t
*
vout
=
(
vout_thread_t
*
)
obj
;
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
free
(
p_sys
->
adaptors
);
vout_window_Delete
(
p_sys
->
embed
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
}
static
vlc_fourcc_t
ParseFormat
(
vout_thread_t
*
vout
,
static
vlc_fourcc_t
ParseFormat
(
vout_display_t
*
vd
,
const
xcb_xv_image_format_info_t
*
restrict
f
)
{
if
(
f
->
byte_order
!=
ORDER
&&
f
->
bpp
!=
8
)
...
...
@@ -273,9 +157,9 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
}
break
;
}
msg_Err
(
v
out
,
"unknown XVideo RGB format %"
PRIx32
" (%.4s)"
,
msg_Err
(
v
d
,
"unknown XVideo RGB format %"
PRIx32
" (%.4s)"
,
f
->
id
,
f
->
guid
);
msg_Dbg
(
v
out
,
" %"
PRIu8
" planes, %"
PRIu8
" bits/pixel, "
msg_Dbg
(
v
d
,
" %"
PRIu8
" planes, %"
PRIu8
" bits/pixel, "
"depth %"
PRIu8
,
f
->
num_planes
,
f
->
bpp
,
f
->
depth
);
break
;
...
...
@@ -321,16 +205,16 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
break
;
}
bad:
msg_Err
(
v
out
,
"unknown XVideo YUV format %"
PRIx32
" (%.4s)"
,
f
->
id
,
msg_Err
(
v
d
,
"unknown XVideo YUV format %"
PRIx32
" (%.4s)"
,
f
->
id
,
f
->
guid
);
msg_Dbg
(
v
out
,
" %"
PRIu8
" planes, %"
PRIu32
" bits/pixel, "
msg_Dbg
(
v
d
,
" %"
PRIu8
" planes, %"
PRIu32
" bits/pixel, "
"%"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
" bits/sample"
,
f
->
num_planes
,
f
->
bpp
,
f
->
y_sample_bits
,
f
->
u_sample_bits
,
f
->
v_sample_bits
);
msg_Dbg
(
v
out
,
" period: %"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
"x"
msg_Dbg
(
v
d
,
" period: %"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
"x"
"%"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
,
f
->
vhorz_y_period
,
f
->
vhorz_u_period
,
f
->
vhorz_v_period
,
f
->
vvert_y_period
,
f
->
vvert_u_period
,
f
->
vvert_v_period
);
msg_Warn
(
v
out
,
" order: %.32s"
,
f
->
vcomp_order
);
msg_Warn
(
v
d
,
" order: %.32s"
,
f
->
vcomp_order
);
break
;
}
return
0
;
...
...
@@ -338,11 +222,13 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
static
const
xcb_xv_image_format_info_t
*
FindFormat
(
vout_thread_t
*
vout
,
vlc_fourcc_t
chroma
,
xcb_xv_port_t
port
,
FindFormat
(
vout_display_t
*
vd
,
vlc_fourcc_t
chroma
,
const
video_format_t
*
fmt
,
xcb_xv_port_t
port
,
const
xcb_xv_list_image_formats_reply_t
*
list
,
xcb_xv_query_image_attributes_reply_t
**
restrict
pa
)
{
xcb_connection_t
*
conn
=
v
out
->
p_
sys
->
conn
;
xcb_connection_t
*
conn
=
v
d
->
sys
->
conn
;
const
xcb_xv_image_format_info_t
*
f
,
*
end
;
#ifndef XCB_XV_OLD
...
...
@@ -353,21 +239,21 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
end
=
f
+
xcb_xv_list_image_formats_format_length
(
list
);
for
(;
f
<
end
;
f
++
)
{
if
(
chroma
!=
ParseFormat
(
v
out
,
f
))
if
(
chroma
!=
ParseFormat
(
v
d
,
f
))
continue
;
xcb_xv_query_image_attributes_reply_t
*
i
;
i
=
xcb_xv_query_image_attributes_reply
(
conn
,
xcb_xv_query_image_attributes
(
conn
,
port
,
f
->
id
,
vout
->
fmt_in
.
i_width
,
vout
->
fmt_in
.
i_height
),
NULL
);
fmt
->
i_width
,
fmt
->
i_height
),
NULL
);
if
(
i
==
NULL
)
continue
;
if
(
i
->
width
!=
vout
->
fmt_in
.
i_width
||
i
->
height
!=
vout
->
fmt_in
.
i_height
)
if
(
i
->
width
!=
fmt
->
i_width
||
i
->
height
!=
fmt
->
i_height
)
{
msg_Warn
(
v
out
,
"incompatible size %ux%u -> %"
PRIu32
"x%"
PRIu32
,
vout
->
fmt_in
.
i_width
,
vout
->
fmt_in
.
i_height
,
msg_Warn
(
v
d
,
"incompatible size %ux%u -> %"
PRIu32
"x%"
PRIu32
,
fmt
->
i_width
,
fmt
->
i_height
,
i
->
width
,
i
->
height
);
free
(
i
);
continue
;
...
...
@@ -378,14 +264,67 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
return
NULL
;
}
/**
*
Allocate drawable window and picture buffers
.
*
Get a list of XVideo adaptors for a given window
.
*/
static
int
Init
(
vout_thread_t
*
vout
)
static
xcb_xv_query_adaptors_reply_t
*
GetAdaptors
(
vout_window_t
*
wnd
,
xcb_connection_t
*
conn
)
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
xcb_xv_query_image_attributes_reply_t
*
att
=
NULL
;
bool
swap_planes
=
false
;
/* whether X wants V before U */
xcb_xv_query_adaptors_cookie_t
ck
;
ck
=
xcb_xv_query_adaptors
(
conn
,
wnd
->
handle
.
xid
);
return
xcb_xv_query_adaptors_reply
(
conn
,
ck
,
NULL
);
}
/**
* Probe the X server.
*/
static
int
Open
(
vlc_object_t
*
obj
)
{
vout_display_t
*
vd
=
(
vout_display_t
*
)
obj
;
vout_display_sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
vd
->
sys
=
p_sys
;
/* Connect to X */
p_sys
->
conn
=
Connect
(
obj
);
if
(
p_sys
->
conn
==
NULL
)
{
free
(
p_sys
);
return
VLC_EGENERIC
;
}
if
(
!
CheckXVideo
(
vd
,
p_sys
->
conn
))
{
msg_Warn
(
vd
,
"Please enable XVideo 2.2 for faster video display"
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
const
xcb_screen_t
*
screen
;
p_sys
->
embed
=
GetWindow
(
vd
,
p_sys
->
conn
,
&
screen
,
&
p_sys
->
shm
);
if
(
p_sys
->
embed
==
NULL
)
{
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
/* Cache adaptors infos */
p_sys
->
adaptors
=
GetAdaptors
(
p_sys
->
embed
,
p_sys
->
conn
);
if
(
p_sys
->
adaptors
==
NULL
)
goto
error
;
/* */
video_format_t
fmt
=
vd
->
fmt
;
// TODO !
#if 1
p_sys
->
att
=
NULL
;
bool
found_adaptor
=
false
;
/* FIXME: check max image size */
xcb_xv_adaptor_info_iterator_t
it
;
...
...
@@ -405,11 +344,11 @@ static int Init (vout_thread_t *vout)
if
(
r
==
NULL
)
continue
;
const
xcb_xv_image_format_info_t
*
fmt
;
const
xcb_xv_image_format_info_t
*
x
fmt
;
/* Video chroma in preference order */
const
vlc_fourcc_t
chromas
[]
=
{
vout
->
fmt_in
.
i_chroma
,
fmt
.
i_chroma
,
VLC_CODEC_YUYV
,
VLC_CODEC_RGB24
,
VLC_CODEC_RGB15
,
...
...
@@ -417,10 +356,10 @@ static int Init (vout_thread_t *vout)
for
(
size_t
i
=
0
;
i
<
sizeof
(
chromas
)
/
sizeof
(
chromas
[
0
]);
i
++
)
{
vlc_fourcc_t
chroma
=
chromas
[
i
];
fmt
=
FindFormat
(
vout
,
chroma
,
a
->
base_id
,
r
,
&
att
);
if
(
fmt
!=
NULL
)
xfmt
=
FindFormat
(
vd
,
chroma
,
&
fmt
,
a
->
base_id
,
r
,
&
p_sys
->
att
);
if
(
x
fmt
!=
NULL
)
{
vout
->
outpu
t
.
i_chroma
=
chroma
;
fm
t
.
i_chroma
=
chroma
;
goto
found_format
;
}
}
...
...
@@ -430,203 +369,306 @@ static int Init (vout_thread_t *vout)
found_format:
/* TODO: grab port */
p_sys
->
port
=
a
->
base_id
;
msg_Dbg
(
v
out
,
"using port %"
PRIu32
,
p_sys
->
port
);
msg_Dbg
(
v
d
,
"using port %"
PRIu32
,
p_sys
->
port
);
p_sys
->
id
=
fmt
->
id
;
msg_Dbg
(
v
out
,
"using image format 0x%"
PRIx32
,
p_sys
->
id
);
if
(
fmt
->
type
==
XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB
)
p_sys
->
id
=
x
fmt
->
id
;
msg_Dbg
(
v
d
,
"using image format 0x%"
PRIx32
,
p_sys
->
id
);
if
(
x
fmt
->
type
==
XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB
)
{
vout
->
fmt_out
.
i_rmask
=
vout
->
output
.
i_rmask
=
fmt
->
red_mask
;
vout
->
fmt_out
.
i_gmask
=
vout
->
output
.
i_gmask
=
fmt
->
green_mask
;
vout
->
fmt_out
.
i_bmask
=
vout
->
output
.
i_bmask
=
fmt
->
blue_mask
;
fmt
.
i_rmask
=
x
fmt
->
red_mask
;
fmt
.
i_gmask
=
x
fmt
->
green_mask
;
fmt
.
i_bmask
=
x
fmt
->
blue_mask
;
}
else
if
(
fmt
->
num_planes
==
3
)
swap_planes
=
!
strcmp
((
const
char
*
)
fmt
->
vcomp_order
,
"YVU"
);
if
(
xfmt
->
num_planes
==
3
&&
!
strcmp
((
const
char
*
)
xfmt
->
vcomp_order
,
"YVU"
))
fmt
.
i_chroma
=
VLC_CODEC_YV12
;
free
(
r
);
goto
found_adaptor
;
found_adaptor
=
true
;
break
;
}
msg_Err
(
vout
,
"no available XVideo adaptor"
);
return
VLC_EGENERIC
;
/* no usable adaptor */
/* Allocate picture buffers */
const
uint32_t
*
offsets
;
found_adaptor:
offsets
=
xcb_xv_query_image_attributes_offsets
(
att
);
p_sys
->
data_size
=
att
->
data_size
;
I_OUTPUTPICTURES
=
0
;
for
(
size_t
index
=
0
;
I_OUTPUTPICTURES
<
2
;
index
++
)
if
(
!
found_adaptor
)
{
picture_t
*
pic
=
vout
->
p_picture
+
index
;
msg_Err
(
vd
,
"no available XVideo adaptor"
);
goto
error
;
}
#endif
if
(
index
>
sizeof
(
vout
->
p_picture
)
/
sizeof
(
pic
))
break
;
if
(
pic
->
i_status
!=
FREE_PICTURE
)
continue
;
/* Create window */
{
const
uint32_t
mask
=
/* XCB_CW_EVENT_MASK */
XCB_EVENT_MASK_BUTTON_PRESS
|
XCB_EVENT_MASK_BUTTON_RELEASE
|
XCB_EVENT_MASK_POINTER_MOTION
;
xcb_void_cookie_t
c
;
xcb_window_t
window
=
xcb_generate_id
(
p_sys
->
conn
);
picture_Setup
(
pic
,
vout
->
output
.
i_chroma
,
att
->
width
,
att
->
height
,
vout
->
fmt_in
.
i_aspect
);
if
(
PictureAlloc
(
vout
,
pic
,
att
->
data_size
,
p_sys
->
shm
?
p_sys
->
conn
:
NULL
))
break
;
/* Allocate further planes as specified by XVideo */
/* We assume that offsets[0] is zero */
for
(
int
i
=
1
;
i
<
pic
->
i_planes
;
i
++
)
pic
->
p
[
i
].
p_pixels
=
pic
->
p
->
p_pixels
+
offsets
[
swap_planes
?
(
3
-
i
)
:
i
];
PP_OUTPUTPICTURE
[
I_OUTPUTPICTURES
++
]
=
pic
;
}
free
(
att
);
c
=
xcb_create_window_checked
(
p_sys
->
conn
,
screen
->
root_depth
,
window
,
p_sys
->
embed
->
handle
.
xid
,
0
,
0
,
1
,
1
,
0
,
XCB_WINDOW_CLASS_INPUT_OUTPUT
,
screen
->
root_visual
,
XCB_CW_EVENT_MASK
,
&
mask
);
if
(
CheckError
(
vd
,
p_sys
->
conn
,
"cannot create X11 window"
,
c
))
goto
error
;
p_sys
->
window
=
window
;
msg_Dbg
(
vd
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
xcb_map_window
(
p_sys
->
conn
,
window
);
unsigned
x
,
y
,
width
,
height
;
vout_display_place_t
place
;
if
(
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
return
VLC_EGENERIC
;
vout_PlacePicture
(
vout
,
width
,
height
,
&
x
,
&
y
,
&
width
,
&
height
)
;
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
p_sys
->
width
=
place
.
width
;
p_sys
->
height
=
place
.
height
;
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
/* */
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
,
place
.
width
,
place
.
height
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
xcb_flush
(
p_sys
->
conn
);
p_sys
->
height
=
height
;
p_sys
->
width
=
width
;
}
/* Create graphic context */
p_sys
->
gc
=
xcb_generate_id
(
p_sys
->
conn
);
xcb_create_gc
(
p_sys
->
conn
,
p_sys
->
gc
,
p_sys
->
window
,
0
,
NULL
);
msg_Dbg
(
vd
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
/* */
p_sys
->
pool
=
NULL
;
vout
->
fmt_out
.
i_chroma
=
vout
->
output
.
i_chroma
;
vout
->
fmt_out
.
i_visible_width
=
vout
->
fmt_in
.
i_visible_width
;
vout
->
fmt_out
.
i_visible_height
=
vout
->
fmt_in
.
i_visible_height
;
vout
->
fmt_out
.
i_sar_num
=
vout
->
fmt_out
.
i_sar_den
=
1
;
/* */
vout_display_info_t
info
=
vd
->
info
;
info
.
has_pictures_invalid
=
false
;
vout
->
output
.
i_width
=
vout
->
fmt_out
.
i_width
=
vout
->
fmt_in
.
i_width
;
vout
->
output
.
i_height
=
vout
->
fmt_out
.
i_height
=
vout
->
fmt_in
.
i_height
;
vout
->
fmt_out
.
i_x_offset
=
vout
->
fmt_in
.
i_x_offset
;
vout
->
fmt_out
.
i_y_offset
=
vout
->
fmt_in
.
i_y_offset
;
/* Setup vout_display_t once everything is fine */
vd
->
fmt
=
fmt
;
vd
->
info
=
info
;
assert
(
height
>
0
);
vout
->
output
.
i_aspect
=
vout
->
fmt_out
.
i_aspect
=
width
*
VOUT_ASPECT_FACTOR
/
height
;
vd
->
get
=
Get
;
vd
->
prepare
=
NULL
;
vd
->
display
=
Display
;
vd
->
control
=
Control
;
vd
->
manage
=
Manage
;
/* */
unsigned
width
,
height
;
if
(
!
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
vout_display_SendEventDisplaySize
(
vd
,
width
,
height
);
vout_display_SendEventFullscreen
(
vd
,
false
);
return
VLC_SUCCESS
;
error:
Close
(
obj
);
return
VLC_EGENERIC
;
}
/**
*
Free picture buffers
.
*
Disconnect from the X server
.
*/
static
void
Deinit
(
vout_thread_t
*
vout
)
static
void
Close
(
vlc_object_t
*
obj
)
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
vout_display_t
*
vd
=
(
vout_display_t
*
)
obj
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
p_sys
->
pool
)
{
for
(
unsigned
i
=
0
;
i
<
MAX_PICTURES
;
i
++
)
{
picture_resource_t
*
res
=
&
p_sys
->
resource
[
i
];
if
(
!
res
->
p
->
p_pixels
)
break
;
PictureResourceFree
(
res
,
p_sys
->
conn
);
}
picture_pool_Delete
(
p_sys
->
pool
);
}
for
(
int
i
=
0
;
i
<
I_OUTPUTPICTURES
;
i
++
)
PictureFree
(
PP_OUTPUTPICTURE
[
i
],
p_sys
->
conn
);
free
(
p_sys
->
att
);
free
(
p_sys
->
adaptors
);
vout_display_DeleteWindow
(
vd
,
p_sys
->
embed
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
}
/**
* Return a direct buffer
*/
static
picture_t
*
Get
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
!
p_sys
->
pool
)
{
picture_t
*
pic
=
picture_New
(
vd
->
fmt
.
i_chroma
,
p_sys
->
att
->
width
,
p_sys
->
att
->
height
,
0
);
if
(
!
pic
)
return
NULL
;
memset
(
p_sys
->
resource
,
0
,
sizeof
(
p_sys
->
resource
));
const
uint32_t
*
offsets
=
xcb_xv_query_image_attributes_offsets
(
p_sys
->
att
);
p_sys
->
data_size
=
p_sys
->
att
->
data_size
;
unsigned
count
;
picture_t
*
pic_array
[
MAX_PICTURES
];
for
(
count
=
0
;
count
<
MAX_PICTURES
;
count
++
)
{
picture_resource_t
*
res
=
&
p_sys
->
resource
[
count
];
for
(
int
i
=
0
;
i
<
pic
->
i_planes
;
i
++
)
{
res
->
p
[
i
].
i_lines
=
pic
->
p
[
i
].
i_lines
;
/* FIXME seems wrong*/
res
->
p
[
i
].
i_pitch
=
pic
->
p
[
i
].
i_pitch
;
}
if
(
PictureResourceAlloc
(
vd
,
res
,
p_sys
->
att
->
data_size
,
p_sys
->
conn
,
p_sys
->
shm
))
break
;
/* Allocate further planes as specified by XVideo */
/* We assume that offsets[0] is zero */
for
(
int
i
=
1
;
i
<
pic
->
i_planes
;
i
++
)
res
->
p
[
i
].
p_pixels
=
res
->
p
[
0
].
p_pixels
+
offsets
[
i
];
pic_array
[
count
]
=
picture_NewFromResource
(
&
vd
->
fmt
,
res
);
if
(
!
pic_array
[
count
])
{
PictureResourceFree
(
res
,
p_sys
->
conn
);
memset
(
res
,
0
,
sizeof
(
*
res
));
break
;
}
}
picture_Release
(
pic
);
if
(
count
==
0
)
return
NULL
;
p_sys
->
pool
=
picture_pool_New
(
count
,
pic_array
);
if
(
!
p_sys
->
pool
)
{
/* TODO release picture resources */
return
NULL
;
}
/* FIXME should also do it in case of error ? */
xcb_flush
(
p_sys
->
conn
);
}
return
picture_pool_Get
(
p_sys
->
pool
);
}
/**
* Sends an image to the X server.
*/
static
void
Display
(
vout_
thread_t
*
vout
,
picture_t
*
pic
)
static
void
Display
(
vout_
display_t
*
vd
,
picture_t
*
pic
)
{
vout_
sys_t
*
p_sys
=
vout
->
p_
sys
;
xcb_shm_seg_t
segment
=
(
uintptr_t
)
pic
->
p_sys
;
vout_
display_sys_t
*
p_sys
=
vd
->
sys
;
xcb_shm_seg_t
segment
=
pic
->
p_sys
->
segment
;
if
(
segment
)
xcb_xv_shm_put_image
(
p_sys
->
conn
,
p_sys
->
port
,
p_sys
->
window
,
p_sys
->
gc
,
segment
,
p_sys
->
id
,
0
,
/* Src: */
vout
->
fmt_out
.
i_x_offset
,
v
out
->
fmt_out
.
i_y_offset
,
v
out
->
fmt_out
.
i_visible_width
,
v
out
->
fmt_out
.
i_visible_height
,
/* Src: */
vd
->
source
.
i_x_offset
,
v
d
->
source
.
i_y_offset
,
v
d
->
source
.
i_visible_width
,
v
d
->
source
.
i_visible_height
,
/* Dst: */
0
,
0
,
p_sys
->
width
,
p_sys
->
height
,
/* Memory: */
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
/* Memory: */
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
pic
->
p
->
i_lines
,
false
);
else
xcb_xv_put_image
(
p_sys
->
conn
,
p_sys
->
port
,
p_sys
->
window
,
p_sys
->
gc
,
p_sys
->
id
,
vout
->
fmt_out
.
i_x_offset
,
vout
->
fmt_out
.
i_y_offset
,
vout
->
fmt_out
.
i_visible_width
,
vout
->
fmt_out
.
i_visible_height
,
vd
->
source
.
i_x_offset
,
vd
->
source
.
i_y_offset
,
vd
->
source
.
i_visible_width
,
vd
->
source
.
i_visible_height
,
0
,
0
,
p_sys
->
width
,
p_sys
->
height
,
v
out
->
fmt_out
.
i_width
,
vout
->
fmt_out
.
i_height
,
v
d
->
source
.
i_width
,
vd
->
source
.
i_height
,
p_sys
->
data_size
,
pic
->
p
->
p_pixels
);
xcb_flush
(
p_sys
->
conn
);
picture_Release
(
pic
);
}
/**
* Process incoming X events.
*/
static
int
Manage
(
vout_thread_t
*
vout
)
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
ap
)
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
xcb_generic_event_t
*
ev
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
while
((
ev
=
xcb_poll_for_event
(
p_sys
->
conn
))
!=
NULL
)
ProcessEvent
(
vout
,
p_sys
->
conn
,
p_sys
->
window
,
ev
);
switch
(
query
)
{
case
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
case
VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
case
VOUT_DISPLAY_CHANGE_ZOOM
:
case
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
case
VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
{
const
vout_display_cfg_t
*
cfg
;
const
video_format_t
*
source
;
if
(
xcb_connection_has_error
(
p_sys
->
conn
))
if
(
query
==
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
||
query
==
VOUT_DISPLAY_CHANGE_SOURCE_CROP
)
{
msg_Err
(
vout
,
"X server failure"
);
return
VLC_EGENERIC
;
source
=
(
const
video_format_t
*
)
va_arg
(
ap
,
const
video_format_t
*
);
cfg
=
vd
->
cfg
;
}
CommonManage
(
vout
);
if
(
vout
->
i_changes
&
VOUT_SIZE_CHANGE
)
{
/* TODO: factor this code with XV and X11 Init() */
unsigned
x
,
y
,
width
,
height
;
if
(
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
return
VLC_EGENERIC
;
vout_PlacePicture
(
vout
,
width
,
height
,
&
x
,
&
y
,
&
width
,
&
height
);
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
vout
->
p_sys
->
width
=
width
;
// XXX: <-- this is useless, as the zoom is
vout
->
p_sys
->
height
=
height
;
// handled with VOUT_SET_SIZE anyway.
vout
->
i_changes
&=
~
VOUT_SIZE_CHANGE
;
else
{
source
=
&
vd
->
source
;
cfg
=
(
const
vout_display_cfg_t
*
)
va_arg
(
ap
,
const
vout_display_cfg_t
*
);
}
return
VLC_SUCCESS
;
}
void
HandleParentStructure
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
xcb_window_t
xid
,
xcb_configure_notify_event_t
*
ev
)
{
unsigned
width
,
height
,
x
,
y
;
/* */
if
(
query
==
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
&&
(
cfg
->
display
.
width
!=
vd
->
cfg
->
display
.
width
||
cfg
->
display
.
height
!=
vd
->
cfg
->
display
.
height
)
&&
vout_window_SetSize
(
p_sys
->
embed
,
cfg
->
display
.
width
,
cfg
->
display
.
height
))
return
VLC_EGENERIC
;
vout_PlacePicture
(
vout
,
ev
->
width
,
ev
->
height
,
&
x
,
&
y
,
&
width
,
&
height
);
vout_display_place_t
place
;
vout_display_PlacePicture
(
&
place
,
source
,
cfg
,
false
);
p_sys
->
width
=
place
.
width
;
p_sys
->
height
=
place
.
height
;
/* Move the picture within the window */
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
xcb_configure_window
(
conn
,
xid
,
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
,
place
.
width
,
place
.
height
,
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
vout
->
p_sys
->
width
=
width
;
vout
->
p_sys
->
height
=
height
;
}
static
int
Control
(
vout_thread_t
*
vout
,
int
query
,
va_list
ap
)
{
/* FIXME it can be shared between x11 and xvideo */
switch
(
query
)
{
case
VOUT_SET_SIZE
:
{
const
unsigned
width
=
va_arg
(
ap
,
unsigned
);
const
unsigned
height
=
va_arg
(
ap
,
unsigned
);
return
vout_window_SetSize
(
vout
->
p_sys
->
embed
,
width
,
height
);
xcb_flush
(
p_sys
->
conn
);
return
VLC_SUCCESS
;
}
case
VOUT_
SET_STAY
_ON_TOP
:
case
VOUT_
DISPLAY_CHANGE
_ON_TOP
:
{
const
bool
is_on_top
=
va_arg
(
ap
,
int
);
return
vout_window_SetOnTop
(
vout
->
p_sys
->
embed
,
is_
on_top
);
int
on_top
=
(
int
)
va_arg
(
ap
,
int
);
return
vout_window_SetOnTop
(
p_sys
->
embed
,
on_top
);
}
/* TODO */
#if 0
/* Hide the mouse. It will be send when
* vout_display_t::info.b_hide_mouse is false */
VOUT_DISPLAY_HIDE_MOUSE,
/* Ask the module to acknowledge/refuse the fullscreen state change after
* being requested (externaly or by VOUT_DISPLAY_EVENT_FULLSCREEN */
VOUT_DISPLAY_CHANGE_FULLSCREEN, /* const vout_display_cfg_t *p_cfg */
#endif
case
VOUT_DISPLAY_RESET_PICTURES
:
assert
(
0
);
default:
msg_Err
(
vd
,
"Unknown request in XCB vout display"
);
return
VLC_EGENERIC
;
}
}
static
void
Manage
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
ManageEvent
(
vd
,
p_sys
->
conn
,
p_sys
->
window
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment