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"
43 #include "Gui/interface.h"
46 static vo_info_t info
= {
49 "Gerd Knorr <kraxel@goldbach.in-berlin.de> and others",
57 #include <X11/extensions/XShm.h>
58 /* since it doesn't seem to be defined on some platforms */
59 int XShmGetEventBase(Display
*);
61 static XShmSegmentInfo Shminfo
[NUM_BUFFERS
];
62 static int Shmem_Flag
;
65 // Note: depends on the inclusion of X11/extensions/XShm.h
66 #include <X11/extensions/Xv.h>
67 #include <X11/extensions/Xvlib.h>
69 // FIXME: dynamically allocate this stuff
70 static void allocate_xvimage(int);
71 static unsigned int ver
, rel
, req
, ev
, err
;
72 static unsigned int formats
, adaptors
, xv_format
;
73 static XvAdaptorInfo
*ai
= NULL
;
74 static XvImageFormatValues
*fo
=NULL
;
76 static int current_buf
= 0;
77 static int current_ip_buf
= 0;
78 static int num_buffers
= 1; // default
79 static int visible_buf
= -1; // -1 means: no buffer was drawn yet
80 static XvImage
*xvimage
[NUM_BUFFERS
];
83 static uint32_t image_width
;
84 static uint32_t image_height
;
85 static uint32_t image_format
;
91 static uint32_t drwX
, drwY
, drwBorderWidth
, drwDepth
;
92 static uint32_t dwidth
, dheight
;
93 static uint32_t max_width
= 0, max_height
= 0; // zero means: not set
95 static void (*draw_alpha_fnc
) (int x0
, int y0
, int w
, int h
,
96 unsigned char *src
, unsigned char *srca
,
99 static void draw_alpha_yv12(int x0
, int y0
, int w
, int h
,
100 unsigned char *src
, unsigned char *srca
,
103 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
104 vo_draw_alpha_yv12(w
, h
, src
, srca
, stride
,
105 xvimage
[current_buf
]->data
+
106 xvimage
[current_buf
]->offsets
[0] +
107 xvimage
[current_buf
]->pitches
[0] * y0
+ x0
,
108 xvimage
[current_buf
]->pitches
[0]);
111 static void draw_alpha_yuy2(int x0
, int y0
, int w
, int h
,
112 unsigned char *src
, unsigned char *srca
,
115 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
116 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
117 xvimage
[current_buf
]->data
+
118 xvimage
[current_buf
]->offsets
[0] +
119 xvimage
[current_buf
]->pitches
[0] * y0
+ 2 * x0
,
120 xvimage
[current_buf
]->pitches
[0]);
123 static void draw_alpha_uyvy(int x0
, int y0
, int w
, int h
,
124 unsigned char *src
, unsigned char *srca
,
127 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
128 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
129 xvimage
[current_buf
]->data
+
130 xvimage
[current_buf
]->offsets
[0] +
131 xvimage
[current_buf
]->pitches
[0] * y0
+ 2 * x0
+ 1,
132 xvimage
[current_buf
]->pitches
[0]);
135 static void draw_alpha_null(int x0
, int y0
, int w
, int h
,
136 unsigned char *src
, unsigned char *srca
,
142 static void deallocate_xvimage(int foo
);
145 * connect to server, create and map window,
146 * allocate colors and (shared) memory
148 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
149 uint32_t d_height
, uint32_t flags
, char *title
,
153 char *hello
= (title
== NULL
) ? "Xv render" : title
;
155 // char *name = ":0.0";
159 XSetWindowAttributes xswa
;
160 XWindowAttributes attribs
;
161 unsigned long xswamask
;
166 unsigned int modeline_width
, modeline_height
;
167 static uint32_t vm_width
;
168 static uint32_t vm_height
;
173 aspect_save_orig(width
, height
);
174 aspect_save_prescale(d_width
, d_height
);
176 image_height
= height
;
178 image_format
= format
;
180 if ((max_width
!= 0 && max_height
!= 0) &&
181 (image_width
> max_width
|| image_height
> max_height
))
183 mp_msg( MSGT_VO
, MSGL_ERR
, "[xv] " MSGTR_VO_XV_ImagedimTooHigh
,
184 image_width
, image_height
, max_width
, max_height
);
188 vo_mouse_autohide
= 1;
193 update_xinerama_info();
194 aspect(&d_width
, &d_height
, A_NOZOOM
);
195 vo_dx
= (vo_screenwidth
- d_width
) / 2;
196 vo_dy
= (vo_screenheight
- d_height
) / 2;
197 geometry(&vo_dx
, &vo_dy
, &d_width
, &d_height
, vo_screenwidth
,
202 vo_dheight
= d_height
;
205 if (flags
& VOFLAG_MODESWITCHING
)
208 flip_flag
= flags
& VOFLAG_FLIPPING
;
210 vo_doublebuffering
? (vo_directrendering
? NUM_BUFFERS
: 2) : 1;
212 /* check image formats */
217 for (i
= 0; i
< formats
; i
++)
219 mp_msg(MSGT_VO
, MSGL_V
,
220 "Xvideo image format: 0x%x (%4.4s) %s\n", fo
[i
].id
,
222 (fo
[i
].format
== XvPacked
) ? "packed" : "planar");
223 if (fo
[i
].id
== format
)
224 xv_format
= fo
[i
].id
;
232 guiGetEvent(guiSetShVideo
, 0); // let the GUI to setup/resize our window
238 hint
.width
= d_width
;
239 hint
.height
= d_height
;
243 if ((d_width
== 0) && (d_height
== 0))
245 vm_width
= image_width
;
246 vm_height
= image_height
;
250 vm_height
= d_height
;
252 vo_vm_switch(vm_width
, vm_height
, &modeline_width
,
254 hint
.x
= (vo_screenwidth
- modeline_width
) / 2;
255 hint
.y
= (vo_screenheight
- modeline_height
) / 2;
256 hint
.width
= modeline_width
;
257 hint
.height
= modeline_height
;
258 aspect_save_screenres(modeline_width
, modeline_height
);
263 #ifdef X11_FULLSCREEN
264 /* this code replaces X11_FULLSCREEN hack in mplayer.c
265 * aspect() is available through aspect.h for all vos.
266 * besides zooming should only be done with -zoom,
267 * but I leave the old -fs behaviour so users don't get
268 * irritated for now (and send lots o' mails ;) ::atmos
271 aspect(&d_width
, &d_height
, A_ZOOM
);
275 // dwidth=d_width; dheight=d_height; //XXX: what are the copy vars used for?
277 vo_dheight
= d_height
;
278 hint
.flags
= PPosition
| PSize
/* | PBaseSize */ ;
279 hint
.base_width
= hint
.width
;
280 hint
.base_height
= hint
.height
;
281 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
),
283 depth
= attribs
.depth
;
284 if (depth
!= 15 && depth
!= 16 && depth
!= 24 && depth
!= 32)
286 XMatchVisualInfo(mDisplay
, mScreen
, depth
, TrueColor
, &vinfo
);
288 xswa
.background_pixel
= 0;
289 if (xv_ck_info
.method
== CK_METHOD_BACKGROUND
)
291 xswa
.background_pixel
= xv_colorkey
;
293 xswa
.border_pixel
= 0;
294 xswamask
= CWBackPixel
| CWBorderPixel
;
298 vo_window
= WinID
? ((Window
) WinID
) : mRootWin
;
301 XUnmapWindow(mDisplay
, vo_window
);
302 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
,
304 vo_x11_selectinput_witherr(mDisplay
, vo_window
,
305 StructureNotifyMask
|
312 XMapWindow(mDisplay
, vo_window
);
313 XGetGeometry(mDisplay
, vo_window
, &mRoot
,
314 &drwX
, &drwY
, &vo_dwidth
, &vo_dheight
,
315 &drwBorderWidth
, &drwDepth
);
316 drwX
= drwY
= 0; // coordinates need to be local to the window
317 aspect_save_prescale(vo_dwidth
, vo_dheight
);
323 } else if (vo_window
== None
)
326 vo_x11_create_smooth_window(mDisplay
, mRootWin
,
327 vinfo
.visual
, hint
.x
, hint
.y
,
328 hint
.width
, hint
.height
, depth
,
330 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
332 vo_x11_classhint(mDisplay
, vo_window
, "xv");
333 vo_hidecursor(mDisplay
, vo_window
);
335 vo_x11_selectinput_witherr(mDisplay
, vo_window
,
336 StructureNotifyMask
| KeyPressMask
|
337 PropertyChangeMask
| ((WinID
== 0) ?
347 XSetStandardProperties(mDisplay
, vo_window
, hello
, hello
, None
,
349 vo_x11_sizehint(hint
.x
, hint
.y
, hint
.width
, hint
.height
, 0);
350 XMapWindow(mDisplay
, vo_window
);
351 if (flags
& VOFLAG_FULLSCREEN
)
355 // vo_fs set means we were already at fullscreen
356 vo_x11_sizehint(hint
.x
, hint
.y
, hint
.width
, hint
.height
, 0);
358 XMoveResizeWindow(mDisplay
, vo_window
, hint
.x
, hint
.y
,
359 hint
.width
, hint
.height
);
360 if (flags
& VOFLAG_FULLSCREEN
&& !vo_fs
)
361 vo_x11_fullscreen(); // handle -fs on non-first file
364 // vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 );
367 XFreeGC(mDisplay
, vo_gc
);
368 vo_gc
= XCreateGC(mDisplay
, vo_window
, 0L, &xgcv
);
369 XSync(mDisplay
, False
);
373 /* Grab the mouse pointer in our window */
375 XGrabPointer(mDisplay
, vo_window
, True
, 0,
376 GrabModeAsync
, GrabModeAsync
,
377 vo_window
, None
, CurrentTime
);
378 XSetInputFocus(mDisplay
, vo_window
, RevertToNone
, CurrentTime
);
383 mp_msg(MSGT_VO
, MSGL_V
, "using Xvideo port %d for hw scaling\n",
391 draw_alpha_fnc
= draw_alpha_yv12
;
395 draw_alpha_fnc
= draw_alpha_yuy2
;
398 draw_alpha_fnc
= draw_alpha_uyvy
;
401 draw_alpha_fnc
= draw_alpha_null
;
405 for (current_buf
= 0; current_buf
< num_buffers
; ++current_buf
)
406 deallocate_xvimage(current_buf
);
408 for (current_buf
= 0; current_buf
< num_buffers
; ++current_buf
)
409 allocate_xvimage(current_buf
);
415 set_gamma_correction();
418 aspect(&vo_dwidth
, &vo_dheight
, A_NOZOOM
);
419 if (((flags
& VOFLAG_FULLSCREEN
) && (WinID
<= 0)) || vo_fs
)
421 aspect(&vo_dwidth
, &vo_dheight
, A_ZOOM
);
425 vo_screenwidth
? vo_screenwidth
: vo_dwidth
)) / 2;
429 vo_screenheight
? vo_screenheight
: vo_dheight
)) / 2;
431 (vo_dwidth
> vo_screenwidth
? vo_screenwidth
: vo_dwidth
);
433 (vo_dheight
> vo_screenheight
? vo_screenheight
: vo_dheight
);
434 mp_msg(MSGT_VO
, MSGL_V
, "[xv-fs] dx: %d dy: %d dw: %d dh: %d\n",
435 drwX
, drwY
, vo_dwidth
, vo_dheight
);
440 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
441 drwY
- (vo_panscan_y
>> 1),
442 vo_dwidth
+ vo_panscan_x
- 1,
443 vo_dheight
+ vo_panscan_y
- 1);
450 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
451 xvimage
[current_buf
], 0, 0, image_width
,
452 image_height
, drwX
, drwY
, 1, 1, False
);
453 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
454 xvimage
[current_buf
], 0, 0, image_width
,
455 image_height
, drwX
, drwY
, vo_dwidth
,
456 (vo_fs
? vo_dheight
- 1 : vo_dheight
), False
);
460 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
461 xvimage
[current_buf
], 0, 0, image_width
, image_height
,
463 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
464 xvimage
[current_buf
], 0, 0, image_width
, image_height
,
465 drwX
, drwY
, vo_dwidth
,
466 (vo_fs
? vo_dheight
- 1 : vo_dheight
));
470 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX
,
471 drwY
, vo_dwidth
, vo_dheight
);
474 vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
479 static void allocate_xvimage(int foo
)
482 * allocate XvImages. FIXME: no error checking, without
483 * mit-shm this will bomb... trzing to fix ::atmos
486 if (mLocalDisplay
&& XShmQueryExtension(mDisplay
))
491 mp_msg(MSGT_VO
, MSGL_INFO
,
492 "Shared memory not supported\nReverting to normal Xv\n");
497 (XvImage
*) XvShmCreateImage(mDisplay
, xv_port
, xv_format
,
498 NULL
, image_width
, image_height
,
502 shmget(IPC_PRIVATE
, xvimage
[foo
]->data_size
, IPC_CREAT
| 0777);
503 Shminfo
[foo
].shmaddr
= (char *) shmat(Shminfo
[foo
].shmid
, 0, 0);
504 Shminfo
[foo
].readOnly
= False
;
506 xvimage
[foo
]->data
= Shminfo
[foo
].shmaddr
;
507 XShmAttach(mDisplay
, &Shminfo
[foo
]);
508 XSync(mDisplay
, False
);
509 shmctl(Shminfo
[foo
].shmid
, IPC_RMID
, 0);
514 (XvImage
*) XvCreateImage(mDisplay
, xv_port
, xv_format
, NULL
,
515 image_width
, image_height
);
516 xvimage
[foo
]->data
= malloc(xvimage
[foo
]->data_size
);
517 XSync(mDisplay
, False
);
519 memset(xvimage
[foo
]->data
, 128, xvimage
[foo
]->data_size
);
523 static void deallocate_xvimage(int foo
)
528 XShmDetach(mDisplay
, &Shminfo
[foo
]);
529 shmdt(Shminfo
[foo
].shmaddr
);
533 free(xvimage
[foo
]->data
);
537 XSync(mDisplay
, False
);
541 static inline void put_xvimage( XvImage
* xvi
)
546 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
547 xvi
, 0, 0, image_width
,
548 image_height
, drwX
- (vo_panscan_x
>> 1),
549 drwY
- (vo_panscan_y
>> 1), vo_dwidth
+ vo_panscan_x
,
550 vo_dheight
+ vo_panscan_y
,
555 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
556 xvi
, 0, 0, image_width
, image_height
,
557 drwX
- (vo_panscan_x
>> 1), drwY
- (vo_panscan_y
>> 1),
558 vo_dwidth
+ vo_panscan_x
,
559 vo_dheight
+ vo_panscan_y
);
563 static void check_events(void)
565 int e
= vo_x11_check_events(mDisplay
);
567 if (e
& VO_EVENT_RESIZE
)
569 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &vo_dwidth
,
570 &vo_dheight
, &drwBorderWidth
, &drwDepth
);
572 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX
,
573 drwY
, vo_dwidth
, vo_dheight
);
575 aspect(&dwidth
, &dheight
, A_NOZOOM
);
578 aspect(&dwidth
, &dheight
, A_ZOOM
);
581 (dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
)) / 2;
585 vo_screenheight
? vo_screenheight
: dheight
)) / 2;
587 (dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
);
589 (dheight
> vo_screenheight
? vo_screenheight
: dheight
);
590 mp_msg(MSGT_VO
, MSGL_V
,
591 "[xv-fs] dx: %d dy: %d dw: %d dh: %d\n", drwX
, drwY
,
592 vo_dwidth
, vo_dheight
);
596 if (e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
)
598 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
599 drwY
- (vo_panscan_y
>> 1),
600 vo_dwidth
+ vo_panscan_x
- 1,
601 vo_dheight
+ vo_panscan_y
- 1);
604 if ((e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
) && int_pause
)
606 /* did we already draw a buffer */
607 if ( visible_buf
!= -1 )
609 /* redraw the last visible buffer */
610 put_xvimage( xvimage
[visible_buf
] );
615 static void draw_osd(void)
617 vo_draw_text(image_width
-
618 image_width
* vo_panscan_x
/ (vo_dwidth
+ vo_panscan_x
),
619 image_height
, draw_alpha_fnc
);
622 static void flip_page(void)
624 put_xvimage( xvimage
[current_buf
] );
626 /* remember the currently visible buffer */
627 visible_buf
= current_buf
;
632 vo_directrendering
? 0 : ((current_buf
+ 1) % num_buffers
);
635 XSync(mDisplay
, False
);
639 static int draw_slice(uint8_t * image
[], int stride
[], int w
, int h
,
644 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[0] +
645 xvimage
[current_buf
]->pitches
[0] * y
+ x
;
646 memcpy_pic(dst
, image
[0], w
, h
, xvimage
[current_buf
]->pitches
[0],
654 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[1] +
655 xvimage
[current_buf
]->pitches
[1] * y
+ x
;
656 if (image_format
!= IMGFMT_YV12
)
657 memcpy_pic(dst
, image
[1], w
, h
, xvimage
[current_buf
]->pitches
[1],
660 memcpy_pic(dst
, image
[2], w
, h
, xvimage
[current_buf
]->pitches
[1],
663 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[2] +
664 xvimage
[current_buf
]->pitches
[2] * y
+ x
;
665 if (image_format
== IMGFMT_YV12
)
666 memcpy_pic(dst
, image
[1], w
, h
, xvimage
[current_buf
]->pitches
[1],
669 memcpy_pic(dst
, image
[2], w
, h
, xvimage
[current_buf
]->pitches
[1],
675 static int draw_frame(uint8_t * src
[])
677 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_XV_DrawFrameCalled
);
681 static uint32_t draw_image(mp_image_t
* mpi
)
683 if (mpi
->flags
& MP_IMGFLAG_DIRECT
)
686 current_buf
= (int) (mpi
->priv
); // hack!
689 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
690 return VO_TRUE
; // done
691 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
693 draw_slice(mpi
->planes
, mpi
->stride
, mpi
->w
, mpi
->h
, 0, 0);
696 if (mpi
->flags
& MP_IMGFLAG_YUV
)
699 memcpy_pic(xvimage
[current_buf
]->data
+
700 xvimage
[current_buf
]->offsets
[0], mpi
->planes
[0],
701 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
702 xvimage
[current_buf
]->pitches
[0], mpi
->stride
[0]);
705 return VO_FALSE
; // not (yet) supported
708 static uint32_t get_image(mp_image_t
* mpi
)
710 int buf
= current_buf
; // we shouldn't change current_buf unless we do DR!
712 if (mpi
->type
== MP_IMGTYPE_STATIC
&& num_buffers
> 1)
713 return VO_FALSE
; // it is not static
714 if (mpi
->imgfmt
!= image_format
)
715 return VO_FALSE
; // needs conversion :(
716 // if(mpi->flags&MP_IMGFLAG_READABLE) return VO_FALSE; // slow video ram
717 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
718 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
))
720 // reference (I/P) frame of IP or IPB:
722 return VO_FALSE
; // not enough
724 // for IPB with 2 buffers we can DR only one of the 2 P frames:
725 if (mpi
->type
== MP_IMGTYPE_IPB
&& num_buffers
< 3
728 buf
= current_ip_buf
;
729 if (mpi
->type
== MP_IMGTYPE_IPB
)
730 ++buf
; // preserve space for B
732 if (mpi
->height
> xvimage
[buf
]->height
)
733 return VO_FALSE
; //buffer to small
734 if (mpi
->width
* (mpi
->bpp
/ 8) > xvimage
[buf
]->pitches
[0])
735 return VO_FALSE
; //buffer to small
736 if ((mpi
->flags
& (MP_IMGFLAG_ACCEPT_STRIDE
| MP_IMGFLAG_ACCEPT_WIDTH
))
737 || (mpi
->width
* (mpi
->bpp
/ 8) == xvimage
[buf
]->pitches
[0]))
741 xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[0];
742 mpi
->stride
[0] = xvimage
[current_buf
]->pitches
[0];
743 mpi
->width
= mpi
->stride
[0] / (mpi
->bpp
/ 8);
744 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
746 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
)
750 xvimage
[current_buf
]->data
+
751 xvimage
[current_buf
]->offsets
[1];
753 xvimage
[current_buf
]->data
+
754 xvimage
[current_buf
]->offsets
[2];
755 mpi
->stride
[1] = xvimage
[current_buf
]->pitches
[1];
756 mpi
->stride
[2] = xvimage
[current_buf
]->pitches
[2];
761 xvimage
[current_buf
]->data
+
762 xvimage
[current_buf
]->offsets
[2];
764 xvimage
[current_buf
]->data
+
765 xvimage
[current_buf
]->offsets
[1];
766 mpi
->stride
[1] = xvimage
[current_buf
]->pitches
[2];
767 mpi
->stride
[2] = xvimage
[current_buf
]->pitches
[1];
770 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
771 mpi
->priv
= (void *) current_buf
;
772 // printf("mga: get_image() SUCCESS -> Direct Rendering ENABLED\n");
778 static int query_format(uint32_t format
)
781 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
783 /* check image formats */
784 for (i
= 0; i
< formats
; i
++)
786 if (fo
[i
].id
== format
)
787 return flag
; //xv_format = fo[i].id;
792 static void uninit(void)
796 if (!vo_config_count
)
799 XvFreeAdaptorInfo(ai
);
805 for (i
= 0; i
< num_buffers
; i
++)
806 deallocate_xvimage(i
);
808 vo_vm_close(mDisplay
);
813 static int preinit(const char *arg
)
818 strarg_t ck_src_arg
= { 0, NULL
};
819 strarg_t ck_method_arg
= { 0, NULL
};
823 /* name arg type arg var test */
824 { "port", OPT_ARG_INT
, &xv_port
, (opt_test_f
)int_pos
},
825 { "ck", OPT_ARG_STR
, &ck_src_arg
, xv_test_ck
},
826 { "ck-method", OPT_ARG_STR
, &ck_method_arg
, xv_test_ckm
},
832 /* parse suboptions */
833 if ( subopt_parse( arg
, subopts
) != 0 )
838 /* modify colorkey settings according to the given options */
839 xv_setup_colorkeyhandling( ck_method_arg
.str
, ck_src_arg
.str
);
844 /* check for Xvideo extension */
845 if (Success
!= XvQueryExtension(mDisplay
, &ver
, &rel
, &req
, &ev
, &err
))
847 mp_msg(MSGT_VO
, MSGL_ERR
,
848 "Sorry, Xv not supported by this X11 version/driver\n");
849 mp_msg(MSGT_VO
, MSGL_ERR
,
850 "******** Try with -vo x11 or -vo sdl *********\n");
854 /* check for Xvideo support */
856 XvQueryAdaptors(mDisplay
, DefaultRootWindow(mDisplay
), &adaptors
,
859 mp_msg(MSGT_VO
, MSGL_ERR
, "Xv: XvQueryAdaptors failed\n");
868 for (port_found
= 0, i
= 0; !port_found
&& i
< adaptors
; i
++)
870 if ((ai
[i
].type
& XvInputMask
) && (ai
[i
].type
& XvImageMask
))
872 for (xv_p
= ai
[i
].base_id
;
873 xv_p
< ai
[i
].base_id
+ ai
[i
].num_ports
; ++xv_p
)
885 if (XvGrabPort(mDisplay
, xv_port
, CurrentTime
))
889 mp_msg(MSGT_VO
, MSGL_WARN
,
890 "Xv: Invalid port parameter, overriding with port 0\n");
895 for (i
= 0; i
< adaptors
&& xv_port
== 0; i
++)
897 if ((ai
[i
].type
& XvInputMask
) && (ai
[i
].type
& XvImageMask
))
899 for (xv_p
= ai
[i
].base_id
;
900 xv_p
< ai
[i
].base_id
+ ai
[i
].num_ports
; ++xv_p
)
901 if (!XvGrabPort(mDisplay
, xv_p
, CurrentTime
))
907 mp_msg(MSGT_VO
, MSGL_WARN
,
908 "Xv: could not grab port %i\n", (int) xv_p
);
916 mp_msg(MSGT_VO
, MSGL_ERR
,
917 "Could not find free Xvideo port - maybe another process is already using it.\n"
918 "Close all video applications, and try again. If that does not help,\n"
919 "see 'mplayer -vo help' for other (non-xv) video out drivers.\n");
921 mp_msg(MSGT_VO
, MSGL_ERR
,
922 "It seems there is no Xvideo support for your video card available.\n"
923 "Run 'xvinfo' to verify its Xv support and read DOCS/HTML/en/video.html#xv!\n"
924 "See 'mplayer -vo help' for other (non-xv) video out drivers. Try -vo x11\n");
928 if ( !vo_xv_init_colorkey() )
930 return -1; // bail out, colorkey setup failed
932 vo_xv_enable_vsync();
933 vo_xv_get_max_img_dim( &max_width
, &max_height
);
935 fo
= XvListImageFormats(mDisplay
, xv_port
, (int *) &formats
);
940 static int control(uint32_t request
, void *data
, ...)
945 return (int_pause
= 1);
947 return (int_pause
= 0);
948 case VOCTRL_QUERY_FORMAT
:
949 return query_format(*((uint32_t *) data
));
950 case VOCTRL_GET_IMAGE
:
951 return get_image(data
);
952 case VOCTRL_DRAW_IMAGE
:
953 return draw_image(data
);
954 case VOCTRL_GUISUPPORT
:
956 case VOCTRL_GET_PANSCAN
:
957 if (!vo_config_count
|| !vo_fs
)
960 case VOCTRL_FULLSCREEN
:
962 /* indended, fallthrough to update panscan on fullscreen/windowed switch */
963 case VOCTRL_SET_PANSCAN
:
964 if ((vo_fs
&& (vo_panscan
!= vo_panscan_amount
))
965 || (!vo_fs
&& vo_panscan_amount
))
967 int old_y
= vo_panscan_y
;
971 if (old_y
!= vo_panscan_y
)
973 vo_x11_clearwindow_part(mDisplay
, vo_window
,
974 vo_dwidth
+ vo_panscan_x
- 1,
975 vo_dheight
+ vo_panscan_y
- 1,
977 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
978 drwY
- (vo_panscan_y
>> 1),
979 vo_dwidth
+ vo_panscan_x
- 1,
980 vo_dheight
+ vo_panscan_y
- 1);
985 case VOCTRL_SET_EQUALIZER
:
991 value
= va_arg(ap
, int);
995 return (vo_xv_set_eq(xv_port
, data
, value
));
997 case VOCTRL_GET_EQUALIZER
:
1003 value
= va_arg(ap
, int *);
1007 return (vo_xv_get_eq(xv_port
, data
, value
));