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)
27 #include "video_out.h"
28 #include "libmpcodecs/vfcap.h"
29 #include "libmpcodecs/mp_image.h"
33 #include <X11/Xutil.h>
36 #include "x11_common.h"
38 #include "fastmemcpy.h"
42 #include "subopt-helper.h"
44 #include "input/input.h"
47 #include "gui/interface.h"
50 #include "libavutil/common.h"
52 static const vo_info_t info
= {
55 "Gerd Knorr <kraxel@goldbach.in-berlin.de> and others",
62 #include <X11/extensions/XShm.h>
65 // Note: depends on the inclusion of X11/extensions/XShm.h
66 #include <X11/extensions/Xv.h>
67 #include <X11/extensions/Xvlib.h>
72 XvImageFormatValues
*fo
;
73 unsigned int formats
, adaptors
, xv_format
;
78 XvImage
*xvimage
[NUM_BUFFERS
];
80 uint32_t image_height
;
81 uint32_t image_format
;
84 uint32_t max_width
, max_height
; // zero means: not set
85 void (*draw_alpha_fnc
)(void *ctx
, int x0
, int y0
, int w
, int h
,
86 unsigned char *src
, unsigned char *srca
,
89 XShmSegmentInfo Shminfo
[NUM_BUFFERS
];
94 // FIXME: dynamically allocate this stuff
95 static void allocate_xvimage(struct vo
*, int);
99 static void draw_alpha_yv12(void *p
, int x0
, int y0
, int w
, int h
,
100 unsigned char *src
, unsigned char *srca
,
104 struct xvctx
*ctx
= vo
->priv
;
105 x0
+= ctx
->image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
106 vo_draw_alpha_yv12(w
, h
, src
, srca
, stride
,
107 ctx
->xvimage
[ctx
->current_buf
]->data
+
108 ctx
->xvimage
[ctx
->current_buf
]->offsets
[0] +
109 ctx
->xvimage
[ctx
->current_buf
]->pitches
[0] * y0
+ x0
,
110 ctx
->xvimage
[ctx
->current_buf
]->pitches
[0]);
113 static void draw_alpha_yuy2(void *p
, int x0
, int y0
, int w
, int h
,
114 unsigned char *src
, unsigned char *srca
,
118 struct xvctx
*ctx
= vo
->priv
;
119 x0
+= ctx
->image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
120 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
121 ctx
->xvimage
[ctx
->current_buf
]->data
+
122 ctx
->xvimage
[ctx
->current_buf
]->offsets
[0] +
123 ctx
->xvimage
[ctx
->current_buf
]->pitches
[0] * y0
+ 2 * x0
,
124 ctx
->xvimage
[ctx
->current_buf
]->pitches
[0]);
127 static void draw_alpha_uyvy(void *p
, int x0
, int y0
, int w
, int h
,
128 unsigned char *src
, unsigned char *srca
,
132 struct xvctx
*ctx
= vo
->priv
;
133 x0
+= ctx
->image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
134 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
135 ctx
->xvimage
[ctx
->current_buf
]->data
+
136 ctx
->xvimage
[ctx
->current_buf
]->offsets
[0] +
137 ctx
->xvimage
[ctx
->current_buf
]->pitches
[0] * y0
+ 2 * x0
+ 1,
138 ctx
->xvimage
[ctx
->current_buf
]->pitches
[0]);
141 static void draw_alpha_null(void *p
, int x0
, int y0
, int w
, int h
,
142 unsigned char *src
, unsigned char *srca
,
148 static void deallocate_xvimage(struct vo
*vo
, int foo
);
150 static void calc_drwXY(uint32_t *drwX
, uint32_t *drwY
) {
153 aspect(&vo_dwidth
, &vo_dheight
, A_ZOOM
);
154 vo_dwidth
= FFMIN(vo_dwidth
, vo_screenwidth
);
155 vo_dheight
= FFMIN(vo_dheight
, vo_screenheight
);
156 *drwX
= (vo_screenwidth
- vo_dwidth
) / 2;
157 *drwY
= (vo_screenheight
- vo_dheight
) / 2;
158 mp_msg(MSGT_VO
, MSGL_V
, "[xv-fs] dx: %d dy: %d dw: %d dh: %d\n",
159 *drwX
, *drwY
, vo_dwidth
, vo_dheight
);
160 } else if (WinID
== 0) {
167 * connect to server, create and map window,
168 * allocate colors and (shared) memory
170 static int config(struct vo
*vo
, uint32_t width
, uint32_t height
,
171 uint32_t d_width
, uint32_t d_height
, uint32_t flags
,
172 char *title
, uint32_t format
)
177 XSetWindowAttributes xswa
;
178 XWindowAttributes attribs
;
179 unsigned long xswamask
;
181 struct xvctx
*ctx
= vo
->priv
;
184 ctx
->image_height
= height
;
185 ctx
->image_width
= width
;
186 ctx
->image_format
= format
;
188 if ((ctx
->max_width
!= 0 && ctx
->max_height
!= 0) &&
189 (ctx
->image_width
> ctx
->max_width
|| ctx
->image_height
> ctx
->max_height
))
191 mp_msg( MSGT_VO
, MSGL_ERR
, MSGTR_VO_XV_ImagedimTooHigh
,
192 ctx
->image_width
, ctx
->image_height
, ctx
->max_width
, ctx
->max_height
);
196 vo_mouse_autohide
= 1;
199 ctx
->visible_buf
= -1;
201 /* check image formats */
203 for (i
= 0; i
< ctx
->formats
; i
++) {
204 mp_msg(MSGT_VO
, MSGL_V
,
205 "Xvideo image format: 0x%x (%4.4s) %s\n", ctx
->fo
[i
].id
,
206 (char *) &ctx
->fo
[i
].id
,
207 (ctx
->fo
[i
].format
== XvPacked
) ? "packed" : "planar");
208 if (ctx
->fo
[i
].id
== format
)
209 ctx
->xv_format
= ctx
->fo
[i
].id
;
216 guiGetEvent(guiSetShVideo
, 0); // let the GUI to setup/resize our window
222 hint
.width
= d_width
;
223 hint
.height
= d_height
;
225 unsigned int modeline_width
, modeline_height
;
228 int vm
= flags
& VOFLAG_MODESWITCHING
;
231 if ((d_width
== 0) && (d_height
== 0))
233 vm_width
= ctx
->image_width
;
234 vm_height
= ctx
->image_height
;
238 vm_height
= d_height
;
240 vo_vm_switch(vm_width
, vm_height
, &modeline_width
,
242 hint
.x
= (vo_screenwidth
- modeline_width
) / 2;
243 hint
.y
= (vo_screenheight
- modeline_height
) / 2;
244 hint
.width
= modeline_width
;
245 hint
.height
= modeline_height
;
246 aspect_save_screenres(modeline_width
, modeline_height
);
248 #warning This "else" makes no sense
250 hint
.flags
= PPosition
| PSize
/* | PBaseSize */ ;
251 hint
.base_width
= hint
.width
;
252 hint
.base_height
= hint
.height
;
253 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
),
255 depth
= attribs
.depth
;
256 if (depth
!= 15 && depth
!= 16 && depth
!= 24 && depth
!= 32)
258 XMatchVisualInfo(mDisplay
, mScreen
, depth
, TrueColor
, &vinfo
);
260 xswa
.background_pixel
= 0;
261 if (xv_ck_info
.method
== CK_METHOD_BACKGROUND
)
263 xswa
.background_pixel
= xv_colorkey
;
265 xswa
.border_pixel
= 0;
266 xswamask
= CWBackPixel
| CWBorderPixel
;
270 vo_window
= WinID
? ((Window
) WinID
) : mRootWin
;
273 XUnmapWindow(mDisplay
, vo_window
);
274 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
,
276 vo_x11_selectinput_witherr(mDisplay
, vo_window
,
277 StructureNotifyMask
|
284 XMapWindow(mDisplay
, vo_window
);
286 uint32_t drwBorderWidth
, drwDepth
;
287 XGetGeometry(mDisplay
, vo_window
, &mRoot
,
288 &ctx
->drwX
, &ctx
->drwY
, &vo_dwidth
, &vo_dheight
,
289 &drwBorderWidth
, &drwDepth
);
290 if (vo_dwidth
<= 0) vo_dwidth
= d_width
;
291 if (vo_dheight
<= 0) vo_dheight
= d_height
;
292 aspect_save_prescale(vo_dwidth
, vo_dheight
);
296 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
, d_width
, d_height
,
297 flags
, CopyFromParent
, "xv", title
);
298 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
302 XFreeGC(mDisplay
, vo_gc
);
303 vo_gc
= XCreateGC(mDisplay
, vo_window
, 0L, &xgcv
);
304 XSync(mDisplay
, False
);
308 /* Grab the mouse pointer in our window */
310 XGrabPointer(mDisplay
, vo_window
, True
, 0,
311 GrabModeAsync
, GrabModeAsync
,
312 vo_window
, None
, CurrentTime
);
313 XSetInputFocus(mDisplay
, vo_window
, RevertToNone
, CurrentTime
);
318 mp_msg(MSGT_VO
, MSGL_V
, "using Xvideo port %d for hw scaling\n",
321 switch (ctx
->xv_format
)
326 ctx
->draw_alpha_fnc
= draw_alpha_yv12
;
330 ctx
->draw_alpha_fnc
= draw_alpha_yuy2
;
333 ctx
->draw_alpha_fnc
= draw_alpha_uyvy
;
336 ctx
->draw_alpha_fnc
= draw_alpha_null
;
339 // In case config has been called before
340 for (i
= 0; i
< ctx
->num_buffers
; i
++)
341 deallocate_xvimage(vo
, i
);
344 vo_doublebuffering
? (vo_directrendering
? NUM_BUFFERS
: 2) : 1;
346 for (i
= 0; i
< ctx
->num_buffers
; i
++)
347 allocate_xvimage(vo
, i
);
349 ctx
->current_buf
= 0;
350 ctx
->current_ip_buf
= 0;
353 set_gamma_correction();
356 aspect(&vo_dwidth
, &vo_dheight
, A_NOZOOM
);
357 if ((flags
& VOFLAG_FULLSCREEN
) && WinID
<= 0) vo_fs
= 1;
358 calc_drwXY(&ctx
->drwX
, &ctx
->drwY
);
362 vo_xv_draw_colorkey(ctx
->drwX
- (vo_panscan_x
>> 1),
363 ctx
->drwY
- (vo_panscan_y
>> 1),
364 vo_dwidth
+ vo_panscan_x
- 1,
365 vo_dheight
+ vo_panscan_y
- 1);
367 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", ctx
->drwX
,
368 ctx
->drwY
, vo_dwidth
, vo_dheight
);
371 vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
376 static void allocate_xvimage(struct vo
*vo
, int foo
)
378 struct xvctx
*ctx
= vo
->priv
;
380 * allocate XvImages. FIXME: no error checking, without
381 * mit-shm this will bomb... trzing to fix ::atmos
384 if (mLocalDisplay
&& XShmQueryExtension(mDisplay
))
389 mp_msg(MSGT_VO
, MSGL_INFO
,
390 MSGTR_LIBVO_XV_SharedMemoryNotSupported
);
395 (XvImage
*) XvShmCreateImage(mDisplay
, xv_port
, ctx
->xv_format
,
396 NULL
, ctx
->image_width
, ctx
->image_height
,
399 ctx
->Shminfo
[foo
].shmid
=
400 shmget(IPC_PRIVATE
, ctx
->xvimage
[foo
]->data_size
, IPC_CREAT
| 0777);
401 ctx
->Shminfo
[foo
].shmaddr
= (char *) shmat(ctx
->Shminfo
[foo
].shmid
, 0, 0);
402 ctx
->Shminfo
[foo
].readOnly
= False
;
404 ctx
->xvimage
[foo
]->data
= ctx
->Shminfo
[foo
].shmaddr
;
405 XShmAttach(mDisplay
, &ctx
->Shminfo
[foo
]);
406 XSync(mDisplay
, False
);
407 shmctl(ctx
->Shminfo
[foo
].shmid
, IPC_RMID
, 0);
412 (XvImage
*) XvCreateImage(mDisplay
, xv_port
, ctx
->xv_format
, NULL
,
413 ctx
->image_width
, ctx
->image_height
);
414 ctx
->xvimage
[foo
]->data
= malloc(ctx
->xvimage
[foo
]->data_size
);
415 XSync(mDisplay
, False
);
417 memset(ctx
->xvimage
[foo
]->data
, 128, ctx
->xvimage
[foo
]->data_size
);
421 static void deallocate_xvimage(struct vo
*vo
, int foo
)
423 struct xvctx
*ctx
= vo
->priv
;
427 XShmDetach(mDisplay
, &ctx
->Shminfo
[foo
]);
428 shmdt(ctx
->Shminfo
[foo
].shmaddr
);
432 free(ctx
->xvimage
[foo
]->data
);
434 XFree(ctx
->xvimage
[foo
]);
436 XSync(mDisplay
, False
);
440 static inline void put_xvimage(struct vo
*vo
, XvImage
*xvi
)
442 struct xvctx
*ctx
= vo
->priv
;
446 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
447 xvi
, 0, 0, ctx
->image_width
,
448 ctx
->image_height
, ctx
->drwX
- (vo_panscan_x
>> 1),
449 ctx
->drwY
- (vo_panscan_y
>> 1), vo_dwidth
+ vo_panscan_x
,
450 vo_dheight
+ vo_panscan_y
,
455 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
456 xvi
, 0, 0, ctx
->image_width
, ctx
->image_height
,
457 ctx
->drwX
- (vo_panscan_x
>> 1), ctx
->drwY
- (vo_panscan_y
>> 1),
458 vo_dwidth
+ vo_panscan_x
,
459 vo_dheight
+ vo_panscan_y
);
463 static void check_events(struct vo
*vo
)
465 struct xvctx
*ctx
= vo
->priv
;
466 int e
= vo_x11_check_events(mDisplay
);
468 if (e
& VO_EVENT_RESIZE
)
471 uint32_t drwBorderWidth
, drwDepth
;
472 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &ctx
->drwX
, &ctx
->drwY
,
473 &vo_dwidth
, &vo_dheight
, &drwBorderWidth
, &drwDepth
);
474 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", ctx
->drwX
,
475 ctx
->drwY
, vo_dwidth
, vo_dheight
);
477 calc_drwXY(&ctx
->drwX
, &ctx
->drwY
);
480 if (e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
)
482 vo_xv_draw_colorkey(ctx
->drwX
- (vo_panscan_x
>> 1),
483 ctx
->drwY
- (vo_panscan_y
>> 1),
484 vo_dwidth
+ vo_panscan_x
- 1,
485 vo_dheight
+ vo_panscan_y
- 1);
488 if ((e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
) && ctx
->is_paused
)
490 /* did we already draw a buffer */
491 if ( ctx
->visible_buf
!= -1 )
493 /* redraw the last visible buffer */
494 put_xvimage(vo
, ctx
->xvimage
[ctx
->visible_buf
]);
499 static void draw_osd(struct vo
*vo
)
501 struct xvctx
*ctx
= vo
->priv
;
503 osd_draw_text(ctx
->image_width
-
504 ctx
->image_width
* vo_panscan_x
/ (vo_dwidth
+ vo_panscan_x
),
505 ctx
->image_height
, ctx
->draw_alpha_fnc
, vo
);
508 static void flip_page(struct vo
*vo
)
510 struct xvctx
*ctx
= vo
->priv
;
511 put_xvimage(vo
, ctx
->xvimage
[ctx
->current_buf
]);
513 /* remember the currently visible buffer */
514 ctx
->visible_buf
= ctx
->current_buf
;
516 if (ctx
->num_buffers
> 1)
519 vo_directrendering
? 0 : ((ctx
->current_buf
+ 1) % ctx
->num_buffers
);
522 XSync(mDisplay
, False
);
526 static int draw_slice(struct vo
*vo
, uint8_t * image
[], int stride
[], int w
,
529 struct xvctx
*ctx
= vo
->priv
;
531 XvImage
*current_image
= ctx
->xvimage
[ctx
->current_buf
];
533 dst
= current_image
->data
+ current_image
->offsets
[0] +
534 current_image
->pitches
[0] * y
+ x
;
535 memcpy_pic(dst
, image
[0], w
, h
, current_image
->pitches
[0],
543 dst
= current_image
->data
+ current_image
->offsets
[1] +
544 current_image
->pitches
[1] * y
+ x
;
545 if (ctx
->image_format
!= IMGFMT_YV12
)
546 memcpy_pic(dst
, image
[1], w
, h
, current_image
->pitches
[1],
549 memcpy_pic(dst
, image
[2], w
, h
, current_image
->pitches
[1],
552 dst
= current_image
->data
+ current_image
->offsets
[2] +
553 current_image
->pitches
[2] * y
+ x
;
554 if (ctx
->image_format
== IMGFMT_YV12
)
555 memcpy_pic(dst
, image
[1], w
, h
, current_image
->pitches
[1],
558 memcpy_pic(dst
, image
[2], w
, h
, current_image
->pitches
[1],
564 static int draw_frame(struct vo
*vo
, uint8_t * src
[])
566 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_XV_DrawFrameCalled
);
570 static uint32_t draw_image(struct vo
*vo
, mp_image_t
* mpi
)
572 struct xvctx
*ctx
= vo
->priv
;
573 if (mpi
->flags
& MP_IMGFLAG_DIRECT
)
576 ctx
->current_buf
= (int) (mpi
->priv
); // hack!
579 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
580 return VO_TRUE
; // done
581 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
583 draw_slice(vo
, mpi
->planes
, mpi
->stride
, mpi
->w
, mpi
->h
, 0, 0);
586 if (mpi
->flags
& MP_IMGFLAG_YUV
)
589 memcpy_pic(ctx
->xvimage
[ctx
->current_buf
]->data
+
590 ctx
->xvimage
[ctx
->current_buf
]->offsets
[0], mpi
->planes
[0],
591 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
592 ctx
->xvimage
[ctx
->current_buf
]->pitches
[0], mpi
->stride
[0]);
595 return VO_FALSE
; // not (yet) supported
598 static uint32_t get_image(struct xvctx
*ctx
, mp_image_t
* mpi
)
600 int buf
= ctx
->current_buf
; // we shouldn't change current_buf unless we do DR!
602 if (mpi
->type
== MP_IMGTYPE_STATIC
&& ctx
->num_buffers
> 1)
603 return VO_FALSE
; // it is not static
604 if (mpi
->imgfmt
!= ctx
->image_format
)
605 return VO_FALSE
; // needs conversion :(
606 // if(mpi->flags&MP_IMGFLAG_READABLE) return VO_FALSE; // slow video ram
607 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
608 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
))
610 // reference (I/P) frame of IP or IPB:
611 if (ctx
->num_buffers
< 2)
612 return VO_FALSE
; // not enough
613 ctx
->current_ip_buf
^= 1;
614 // for IPB with 2 buffers we can DR only one of the 2 P frames:
615 if (mpi
->type
== MP_IMGTYPE_IPB
&& ctx
->num_buffers
< 3
616 && ctx
->current_ip_buf
)
618 buf
= ctx
->current_ip_buf
;
619 if (mpi
->type
== MP_IMGTYPE_IPB
)
620 ++buf
; // preserve space for B
622 if (mpi
->height
> ctx
->xvimage
[buf
]->height
)
623 return VO_FALSE
; //buffer to small
624 if (mpi
->width
* (mpi
->bpp
/ 8) > ctx
->xvimage
[buf
]->pitches
[0])
625 return VO_FALSE
; //buffer to small
626 if ((mpi
->flags
& (MP_IMGFLAG_ACCEPT_STRIDE
| MP_IMGFLAG_ACCEPT_WIDTH
))
627 || (mpi
->width
* (mpi
->bpp
/ 8) == ctx
->xvimage
[buf
]->pitches
[0]))
629 ctx
->current_buf
= buf
;
630 XvImage
*current_image
= ctx
->xvimage
[ctx
->current_buf
];
631 mpi
->planes
[0] = current_image
->data
+ current_image
->offsets
[0];
632 mpi
->stride
[0] = current_image
->pitches
[0];
633 mpi
->width
= mpi
->stride
[0] / (mpi
->bpp
/ 8);
634 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
636 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
)
640 current_image
->data
+
641 current_image
->offsets
[1];
643 current_image
->data
+
644 current_image
->offsets
[2];
645 mpi
->stride
[1] = current_image
->pitches
[1];
646 mpi
->stride
[2] = current_image
->pitches
[2];
651 current_image
->data
+
652 current_image
->offsets
[2];
654 current_image
->data
+
655 current_image
->offsets
[1];
656 mpi
->stride
[1] = current_image
->pitches
[2];
657 mpi
->stride
[2] = current_image
->pitches
[1];
660 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
661 mpi
->priv
= (void *) ctx
->current_buf
;
662 // printf("mga: get_image() SUCCESS -> Direct Rendering ENABLED\n");
668 static int query_format(struct xvctx
*ctx
, uint32_t format
)
671 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
673 /* check image formats */
674 for (i
= 0; i
< ctx
->formats
; i
++)
676 if (ctx
->fo
[i
].id
== format
)
677 return flag
; //xv_format = fo[i].id;
682 static void uninit(struct vo
*vo
)
684 struct xvctx
*ctx
= vo
->priv
;
687 if (!vo_config_count
)
689 ctx
->visible_buf
= -1;
690 XvFreeAdaptorInfo(ctx
->ai
);
696 for (i
= 0; i
< ctx
->num_buffers
; i
++)
697 deallocate_xvimage(vo
, i
);
699 vo_vm_close(mDisplay
);
701 mp_input_rm_event_fd(ConnectionNumber(mDisplay
));
707 static void x11_fd_callback(void *ctx
)
709 return check_events(ctx
);
712 static int preinit(struct vo
*vo
, const char *arg
)
717 strarg_t ck_src_arg
= { 0, NULL
};
718 strarg_t ck_method_arg
= { 0, NULL
};
719 struct xvctx
*ctx
= calloc(1, sizeof *ctx
);
724 /* name arg type arg var test */
725 { "port", OPT_ARG_INT
, &ctx
->xv_port
, (opt_test_f
)int_pos
},
726 { "ck", OPT_ARG_STR
, &ck_src_arg
, xv_test_ck
},
727 { "ck-method", OPT_ARG_STR
, &ck_method_arg
, xv_test_ckm
},
733 /* parse suboptions */
734 if ( subopt_parse( arg
, subopts
) != 0 )
739 /* modify colorkey settings according to the given options */
740 xv_setup_colorkeyhandling( ck_method_arg
.str
, ck_src_arg
.str
);
745 /* check for Xvideo extension */
746 unsigned int ver
, rel
, req
, ev
, err
;
747 if (Success
!= XvQueryExtension(mDisplay
, &ver
, &rel
, &req
, &ev
, &err
))
749 mp_msg(MSGT_VO
, MSGL_ERR
,
750 MSGTR_LIBVO_XV_XvNotSupportedByX11
);
754 /* check for Xvideo support */
756 XvQueryAdaptors(mDisplay
, DefaultRootWindow(mDisplay
), &ctx
->adaptors
,
759 mp_msg(MSGT_VO
, MSGL_ERR
, MSGTR_LIBVO_XV_XvQueryAdaptorsFailed
);
768 for (port_found
= 0, i
= 0; !port_found
&& i
< ctx
->adaptors
; i
++)
770 if ((ctx
->ai
[i
].type
& XvInputMask
) && (ctx
->ai
[i
].type
& XvImageMask
))
772 for (xv_p
= ctx
->ai
[i
].base_id
;
773 xv_p
< ctx
->ai
[i
].base_id
+ ctx
->ai
[i
].num_ports
; ++xv_p
)
785 if (XvGrabPort(mDisplay
, xv_port
, CurrentTime
))
789 mp_msg(MSGT_VO
, MSGL_WARN
,
790 MSGTR_LIBVO_XV_InvalidPortParameter
);
795 for (i
= 0; i
< ctx
->adaptors
&& xv_port
== 0; i
++)
797 if ((ctx
->ai
[i
].type
& XvInputMask
) && (ctx
->ai
[i
].type
& XvImageMask
))
799 for (xv_p
= ctx
->ai
[i
].base_id
;
800 xv_p
< ctx
->ai
[i
].base_id
+ ctx
->ai
[i
].num_ports
; ++xv_p
)
801 if (!XvGrabPort(mDisplay
, xv_p
, CurrentTime
))
807 mp_msg(MSGT_VO
, MSGL_WARN
,
808 MSGTR_LIBVO_XV_CouldNotGrabPort
, (int) xv_p
);
816 mp_msg(MSGT_VO
, MSGL_ERR
,
817 MSGTR_LIBVO_XV_CouldNotFindFreePort
);
819 mp_msg(MSGT_VO
, MSGL_ERR
,
820 MSGTR_LIBVO_XV_NoXvideoSupport
);
824 if ( !vo_xv_init_colorkey() )
826 return -1; // bail out, colorkey setup failed
828 vo_xv_enable_vsync();
829 vo_xv_get_max_img_dim(&ctx
->max_width
, &ctx
->max_height
);
831 ctx
->fo
= XvListImageFormats(mDisplay
, xv_port
, (int *) &ctx
->formats
);
833 mp_input_add_event_fd(ConnectionNumber(mDisplay
), x11_fd_callback
, vo
);
837 static int control(struct vo
*vo
, uint32_t request
, void *data
)
839 struct xvctx
*ctx
= vo
->priv
;
843 return (ctx
->is_paused
= 1);
845 return (ctx
->is_paused
= 0);
846 case VOCTRL_QUERY_FORMAT
:
847 return query_format(ctx
, *((uint32_t *) data
));
848 case VOCTRL_GET_IMAGE
:
849 return get_image(ctx
, data
);
850 case VOCTRL_DRAW_IMAGE
:
851 return draw_image(vo
, data
);
852 case VOCTRL_GUISUPPORT
:
854 case VOCTRL_GET_PANSCAN
:
855 if (!vo_config_count
|| !vo_fs
)
858 case VOCTRL_FULLSCREEN
:
860 /* indended, fallthrough to update panscan on fullscreen/windowed switch */
861 case VOCTRL_SET_PANSCAN
:
862 if ((vo_fs
&& (vo_panscan
!= vo_panscan_amount
))
863 || (!vo_fs
&& vo_panscan_amount
))
865 int old_y
= vo_panscan_y
;
869 if (old_y
!= vo_panscan_y
)
871 vo_x11_clearwindow_part(mDisplay
, vo_window
,
872 vo_dwidth
+ vo_panscan_x
- 1,
873 vo_dheight
+ vo_panscan_y
- 1,
875 vo_xv_draw_colorkey(ctx
->drwX
- (vo_panscan_x
>> 1),
876 ctx
->drwY
- (vo_panscan_y
>> 1),
877 vo_dwidth
+ vo_panscan_x
- 1,
878 vo_dheight
+ vo_panscan_y
- 1);
883 case VOCTRL_SET_EQUALIZER
:
885 struct voctrl_set_equalizer_args
*args
= data
;
886 return vo_xv_set_eq(xv_port
, args
->name
, args
->value
);
888 case VOCTRL_GET_EQUALIZER
:
890 struct voctrl_get_equalizer_args
*args
= data
;
891 return vo_xv_get_eq(xv_port
, args
->name
, args
->valueptr
);
896 case VOCTRL_UPDATE_SCREENINFO
:
897 update_xinerama_info();
903 const struct vo_driver video_out_xv
= {
909 .draw_frame
= draw_frame
,
910 .draw_slice
= draw_slice
,
911 .draw_osd
= draw_osd
,
912 .flip_page
= flip_page
,
913 .check_events
= check_events
,