1 /* vo_xv.c, X11 Xv interface */
3 // Number of buffers _FOR_DOUBLEBUFFERING_MODE_
4 // Use option -double to enable double buffering! (default: single buffer)
26 #include "video_out.h"
27 #include "video_out_internal.h"
31 #include <X11/Xutil.h>
34 #include "x11_common.h"
36 #include "fastmemcpy.h"
40 #include "subopt-helper.h"
42 #include "input/input.h"
45 #include "gui/interface.h"
48 #include "libavutil/common.h"
50 static const vo_info_t info
= {
53 "Gerd Knorr <kraxel@goldbach.in-berlin.de> and others",
57 const LIBVO_EXTERN(xv
)
61 #include <X11/extensions/XShm.h>
63 static XShmSegmentInfo Shminfo
[NUM_BUFFERS
];
64 static int Shmem_Flag
;
67 // Note: depends on the inclusion of X11/extensions/XShm.h
68 #include <X11/extensions/Xv.h>
69 #include <X11/extensions/Xvlib.h>
71 // FIXME: dynamically allocate this stuff
72 static void allocate_xvimage(int);
73 static unsigned int ver
, rel
, req
, ev
, err
;
74 static unsigned int formats
, adaptors
, xv_format
;
75 static XvAdaptorInfo
*ai
= NULL
;
76 static XvImageFormatValues
*fo
=NULL
;
78 static int current_buf
= 0;
79 static int current_ip_buf
= 0;
80 static int num_buffers
= 1; // default
81 static int visible_buf
= -1; // -1 means: no buffer was drawn yet
82 static XvImage
*xvimage
[NUM_BUFFERS
];
85 static uint32_t image_width
;
86 static uint32_t image_height
;
87 static uint32_t image_format
;
93 static uint32_t drwX
, drwY
, drwBorderWidth
, drwDepth
;
94 static uint32_t max_width
= 0, max_height
= 0; // zero means: not set
96 static void (*draw_alpha_fnc
) (int x0
, int y0
, int w
, int h
,
97 unsigned char *src
, unsigned char *srca
,
100 static void draw_alpha_yv12(int x0
, int y0
, int w
, int h
,
101 unsigned char *src
, unsigned char *srca
,
104 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
105 vo_draw_alpha_yv12(w
, h
, src
, srca
, stride
,
106 xvimage
[current_buf
]->data
+
107 xvimage
[current_buf
]->offsets
[0] +
108 xvimage
[current_buf
]->pitches
[0] * y0
+ x0
,
109 xvimage
[current_buf
]->pitches
[0]);
112 static void draw_alpha_yuy2(int x0
, int y0
, int w
, int h
,
113 unsigned char *src
, unsigned char *srca
,
116 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
117 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
118 xvimage
[current_buf
]->data
+
119 xvimage
[current_buf
]->offsets
[0] +
120 xvimage
[current_buf
]->pitches
[0] * y0
+ 2 * x0
,
121 xvimage
[current_buf
]->pitches
[0]);
124 static void draw_alpha_uyvy(int x0
, int y0
, int w
, int h
,
125 unsigned char *src
, unsigned char *srca
,
128 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
129 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
130 xvimage
[current_buf
]->data
+
131 xvimage
[current_buf
]->offsets
[0] +
132 xvimage
[current_buf
]->pitches
[0] * y0
+ 2 * x0
+ 1,
133 xvimage
[current_buf
]->pitches
[0]);
136 static void draw_alpha_null(int x0
, int y0
, int w
, int h
,
137 unsigned char *src
, unsigned char *srca
,
143 static void deallocate_xvimage(int foo
);
145 static void calc_drwXY(uint32_t *drwX
, uint32_t *drwY
) {
148 aspect(&vo_dwidth
, &vo_dheight
, A_ZOOM
);
149 vo_dwidth
= FFMIN(vo_dwidth
, vo_screenwidth
);
150 vo_dheight
= FFMIN(vo_dheight
, vo_screenheight
);
151 *drwX
= (vo_screenwidth
- vo_dwidth
) / 2;
152 *drwY
= (vo_screenheight
- vo_dheight
) / 2;
153 mp_msg(MSGT_VO
, MSGL_V
, "[xv-fs] dx: %d dy: %d dw: %d dh: %d\n",
154 *drwX
, *drwY
, vo_dwidth
, vo_dheight
);
155 } else if (WinID
== 0) {
162 * connect to server, create and map window,
163 * allocate colors and (shared) memory
165 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
166 uint32_t d_height
, uint32_t flags
, char *title
,
172 XSetWindowAttributes xswa
;
173 XWindowAttributes attribs
;
174 unsigned long xswamask
;
179 unsigned int modeline_width
, modeline_height
;
180 static uint32_t vm_width
;
181 static uint32_t vm_height
;
184 image_height
= height
;
186 image_format
= format
;
188 if ((max_width
!= 0 && max_height
!= 0) &&
189 (image_width
> max_width
|| image_height
> max_height
))
191 mp_msg( MSGT_VO
, MSGL_ERR
, MSGTR_VO_XV_ImagedimTooHigh
,
192 image_width
, image_height
, max_width
, max_height
);
196 vo_mouse_autohide
= 1;
202 if (flags
& VOFLAG_MODESWITCHING
)
205 flip_flag
= flags
& VOFLAG_FLIPPING
;
207 vo_doublebuffering
? (vo_directrendering
? NUM_BUFFERS
: 2) : 1;
209 /* check image formats */
214 for (i
= 0; i
< formats
; i
++)
216 mp_msg(MSGT_VO
, MSGL_V
,
217 "Xvideo image format: 0x%x (%4.4s) %s\n", fo
[i
].id
,
219 (fo
[i
].format
== XvPacked
) ? "packed" : "planar");
220 if (fo
[i
].id
== format
)
221 xv_format
= fo
[i
].id
;
229 guiGetEvent(guiSetShVideo
, 0); // let the GUI to setup/resize our window
235 hint
.width
= d_width
;
236 hint
.height
= d_height
;
240 if ((d_width
== 0) && (d_height
== 0))
242 vm_width
= image_width
;
243 vm_height
= image_height
;
247 vm_height
= d_height
;
249 vo_vm_switch(vm_width
, vm_height
, &modeline_width
,
251 hint
.x
= (vo_screenwidth
- modeline_width
) / 2;
252 hint
.y
= (vo_screenheight
- modeline_height
) / 2;
253 hint
.width
= modeline_width
;
254 hint
.height
= modeline_height
;
255 aspect_save_screenres(modeline_width
, modeline_height
);
258 hint
.flags
= PPosition
| PSize
/* | PBaseSize */ ;
259 hint
.base_width
= hint
.width
;
260 hint
.base_height
= hint
.height
;
261 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
),
263 depth
= attribs
.depth
;
264 if (depth
!= 15 && depth
!= 16 && depth
!= 24 && depth
!= 32)
266 XMatchVisualInfo(mDisplay
, mScreen
, depth
, TrueColor
, &vinfo
);
268 xswa
.background_pixel
= 0;
269 if (xv_ck_info
.method
== CK_METHOD_BACKGROUND
)
271 xswa
.background_pixel
= xv_colorkey
;
273 xswa
.border_pixel
= 0;
274 xswamask
= CWBackPixel
| CWBorderPixel
;
278 vo_window
= WinID
? ((Window
) WinID
) : mRootWin
;
281 XUnmapWindow(mDisplay
, vo_window
);
282 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
,
284 vo_x11_selectinput_witherr(mDisplay
, vo_window
,
285 StructureNotifyMask
|
292 XMapWindow(mDisplay
, vo_window
);
293 XGetGeometry(mDisplay
, vo_window
, &mRoot
,
294 &drwX
, &drwY
, &vo_dwidth
, &vo_dheight
,
295 &drwBorderWidth
, &drwDepth
);
296 if (vo_dwidth
<= 0) vo_dwidth
= d_width
;
297 if (vo_dheight
<= 0) vo_dheight
= d_height
;
298 aspect_save_prescale(vo_dwidth
, vo_dheight
);
302 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
, d_width
, d_height
,
303 flags
, CopyFromParent
, "xv", title
);
304 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
308 XFreeGC(mDisplay
, vo_gc
);
309 vo_gc
= XCreateGC(mDisplay
, vo_window
, 0L, &xgcv
);
310 XSync(mDisplay
, False
);
314 /* Grab the mouse pointer in our window */
316 XGrabPointer(mDisplay
, vo_window
, True
, 0,
317 GrabModeAsync
, GrabModeAsync
,
318 vo_window
, None
, CurrentTime
);
319 XSetInputFocus(mDisplay
, vo_window
, RevertToNone
, CurrentTime
);
324 mp_msg(MSGT_VO
, MSGL_V
, "using Xvideo port %d for hw scaling\n",
332 draw_alpha_fnc
= draw_alpha_yv12
;
336 draw_alpha_fnc
= draw_alpha_yuy2
;
339 draw_alpha_fnc
= draw_alpha_uyvy
;
342 draw_alpha_fnc
= draw_alpha_null
;
346 for (current_buf
= 0; current_buf
< num_buffers
; ++current_buf
)
347 deallocate_xvimage(current_buf
);
349 for (current_buf
= 0; current_buf
< num_buffers
; ++current_buf
)
350 allocate_xvimage(current_buf
);
356 set_gamma_correction();
359 aspect(&vo_dwidth
, &vo_dheight
, A_NOZOOM
);
360 if ((flags
& VOFLAG_FULLSCREEN
) && WinID
<= 0) vo_fs
= 1;
361 calc_drwXY(&drwX
, &drwY
);
365 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
366 drwY
- (vo_panscan_y
>> 1),
367 vo_dwidth
+ vo_panscan_x
- 1,
368 vo_dheight
+ vo_panscan_y
- 1);
375 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
376 xvimage
[current_buf
], 0, 0, image_width
,
377 image_height
, drwX
, drwY
, 1, 1, False
);
378 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
379 xvimage
[current_buf
], 0, 0, image_width
,
380 image_height
, drwX
, drwY
, vo_dwidth
,
381 (vo_fs
? vo_dheight
- 1 : vo_dheight
), False
);
385 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
386 xvimage
[current_buf
], 0, 0, image_width
, image_height
,
388 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
389 xvimage
[current_buf
], 0, 0, image_width
, image_height
,
390 drwX
, drwY
, vo_dwidth
,
391 (vo_fs
? vo_dheight
- 1 : vo_dheight
));
395 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX
,
396 drwY
, vo_dwidth
, vo_dheight
);
399 vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
404 static void allocate_xvimage(int foo
)
407 * allocate XvImages. FIXME: no error checking, without
408 * mit-shm this will bomb... trzing to fix ::atmos
411 if (mLocalDisplay
&& XShmQueryExtension(mDisplay
))
416 mp_msg(MSGT_VO
, MSGL_INFO
,
417 MSGTR_LIBVO_XV_SharedMemoryNotSupported
);
422 (XvImage
*) XvShmCreateImage(mDisplay
, xv_port
, xv_format
,
423 NULL
, image_width
, image_height
,
427 shmget(IPC_PRIVATE
, xvimage
[foo
]->data_size
, IPC_CREAT
| 0777);
428 Shminfo
[foo
].shmaddr
= (char *) shmat(Shminfo
[foo
].shmid
, 0, 0);
429 Shminfo
[foo
].readOnly
= False
;
431 xvimage
[foo
]->data
= Shminfo
[foo
].shmaddr
;
432 XShmAttach(mDisplay
, &Shminfo
[foo
]);
433 XSync(mDisplay
, False
);
434 shmctl(Shminfo
[foo
].shmid
, IPC_RMID
, 0);
439 (XvImage
*) XvCreateImage(mDisplay
, xv_port
, xv_format
, NULL
,
440 image_width
, image_height
);
441 xvimage
[foo
]->data
= malloc(xvimage
[foo
]->data_size
);
442 XSync(mDisplay
, False
);
444 memset(xvimage
[foo
]->data
, 128, xvimage
[foo
]->data_size
);
448 static void deallocate_xvimage(int foo
)
453 XShmDetach(mDisplay
, &Shminfo
[foo
]);
454 shmdt(Shminfo
[foo
].shmaddr
);
458 free(xvimage
[foo
]->data
);
462 XSync(mDisplay
, False
);
466 static inline void put_xvimage( XvImage
* xvi
)
471 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
472 xvi
, 0, 0, image_width
,
473 image_height
, drwX
- (vo_panscan_x
>> 1),
474 drwY
- (vo_panscan_y
>> 1), vo_dwidth
+ vo_panscan_x
,
475 vo_dheight
+ vo_panscan_y
,
480 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
481 xvi
, 0, 0, image_width
, image_height
,
482 drwX
- (vo_panscan_x
>> 1), drwY
- (vo_panscan_y
>> 1),
483 vo_dwidth
+ vo_panscan_x
,
484 vo_dheight
+ vo_panscan_y
);
488 static void check_events(void)
490 int e
= vo_x11_check_events(mDisplay
);
492 if (e
& VO_EVENT_RESIZE
)
494 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &vo_dwidth
,
495 &vo_dheight
, &drwBorderWidth
, &drwDepth
);
496 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX
,
497 drwY
, vo_dwidth
, vo_dheight
);
499 calc_drwXY(&drwX
, &drwY
);
502 if (e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
)
504 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
505 drwY
- (vo_panscan_y
>> 1),
506 vo_dwidth
+ vo_panscan_x
- 1,
507 vo_dheight
+ vo_panscan_y
- 1);
510 if ((e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
) && int_pause
)
512 /* did we already draw a buffer */
513 if ( visible_buf
!= -1 )
515 /* redraw the last visible buffer */
516 put_xvimage( xvimage
[visible_buf
] );
521 static void draw_osd(void)
523 vo_draw_text(image_width
-
524 image_width
* vo_panscan_x
/ (vo_dwidth
+ vo_panscan_x
),
525 image_height
, draw_alpha_fnc
);
528 static void flip_page(void)
530 put_xvimage( xvimage
[current_buf
] );
532 /* remember the currently visible buffer */
533 visible_buf
= current_buf
;
538 vo_directrendering
? 0 : ((current_buf
+ 1) % num_buffers
);
541 XSync(mDisplay
, False
);
545 static int draw_slice(uint8_t * image
[], int stride
[], int w
, int h
,
550 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[0] +
551 xvimage
[current_buf
]->pitches
[0] * y
+ x
;
552 memcpy_pic(dst
, image
[0], w
, h
, xvimage
[current_buf
]->pitches
[0],
560 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[1] +
561 xvimage
[current_buf
]->pitches
[1] * y
+ x
;
562 if (image_format
!= IMGFMT_YV12
)
563 memcpy_pic(dst
, image
[1], w
, h
, xvimage
[current_buf
]->pitches
[1],
566 memcpy_pic(dst
, image
[2], w
, h
, xvimage
[current_buf
]->pitches
[1],
569 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[2] +
570 xvimage
[current_buf
]->pitches
[2] * y
+ x
;
571 if (image_format
== IMGFMT_YV12
)
572 memcpy_pic(dst
, image
[1], w
, h
, xvimage
[current_buf
]->pitches
[1],
575 memcpy_pic(dst
, image
[2], w
, h
, xvimage
[current_buf
]->pitches
[1],
581 static int draw_frame(uint8_t * src
[])
583 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_XV_DrawFrameCalled
);
587 static uint32_t draw_image(mp_image_t
* mpi
)
589 if (mpi
->flags
& MP_IMGFLAG_DIRECT
)
592 current_buf
= (int) (mpi
->priv
); // hack!
595 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
596 return VO_TRUE
; // done
597 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
599 draw_slice(mpi
->planes
, mpi
->stride
, mpi
->w
, mpi
->h
, 0, 0);
602 if (mpi
->flags
& MP_IMGFLAG_YUV
)
605 memcpy_pic(xvimage
[current_buf
]->data
+
606 xvimage
[current_buf
]->offsets
[0], mpi
->planes
[0],
607 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
608 xvimage
[current_buf
]->pitches
[0], mpi
->stride
[0]);
611 return VO_FALSE
; // not (yet) supported
614 static uint32_t get_image(mp_image_t
* mpi
)
616 int buf
= current_buf
; // we shouldn't change current_buf unless we do DR!
618 if (mpi
->type
== MP_IMGTYPE_STATIC
&& num_buffers
> 1)
619 return VO_FALSE
; // it is not static
620 if (mpi
->imgfmt
!= image_format
)
621 return VO_FALSE
; // needs conversion :(
622 // if(mpi->flags&MP_IMGFLAG_READABLE) return VO_FALSE; // slow video ram
623 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
624 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
))
626 // reference (I/P) frame of IP or IPB:
628 return VO_FALSE
; // not enough
630 // for IPB with 2 buffers we can DR only one of the 2 P frames:
631 if (mpi
->type
== MP_IMGTYPE_IPB
&& num_buffers
< 3
634 buf
= current_ip_buf
;
635 if (mpi
->type
== MP_IMGTYPE_IPB
)
636 ++buf
; // preserve space for B
638 if (mpi
->height
> xvimage
[buf
]->height
)
639 return VO_FALSE
; //buffer to small
640 if (mpi
->width
* (mpi
->bpp
/ 8) > xvimage
[buf
]->pitches
[0])
641 return VO_FALSE
; //buffer to small
642 if ((mpi
->flags
& (MP_IMGFLAG_ACCEPT_STRIDE
| MP_IMGFLAG_ACCEPT_WIDTH
))
643 || (mpi
->width
* (mpi
->bpp
/ 8) == xvimage
[buf
]->pitches
[0]))
647 xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[0];
648 mpi
->stride
[0] = xvimage
[current_buf
]->pitches
[0];
649 mpi
->width
= mpi
->stride
[0] / (mpi
->bpp
/ 8);
650 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
652 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
)
656 xvimage
[current_buf
]->data
+
657 xvimage
[current_buf
]->offsets
[1];
659 xvimage
[current_buf
]->data
+
660 xvimage
[current_buf
]->offsets
[2];
661 mpi
->stride
[1] = xvimage
[current_buf
]->pitches
[1];
662 mpi
->stride
[2] = xvimage
[current_buf
]->pitches
[2];
667 xvimage
[current_buf
]->data
+
668 xvimage
[current_buf
]->offsets
[2];
670 xvimage
[current_buf
]->data
+
671 xvimage
[current_buf
]->offsets
[1];
672 mpi
->stride
[1] = xvimage
[current_buf
]->pitches
[2];
673 mpi
->stride
[2] = xvimage
[current_buf
]->pitches
[1];
676 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
677 mpi
->priv
= (void *) current_buf
;
678 // printf("mga: get_image() SUCCESS -> Direct Rendering ENABLED\n");
684 static int query_format(uint32_t format
)
687 int flag
= VFCAP_CSP_SUPPORTED
| VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP
| VFCAP_HWSCALE_DOWN
| VFCAP_OSD
| VFCAP_ACCEPT_STRIDE
; // FIXME! check for DOWN
689 /* check image formats */
690 for (i
= 0; i
< formats
; i
++)
692 if (fo
[i
].id
== format
)
693 return flag
; //xv_format = fo[i].id;
698 static void uninit(void)
702 if (!vo_config_count
)
705 XvFreeAdaptorInfo(ai
);
711 for (i
= 0; i
< num_buffers
; i
++)
712 deallocate_xvimage(i
);
714 vo_vm_close(mDisplay
);
716 mp_input_rm_event_fd(ConnectionNumber(mDisplay
));
720 static int preinit(const char *arg
)
725 strarg_t ck_src_arg
= { 0, NULL
};
726 strarg_t ck_method_arg
= { 0, NULL
};
730 /* name arg type arg var test */
731 { "port", OPT_ARG_INT
, &xv_port
, (opt_test_f
)int_pos
},
732 { "ck", OPT_ARG_STR
, &ck_src_arg
, xv_test_ck
},
733 { "ck-method", OPT_ARG_STR
, &ck_method_arg
, xv_test_ckm
},
739 /* parse suboptions */
740 if ( subopt_parse( arg
, subopts
) != 0 )
745 /* modify colorkey settings according to the given options */
746 xv_setup_colorkeyhandling( ck_method_arg
.str
, ck_src_arg
.str
);
751 /* check for Xvideo extension */
752 if (Success
!= XvQueryExtension(mDisplay
, &ver
, &rel
, &req
, &ev
, &err
))
754 mp_msg(MSGT_VO
, MSGL_ERR
,
755 MSGTR_LIBVO_XV_XvNotSupportedByX11
);
759 /* check for Xvideo support */
761 XvQueryAdaptors(mDisplay
, DefaultRootWindow(mDisplay
), &adaptors
,
764 mp_msg(MSGT_VO
, MSGL_ERR
, MSGTR_LIBVO_XV_XvQueryAdaptorsFailed
);
773 for (port_found
= 0, i
= 0; !port_found
&& i
< adaptors
; i
++)
775 if ((ai
[i
].type
& XvInputMask
) && (ai
[i
].type
& XvImageMask
))
777 for (xv_p
= ai
[i
].base_id
;
778 xv_p
< ai
[i
].base_id
+ ai
[i
].num_ports
; ++xv_p
)
790 if (XvGrabPort(mDisplay
, xv_port
, CurrentTime
))
794 mp_msg(MSGT_VO
, MSGL_WARN
,
795 MSGTR_LIBVO_XV_InvalidPortParameter
);
800 for (i
= 0; i
< adaptors
&& xv_port
== 0; i
++)
802 if ((ai
[i
].type
& XvInputMask
) && (ai
[i
].type
& XvImageMask
))
804 for (xv_p
= ai
[i
].base_id
;
805 xv_p
< ai
[i
].base_id
+ ai
[i
].num_ports
; ++xv_p
)
806 if (!XvGrabPort(mDisplay
, xv_p
, CurrentTime
))
812 mp_msg(MSGT_VO
, MSGL_WARN
,
813 MSGTR_LIBVO_XV_CouldNotGrabPort
, (int) xv_p
);
821 mp_msg(MSGT_VO
, MSGL_ERR
,
822 MSGTR_LIBVO_XV_CouldNotFindFreePort
);
824 mp_msg(MSGT_VO
, MSGL_ERR
,
825 MSGTR_LIBVO_XV_NoXvideoSupport
);
829 if ( !vo_xv_init_colorkey() )
831 return -1; // bail out, colorkey setup failed
833 vo_xv_enable_vsync();
834 vo_xv_get_max_img_dim( &max_width
, &max_height
);
836 fo
= XvListImageFormats(mDisplay
, xv_port
, (int *) &formats
);
838 mp_input_add_event_fd(ConnectionNumber(mDisplay
), check_events
);
842 static int control(uint32_t request
, void *data
, ...)
847 return (int_pause
= 1);
849 return (int_pause
= 0);
850 case VOCTRL_QUERY_FORMAT
:
851 return query_format(*((uint32_t *) data
));
852 case VOCTRL_GET_IMAGE
:
853 return get_image(data
);
854 case VOCTRL_DRAW_IMAGE
:
855 return draw_image(data
);
856 case VOCTRL_GUISUPPORT
:
858 case VOCTRL_GET_PANSCAN
:
859 if (!vo_config_count
|| !vo_fs
)
862 case VOCTRL_FULLSCREEN
:
864 /* indended, fallthrough to update panscan on fullscreen/windowed switch */
865 case VOCTRL_SET_PANSCAN
:
866 if ((vo_fs
&& (vo_panscan
!= vo_panscan_amount
))
867 || (!vo_fs
&& vo_panscan_amount
))
869 int old_y
= vo_panscan_y
;
873 if (old_y
!= vo_panscan_y
)
875 vo_x11_clearwindow_part(mDisplay
, vo_window
,
876 vo_dwidth
+ vo_panscan_x
- 1,
877 vo_dheight
+ vo_panscan_y
- 1,
879 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
880 drwY
- (vo_panscan_y
>> 1),
881 vo_dwidth
+ vo_panscan_x
- 1,
882 vo_dheight
+ vo_panscan_y
- 1);
887 case VOCTRL_SET_EQUALIZER
:
893 value
= va_arg(ap
, int);
897 return (vo_xv_set_eq(xv_port
, data
, value
));
899 case VOCTRL_GET_EQUALIZER
:
905 value
= va_arg(ap
, int *);
909 return (vo_xv_get_eq(xv_port
, data
, value
));
914 case VOCTRL_UPDATE_SCREENINFO
:
915 update_xinerama_info();