2009-02-08 04:27:30 +01:00
|
|
|
/*
|
|
|
|
* X11 Xv interface
|
|
|
|
*
|
|
|
|
* This file is part of MPlayer.
|
|
|
|
*
|
|
|
|
* MPlayer is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* MPlayer is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
2001-02-24 21:28:24 +01:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2008-04-04 07:04:11 +02:00
|
|
|
#include <stdint.h>
|
2008-12-01 18:53:57 +01:00
|
|
|
#include <stdbool.h>
|
2012-03-20 00:02:13 +01:00
|
|
|
#include <errno.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
|
|
|
#include <libavutil/common.h>
|
2001-02-24 21:28:24 +01:00
|
|
|
|
|
|
|
#include "config.h"
|
2012-03-20 00:02:13 +01:00
|
|
|
|
|
|
|
#ifdef HAVE_SHM
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
#include <sys/shm.h>
|
|
|
|
#include <X11/extensions/XShm.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Note: depends on the inclusion of X11/extensions/XShm.h
|
|
|
|
#include <X11/extensions/Xv.h>
|
|
|
|
#include <X11/extensions/Xvlib.h>
|
|
|
|
|
2008-04-19 06:45:16 +02:00
|
|
|
#include "options.h"
|
2008-04-20 05:04:10 +02:00
|
|
|
#include "talloc.h"
|
2002-05-02 12:49:55 +02:00
|
|
|
#include "mp_msg.h"
|
2001-02-24 21:28:24 +01:00
|
|
|
#include "video_out.h"
|
2008-04-04 07:04:11 +02:00
|
|
|
#include "libmpcodecs/vfcap.h"
|
|
|
|
#include "libmpcodecs/mp_image.h"
|
|
|
|
#include "osd.h"
|
2001-03-03 22:46:39 +01:00
|
|
|
#include "x11_common.h"
|
2001-04-11 21:41:38 +02:00
|
|
|
#include "fastmemcpy.h"
|
2011-01-26 18:40:52 +01:00
|
|
|
#include "sub/sub.h"
|
2001-10-03 16:53:15 +02:00
|
|
|
#include "aspect.h"
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
#include "csputils.h"
|
2005-02-20 23:43:25 +01:00
|
|
|
#include "subopt-helper.h"
|
|
|
|
|
2007-12-02 15:06:03 +01:00
|
|
|
static const vo_info_t info = {
|
2004-06-14 06:53:03 +02:00
|
|
|
"X11/Xv",
|
|
|
|
"xv",
|
|
|
|
"Gerd Knorr <kraxel@goldbach.in-berlin.de> and others",
|
|
|
|
""
|
2001-02-24 21:28:24 +01:00
|
|
|
};
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx {
|
|
|
|
XvAdaptorInfo *ai;
|
|
|
|
XvImageFormatValues *fo;
|
|
|
|
unsigned int formats, adaptors, xv_format;
|
|
|
|
int current_buf;
|
|
|
|
int current_ip_buf;
|
|
|
|
int num_buffers;
|
2008-12-01 18:53:57 +01:00
|
|
|
int total_buffers;
|
2011-12-05 04:24:18 +01:00
|
|
|
bool have_image_copy;
|
|
|
|
bool unchanged_image;
|
2008-04-04 07:04:11 +02:00
|
|
|
int visible_buf;
|
2012-03-20 00:02:13 +01:00
|
|
|
XvImage *xvimage[2 + 1];
|
2008-04-04 07:04:11 +02:00
|
|
|
uint32_t image_width;
|
|
|
|
uint32_t image_height;
|
|
|
|
uint32_t image_format;
|
2011-10-06 20:46:01 +02:00
|
|
|
uint32_t image_d_width;
|
|
|
|
uint32_t image_d_height;
|
2008-04-04 07:04:11 +02:00
|
|
|
int is_paused;
|
2009-02-13 02:52:51 +01:00
|
|
|
struct vo_rect src_rect;
|
|
|
|
struct vo_rect dst_rect;
|
2008-04-04 07:04:11 +02:00
|
|
|
uint32_t max_width, max_height; // zero means: not set
|
2008-04-04 08:57:58 +02:00
|
|
|
int mode_switched;
|
2008-12-02 00:02:52 +01:00
|
|
|
int osd_objects_drawn;
|
2008-04-04 07:04:11 +02:00
|
|
|
void (*draw_alpha_fnc)(void *ctx, int x0, int y0, int w, int h,
|
|
|
|
unsigned char *src, unsigned char *srca,
|
|
|
|
int stride);
|
|
|
|
#ifdef HAVE_SHM
|
2012-03-20 00:02:13 +01:00
|
|
|
XShmSegmentInfo Shminfo[2 + 1];
|
2008-04-04 07:04:11 +02:00
|
|
|
int Shmem_Flag;
|
|
|
|
#endif
|
|
|
|
};
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void allocate_xvimage(struct vo *, int);
|
2003-09-01 00:27:10 +02:00
|
|
|
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2010-06-02 18:12:01 +02:00
|
|
|
static void fixup_osd_position(struct vo *vo, int *x0, int *y0, int *w, int *h)
|
2010-05-31 23:24:00 +02:00
|
|
|
{
|
2010-06-02 18:12:01 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
*x0 += ctx->image_width * (vo->panscan_x >> 1)
|
|
|
|
/ (vo->dwidth + vo->panscan_x);
|
|
|
|
*w = av_clip(*w, 0, ctx->image_width);
|
|
|
|
*h = av_clip(*h, 0, ctx->image_height);
|
|
|
|
*x0 = FFMIN(*x0, ctx->image_width - *w);
|
|
|
|
*y0 = FFMIN(*y0, ctx->image_height - *h);
|
2010-05-31 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void draw_alpha_yv12(void *p, int x0, int y0, int w, int h,
|
2004-06-14 06:53:03 +02:00
|
|
|
unsigned char *src, unsigned char *srca,
|
|
|
|
int stride)
|
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct vo *vo = p;
|
|
|
|
struct xvctx *ctx = vo->priv;
|
2010-06-02 18:12:01 +02:00
|
|
|
fixup_osd_position(vo, &x0, &y0, &w, &h);
|
2004-06-14 06:53:03 +02:00
|
|
|
vo_draw_alpha_yv12(w, h, src, srca, stride,
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->xvimage[ctx->current_buf]->data +
|
|
|
|
ctx->xvimage[ctx->current_buf]->offsets[0] +
|
|
|
|
ctx->xvimage[ctx->current_buf]->pitches[0] * y0 + x0,
|
|
|
|
ctx->xvimage[ctx->current_buf]->pitches[0]);
|
2008-12-02 00:02:52 +01:00
|
|
|
ctx->osd_objects_drawn++;
|
2001-08-23 13:04:23 +02:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void draw_alpha_yuy2(void *p, int x0, int y0, int w, int h,
|
2004-06-14 06:53:03 +02:00
|
|
|
unsigned char *src, unsigned char *srca,
|
|
|
|
int stride)
|
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct vo *vo = p;
|
|
|
|
struct xvctx *ctx = vo->priv;
|
2010-06-02 18:12:01 +02:00
|
|
|
fixup_osd_position(vo, &x0, &y0, &w, &h);
|
2004-06-14 06:53:03 +02:00
|
|
|
vo_draw_alpha_yuy2(w, h, src, srca, stride,
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->xvimage[ctx->current_buf]->data +
|
|
|
|
ctx->xvimage[ctx->current_buf]->offsets[0] +
|
|
|
|
ctx->xvimage[ctx->current_buf]->pitches[0] * y0 + 2 * x0,
|
|
|
|
ctx->xvimage[ctx->current_buf]->pitches[0]);
|
2008-12-02 00:02:52 +01:00
|
|
|
ctx->osd_objects_drawn++;
|
2001-08-23 13:04:23 +02:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void draw_alpha_uyvy(void *p, int x0, int y0, int w, int h,
|
2004-06-14 06:53:03 +02:00
|
|
|
unsigned char *src, unsigned char *srca,
|
|
|
|
int stride)
|
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct vo *vo = p;
|
|
|
|
struct xvctx *ctx = vo->priv;
|
2010-06-02 18:12:01 +02:00
|
|
|
fixup_osd_position(vo, &x0, &y0, &w, &h);
|
2004-06-14 06:53:03 +02:00
|
|
|
vo_draw_alpha_yuy2(w, h, src, srca, stride,
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->xvimage[ctx->current_buf]->data +
|
|
|
|
ctx->xvimage[ctx->current_buf]->offsets[0] +
|
|
|
|
ctx->xvimage[ctx->current_buf]->pitches[0] * y0 + 2 * x0 + 1,
|
|
|
|
ctx->xvimage[ctx->current_buf]->pitches[0]);
|
2008-12-02 00:02:52 +01:00
|
|
|
ctx->osd_objects_drawn++;
|
2001-08-23 13:04:23 +02:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void draw_alpha_null(void *p, int x0, int y0, int w, int h,
|
2004-06-14 06:53:03 +02:00
|
|
|
unsigned char *src, unsigned char *srca,
|
|
|
|
int stride)
|
|
|
|
{
|
2001-08-23 13:04:23 +02:00
|
|
|
}
|
|
|
|
|
2002-07-25 15:12:23 +02:00
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void deallocate_xvimage(struct vo *vo, int foo);
|
2002-10-16 21:31:07 +02:00
|
|
|
|
2009-02-13 02:52:51 +01:00
|
|
|
static void resize(struct vo *vo)
|
2009-02-12 18:40:53 +01:00
|
|
|
{
|
2009-02-13 02:52:51 +01:00
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
|
|
|
|
calc_src_dst_rects(vo, ctx->image_width, ctx->image_height, &ctx->src_rect,
|
2009-02-18 00:07:37 +01:00
|
|
|
&ctx->dst_rect, NULL, NULL);
|
2009-02-13 02:52:51 +01:00
|
|
|
struct vo_rect *dst = &ctx->dst_rect;
|
2011-07-06 07:24:20 +02:00
|
|
|
vo_x11_clearwindow_part(vo, vo->x11->window, dst->width, dst->height);
|
2009-02-13 02:52:51 +01:00
|
|
|
vo_xv_draw_colorkey(vo, dst->left, dst->top, dst->width, dst->height);
|
2009-02-12 18:40:53 +01:00
|
|
|
}
|
|
|
|
|
2001-03-21 20:10:55 +01:00
|
|
|
/*
|
|
|
|
* connect to server, create and map window,
|
2001-02-24 21:28:24 +01:00
|
|
|
* allocate colors and (shared) memory
|
|
|
|
*/
|
2008-04-04 07:04:11 +02:00
|
|
|
static int config(struct vo *vo, uint32_t width, uint32_t height,
|
|
|
|
uint32_t d_width, uint32_t d_height, uint32_t flags,
|
2011-12-06 20:23:54 +01:00
|
|
|
uint32_t format)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2008-04-20 08:34:27 +02:00
|
|
|
struct vo_x11_state *x11 = vo->x11;
|
2004-06-14 06:53:03 +02:00
|
|
|
XVisualInfo vinfo;
|
|
|
|
XSetWindowAttributes xswa;
|
|
|
|
XWindowAttributes attribs;
|
|
|
|
unsigned long xswamask;
|
|
|
|
int depth;
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
int i;
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->image_height = height;
|
|
|
|
ctx->image_width = width;
|
|
|
|
ctx->image_format = format;
|
2011-10-06 20:46:01 +02:00
|
|
|
ctx->image_d_width = d_width;
|
|
|
|
ctx->image_d_height = d_height;
|
2001-10-18 04:42:20 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
if ((ctx->max_width != 0 && ctx->max_height != 0)
|
|
|
|
&& (ctx->image_width > ctx->max_width
|
|
|
|
|| ctx->image_height > ctx->max_height)) {
|
2009-07-07 00:15:02 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_ERR, "Source image dimensions are too high: %ux%u (maximum is %ux%u)\n",
|
2008-12-01 15:15:17 +01:00
|
|
|
ctx->image_width, ctx->image_height, ctx->max_width,
|
|
|
|
ctx->max_height);
|
2005-11-10 03:39:31 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->visible_buf = -1;
|
2011-12-05 04:24:18 +01:00
|
|
|
ctx->have_image_copy = false;
|
2004-06-14 06:53:03 +02:00
|
|
|
|
|
|
|
/* check image formats */
|
2008-04-04 07:42:51 +02:00
|
|
|
ctx->xv_format = 0;
|
|
|
|
for (i = 0; i < ctx->formats; i++) {
|
2008-12-01 15:15:17 +01:00
|
|
|
mp_msg(MSGT_VO, MSGL_V, "Xvideo image format: 0x%x (%4.4s) %s\n",
|
|
|
|
ctx->fo[i].id, (char *) &ctx->fo[i].id,
|
2008-04-04 07:42:51 +02:00
|
|
|
(ctx->fo[i].format == XvPacked) ? "packed" : "planar");
|
|
|
|
if (ctx->fo[i].id == format)
|
|
|
|
ctx->xv_format = ctx->fo[i].id;
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
2008-04-04 07:42:51 +02:00
|
|
|
if (!ctx->xv_format)
|
|
|
|
return -1;
|
2001-10-18 04:42:20 +02:00
|
|
|
|
2001-05-08 14:17:03 +02:00
|
|
|
{
|
2008-08-04 08:16:23 +02:00
|
|
|
#ifdef CONFIG_XF86VM
|
2008-04-04 07:47:12 +02:00
|
|
|
int vm = flags & VOFLAG_MODESWITCHING;
|
2008-12-01 15:15:17 +01:00
|
|
|
if (vm) {
|
2008-11-17 19:50:23 +01:00
|
|
|
vo_vm_switch(vo);
|
2008-04-04 08:57:58 +02:00
|
|
|
ctx->mode_switched = 1;
|
2008-11-15 20:14:09 +01:00
|
|
|
}
|
2004-06-14 06:53:03 +02:00
|
|
|
#endif
|
2008-04-20 08:34:27 +02:00
|
|
|
XGetWindowAttributes(x11->display, DefaultRootWindow(x11->display),
|
2004-06-14 06:53:03 +02:00
|
|
|
&attribs);
|
|
|
|
depth = attribs.depth;
|
|
|
|
if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
|
|
|
|
depth = 24;
|
2008-04-21 03:59:00 +02:00
|
|
|
XMatchVisualInfo(x11->display, x11->screen, depth, TrueColor, &vinfo);
|
2004-06-14 06:53:03 +02:00
|
|
|
|
|
|
|
xswa.border_pixel = 0;
|
2011-05-30 00:46:52 +02:00
|
|
|
xswamask = CWBorderPixel;
|
|
|
|
if (x11->xv_ck_info.method == CK_METHOD_BACKGROUND) {
|
|
|
|
xswa.background_pixel = x11->xv_colorkey;
|
|
|
|
xswamask |= CWBackPixel;
|
|
|
|
}
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
vo_x11_create_vo_window(vo, &vinfo, vo->dx, vo->dy, vo->dwidth,
|
2011-12-06 20:23:54 +01:00
|
|
|
vo->dheight, flags, CopyFromParent, "xv");
|
2008-12-01 15:15:17 +01:00
|
|
|
XChangeWindowAttributes(x11->display, x11->window, xswamask, &xswa);
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-08-04 08:16:23 +02:00
|
|
|
#ifdef CONFIG_XF86VM
|
2008-12-01 15:15:17 +01:00
|
|
|
if (vm) {
|
2004-06-14 06:53:03 +02:00
|
|
|
/* Grab the mouse pointer in our window */
|
|
|
|
if (vo_grabpointer)
|
2008-12-01 15:15:17 +01:00
|
|
|
XGrabPointer(x11->display, x11->window, True, 0, GrabModeAsync,
|
|
|
|
GrabModeAsync, x11->window, None, CurrentTime);
|
|
|
|
XSetInputFocus(x11->display, x11->window, RevertToNone,
|
|
|
|
CurrentTime);
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
2002-01-31 01:37:59 +01:00
|
|
|
#endif
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
mp_msg(MSGT_VO, MSGL_V, "using Xvideo port %d for hw scaling\n",
|
2008-04-21 02:43:03 +02:00
|
|
|
x11->xv_port);
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
switch (ctx->xv_format) {
|
|
|
|
case IMGFMT_YV12:
|
|
|
|
case IMGFMT_I420:
|
|
|
|
case IMGFMT_IYUV:
|
|
|
|
ctx->draw_alpha_fnc = draw_alpha_yv12;
|
|
|
|
break;
|
|
|
|
case IMGFMT_YUY2:
|
|
|
|
case IMGFMT_YVYU:
|
|
|
|
ctx->draw_alpha_fnc = draw_alpha_yuy2;
|
|
|
|
break;
|
|
|
|
case IMGFMT_UYVY:
|
|
|
|
ctx->draw_alpha_fnc = draw_alpha_uyvy;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ctx->draw_alpha_fnc = draw_alpha_null;
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
|
|
|
|
2008-04-04 08:09:14 +02:00
|
|
|
// In case config has been called before
|
2008-12-01 18:53:57 +01:00
|
|
|
for (i = 0; i < ctx->total_buffers; i++)
|
2008-04-04 08:09:14 +02:00
|
|
|
deallocate_xvimage(vo, i);
|
|
|
|
|
2012-03-20 00:02:13 +01:00
|
|
|
ctx->num_buffers = 2;
|
2008-12-01 18:53:57 +01:00
|
|
|
ctx->total_buffers = ctx->num_buffers + 1;
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-12-01 18:53:57 +01:00
|
|
|
for (i = 0; i < ctx->total_buffers; i++)
|
2008-04-04 07:04:11 +02:00
|
|
|
allocate_xvimage(vo, i);
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->current_buf = 0;
|
|
|
|
ctx->current_ip_buf = 0;
|
2001-03-21 20:10:55 +01:00
|
|
|
|
2002-06-10 20:40:19 +02:00
|
|
|
|
2009-02-13 02:52:51 +01:00
|
|
|
resize(vo);
|
2003-11-30 17:36:10 +01:00
|
|
|
|
2004-06-14 06:53:03 +02:00
|
|
|
return 0;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void allocate_xvimage(struct vo *vo, int foo)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
2008-04-20 08:34:27 +02:00
|
|
|
struct vo_x11_state *x11 = vo->x11;
|
2004-06-14 06:53:03 +02:00
|
|
|
/*
|
|
|
|
* allocate XvImages. FIXME: no error checking, without
|
|
|
|
* mit-shm this will bomb... trzing to fix ::atmos
|
|
|
|
*/
|
2002-06-13 16:23:03 +02:00
|
|
|
#ifdef HAVE_SHM
|
2008-04-21 03:59:00 +02:00
|
|
|
if (x11->display_is_local && XShmQueryExtension(x11->display))
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->Shmem_Flag = 1;
|
2008-12-01 15:15:17 +01:00
|
|
|
else {
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->Shmem_Flag = 0;
|
2009-07-07 00:15:02 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_INFO, "[VO_XV] Shared memory not supported\nReverting to normal Xv.\n");
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
2008-12-01 15:15:17 +01:00
|
|
|
if (ctx->Shmem_Flag) {
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->xvimage[foo] =
|
2008-12-01 15:15:17 +01:00
|
|
|
(XvImage *) XvShmCreateImage(x11->display, x11->xv_port,
|
|
|
|
ctx->xv_format, NULL,
|
|
|
|
ctx->image_width, ctx->image_height,
|
2008-04-04 07:04:11 +02:00
|
|
|
&ctx->Shminfo[foo]);
|
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
ctx->Shminfo[foo].shmid = shmget(IPC_PRIVATE,
|
|
|
|
ctx->xvimage[foo]->data_size,
|
|
|
|
IPC_CREAT | 0777);
|
|
|
|
ctx->Shminfo[foo].shmaddr = (char *) shmat(ctx->Shminfo[foo].shmid, 0,
|
|
|
|
0);
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->Shminfo[foo].readOnly = False;
|
|
|
|
|
|
|
|
ctx->xvimage[foo]->data = ctx->Shminfo[foo].shmaddr;
|
2008-04-20 08:34:27 +02:00
|
|
|
XShmAttach(x11->display, &ctx->Shminfo[foo]);
|
|
|
|
XSync(x11->display, False);
|
2008-04-04 07:04:11 +02:00
|
|
|
shmctl(ctx->Shminfo[foo].shmid, IPC_RMID, 0);
|
2004-06-14 06:53:03 +02:00
|
|
|
} else
|
2002-06-13 16:23:03 +02:00
|
|
|
#endif
|
2004-06-14 06:53:03 +02:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->xvimage[foo] =
|
2008-12-01 15:15:17 +01:00
|
|
|
(XvImage *) XvCreateImage(x11->display, x11->xv_port,
|
|
|
|
ctx->xv_format, NULL, ctx->image_width,
|
|
|
|
ctx->image_height);
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->xvimage[foo]->data = malloc(ctx->xvimage[foo]->data_size);
|
2008-04-20 08:34:27 +02:00
|
|
|
XSync(x11->display, False);
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
2008-04-04 07:04:11 +02:00
|
|
|
memset(ctx->xvimage[foo]->data, 128, ctx->xvimage[foo]->data_size);
|
2004-06-14 06:53:03 +02:00
|
|
|
return;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void deallocate_xvimage(struct vo *vo, int foo)
|
2001-08-31 12:06:32 +02:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
2002-06-13 16:23:03 +02:00
|
|
|
#ifdef HAVE_SHM
|
2008-12-01 15:15:17 +01:00
|
|
|
if (ctx->Shmem_Flag) {
|
2008-04-20 08:34:27 +02:00
|
|
|
XShmDetach(vo->x11->display, &ctx->Shminfo[foo]);
|
2008-04-04 07:04:11 +02:00
|
|
|
shmdt(ctx->Shminfo[foo].shmaddr);
|
2004-06-14 06:53:03 +02:00
|
|
|
} else
|
2002-06-13 16:23:03 +02:00
|
|
|
#endif
|
2004-06-14 06:53:03 +02:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
free(ctx->xvimage[foo]->data);
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
2008-04-04 07:04:11 +02:00
|
|
|
XFree(ctx->xvimage[foo]);
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-04-20 08:34:27 +02:00
|
|
|
XSync(vo->x11->display, False);
|
2004-06-14 06:53:03 +02:00
|
|
|
return;
|
2001-08-31 12:06:32 +02:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static inline void put_xvimage(struct vo *vo, XvImage *xvi)
|
2005-02-23 13:23:44 +01:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
2008-04-20 08:34:27 +02:00
|
|
|
struct vo_x11_state *x11 = vo->x11;
|
2009-02-13 02:52:51 +01:00
|
|
|
struct vo_rect *src = &ctx->src_rect;
|
|
|
|
struct vo_rect *dst = &ctx->dst_rect;
|
2005-02-23 13:23:44 +01:00
|
|
|
#ifdef HAVE_SHM
|
2008-12-01 15:15:17 +01:00
|
|
|
if (ctx->Shmem_Flag) {
|
|
|
|
XvShmPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi,
|
2009-02-13 02:52:51 +01:00
|
|
|
src->left, src->top, src->width, src->height,
|
|
|
|
dst->left, dst->top, dst->width, dst->height,
|
2005-02-23 13:23:44 +01:00
|
|
|
False);
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2009-02-13 02:52:51 +01:00
|
|
|
XvPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi,
|
|
|
|
src->left, src->top, src->width, src->height,
|
|
|
|
dst->left, dst->top, dst->width, dst->height);
|
2005-02-23 13:23:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-01 18:53:57 +01:00
|
|
|
// Only copies luma for planar formats as draw_alpha doesn't change others */
|
2009-10-22 03:21:14 +02:00
|
|
|
static void copy_backup_image(struct vo *vo, int dest, int src)
|
2008-12-01 18:53:57 +01:00
|
|
|
{
|
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
|
|
|
|
XvImage *vb = ctx->xvimage[dest];
|
|
|
|
XvImage *cp = ctx->xvimage[src];
|
|
|
|
memcpy_pic(vb->data + vb->offsets[0], cp->data + cp->offsets[0],
|
|
|
|
vb->width, vb->height,
|
|
|
|
vb->pitches[0], cp->pitches[0]);
|
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void check_events(struct vo *vo)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2008-04-20 08:34:27 +02:00
|
|
|
int e = vo_x11_check_events(vo);
|
2003-09-01 00:27:10 +02:00
|
|
|
|
2011-12-05 05:36:20 +01:00
|
|
|
if (e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) {
|
2009-02-13 02:52:51 +01:00
|
|
|
resize(vo);
|
2011-12-05 05:36:20 +01:00
|
|
|
vo->want_redraw = true;
|
2005-02-23 13:23:44 +01:00
|
|
|
}
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2008-06-24 00:53:58 +02:00
|
|
|
static void draw_osd(struct vo *vo, struct osd_state *osd)
|
2004-06-14 06:53:03 +02:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
|
2008-12-02 00:02:52 +01:00
|
|
|
ctx->osd_objects_drawn = 0;
|
2008-12-01 15:15:17 +01:00
|
|
|
osd_draw_text(osd,
|
|
|
|
ctx->image_width -
|
|
|
|
ctx->image_width * vo->panscan_x / (vo->dwidth +
|
|
|
|
vo->panscan_x),
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->image_height, ctx->draw_alpha_fnc, vo);
|
2008-12-02 00:02:52 +01:00
|
|
|
if (ctx->osd_objects_drawn)
|
2011-12-05 04:24:18 +01:00
|
|
|
ctx->unchanged_image = false;
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
2001-08-13 13:08:18 +02:00
|
|
|
|
2011-12-05 04:24:18 +01:00
|
|
|
static int redraw_frame(struct vo *vo)
|
2008-12-01 18:53:57 +01:00
|
|
|
{
|
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
|
2011-12-05 04:24:18 +01:00
|
|
|
if (ctx->have_image_copy)
|
2008-12-02 00:02:52 +01:00
|
|
|
copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers);
|
2011-12-05 04:24:18 +01:00
|
|
|
else if (ctx->unchanged_image) {
|
2008-12-02 00:02:52 +01:00
|
|
|
copy_backup_image(vo, ctx->num_buffers, ctx->visible_buf);
|
2011-12-05 04:24:18 +01:00
|
|
|
ctx->have_image_copy = true;
|
|
|
|
} else
|
2008-12-01 18:53:57 +01:00
|
|
|
return false;
|
|
|
|
ctx->current_buf = ctx->visible_buf;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void flip_page(struct vo *vo)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
put_xvimage(vo, ctx->xvimage[ctx->current_buf]);
|
2005-02-23 13:23:44 +01:00
|
|
|
|
|
|
|
/* remember the currently visible buffer */
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->visible_buf = ctx->current_buf;
|
2002-06-04 22:17:07 +02:00
|
|
|
|
2012-03-20 00:02:13 +01:00
|
|
|
ctx->current_buf = (ctx->current_buf + 1) % ctx->num_buffers;
|
|
|
|
XFlush(vo->x11->display);
|
2004-06-14 06:53:03 +02:00
|
|
|
return;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w,
|
2008-04-04 07:04:11 +02:00
|
|
|
int h, int x, int y)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
2004-06-14 06:53:03 +02:00
|
|
|
uint8_t *dst;
|
2008-04-04 07:04:11 +02:00
|
|
|
XvImage *current_image = ctx->xvimage[ctx->current_buf];
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
dst = current_image->data + current_image->offsets[0]
|
|
|
|
+ current_image->pitches[0] * y + x;
|
|
|
|
memcpy_pic(dst, image[0], w, h, current_image->pitches[0], stride[0]);
|
2004-06-14 06:53:03 +02:00
|
|
|
|
|
|
|
x /= 2;
|
|
|
|
y /= 2;
|
|
|
|
w /= 2;
|
|
|
|
h /= 2;
|
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
dst = current_image->data + current_image->offsets[1]
|
|
|
|
+ current_image->pitches[1] * y + x;
|
2008-04-04 07:04:11 +02:00
|
|
|
if (ctx->image_format != IMGFMT_YV12)
|
2008-12-01 15:15:17 +01:00
|
|
|
memcpy_pic(dst, image[1], w, h, current_image->pitches[1], stride[1]);
|
2004-06-14 06:53:03 +02:00
|
|
|
else
|
2008-12-01 15:15:17 +01:00
|
|
|
memcpy_pic(dst, image[2], w, h, current_image->pitches[1], stride[2]);
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
dst = current_image->data + current_image->offsets[2]
|
|
|
|
+ current_image->pitches[2] * y + x;
|
2008-04-04 07:04:11 +02:00
|
|
|
if (ctx->image_format == IMGFMT_YV12)
|
2008-12-01 15:15:17 +01:00
|
|
|
memcpy_pic(dst, image[1], w, h, current_image->pitches[1], stride[1]);
|
2004-06-14 06:53:03 +02:00
|
|
|
else
|
2008-12-01 15:15:17 +01:00
|
|
|
memcpy_pic(dst, image[2], w, h, current_image->pitches[1], stride[2]);
|
2002-05-30 02:08:47 +02:00
|
|
|
|
2004-06-14 06:53:03 +02:00
|
|
|
return 0;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2011-12-05 04:24:18 +01:00
|
|
|
static mp_image_t *get_screenshot(struct vo *vo)
|
|
|
|
{
|
2011-10-06 20:46:01 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
|
|
|
|
|
|
|
// try to get an image without OSD
|
2011-12-05 04:24:18 +01:00
|
|
|
if (ctx->have_image_copy)
|
2011-10-06 20:46:01 +02:00
|
|
|
copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers);
|
|
|
|
|
|
|
|
XvImage *xv_image = ctx->xvimage[ctx->visible_buf];
|
|
|
|
|
|
|
|
int w = xv_image->width;
|
|
|
|
int h = xv_image->height;
|
|
|
|
|
|
|
|
mp_image_t *image = alloc_mpi(w, h, ctx->image_format);
|
|
|
|
|
|
|
|
int bytes = 1;
|
|
|
|
if (!(image->flags & MP_IMGFLAG_PLANAR) && (image->flags & MP_IMGFLAG_YUV))
|
|
|
|
// packed YUV
|
|
|
|
bytes = image->bpp / 8;
|
|
|
|
|
|
|
|
memcpy_pic(image->planes[0], xv_image->data + xv_image->offsets[0],
|
|
|
|
bytes * w, h, image->stride[0], xv_image->pitches[0]);
|
|
|
|
|
|
|
|
if (image->flags & MP_IMGFLAG_PLANAR) {
|
|
|
|
int swap = ctx->image_format == IMGFMT_YV12;
|
|
|
|
int p1 = swap ? 2 : 1;
|
|
|
|
int p2 = swap ? 1 : 2;
|
|
|
|
|
|
|
|
w /= 2;
|
|
|
|
h /= 2;
|
|
|
|
|
|
|
|
memcpy_pic(image->planes[p1], xv_image->data + xv_image->offsets[1],
|
|
|
|
w, h, image->stride[p1], xv_image->pitches[1]);
|
|
|
|
memcpy_pic(image->planes[p2], xv_image->data + xv_image->offsets[2],
|
|
|
|
w, h, image->stride[p2], xv_image->pitches[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
image->w = ctx->image_d_width;
|
|
|
|
image->h = ctx->image_d_height;
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
|
2004-06-14 06:53:03 +02:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
2008-12-01 18:53:57 +01:00
|
|
|
|
2011-12-05 04:24:18 +01:00
|
|
|
ctx->have_image_copy = false;
|
2008-12-01 18:53:57 +01:00
|
|
|
|
2012-03-20 00:02:13 +01:00
|
|
|
if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
|
2008-12-01 18:53:57 +01:00
|
|
|
; // done
|
|
|
|
else if (mpi->flags & MP_IMGFLAG_PLANAR)
|
2008-04-04 07:04:11 +02:00
|
|
|
draw_slice(vo, mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
|
2008-12-01 18:53:57 +01:00
|
|
|
else if (mpi->flags & MP_IMGFLAG_YUV)
|
2004-06-14 06:53:03 +02:00
|
|
|
// packed YUV:
|
2008-04-04 07:04:11 +02:00
|
|
|
memcpy_pic(ctx->xvimage[ctx->current_buf]->data +
|
|
|
|
ctx->xvimage[ctx->current_buf]->offsets[0], mpi->planes[0],
|
2004-06-14 06:53:03 +02:00
|
|
|
mpi->w * (mpi->bpp / 8), mpi->h,
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->xvimage[ctx->current_buf]->pitches[0], mpi->stride[0]);
|
2008-12-01 18:53:57 +01:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ctx->is_paused) {
|
|
|
|
copy_backup_image(vo, ctx->num_buffers, ctx->current_buf);
|
2011-12-05 04:24:18 +01:00
|
|
|
ctx->have_image_copy = true;
|
2002-10-09 23:26:16 +02:00
|
|
|
}
|
2011-12-05 04:24:18 +01:00
|
|
|
ctx->unchanged_image = true;
|
2008-12-01 18:53:57 +01:00
|
|
|
return true;
|
2002-07-20 18:27:17 +02:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static int query_format(struct xvctx *ctx, uint32_t format)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2003-09-12 17:50:35 +02:00
|
|
|
uint32_t i;
|
2004-06-14 06:53:03 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
/* check image formats */
|
2008-12-01 15:15:17 +01:00
|
|
|
for (i = 0; i < ctx->formats; i++) {
|
2008-04-04 07:04:11 +02:00
|
|
|
if (ctx->fo[i].id == format)
|
2004-06-14 06:53:03 +02:00
|
|
|
return flag; //xv_format = fo[i].id;
|
|
|
|
}
|
|
|
|
return 0;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static void uninit(struct vo *vo)
|
2001-09-04 17:21:00 +02:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
2004-06-14 06:53:03 +02:00
|
|
|
int i;
|
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->visible_buf = -1;
|
2008-04-04 08:57:58 +02:00
|
|
|
if (ctx->ai)
|
|
|
|
XvFreeAdaptorInfo(ctx->ai);
|
2008-04-04 07:04:11 +02:00
|
|
|
ctx->ai = NULL;
|
|
|
|
if (ctx->fo) {
|
|
|
|
XFree(ctx->fo);
|
|
|
|
ctx->fo = NULL;
|
2004-11-15 15:56:18 +01:00
|
|
|
}
|
2008-12-01 18:53:57 +01:00
|
|
|
for (i = 0; i < ctx->total_buffers; i++)
|
2008-04-04 07:04:11 +02:00
|
|
|
deallocate_xvimage(vo, i);
|
2008-08-04 08:16:23 +02:00
|
|
|
#ifdef CONFIG_XF86VM
|
2008-04-04 08:57:58 +02:00
|
|
|
if (ctx->mode_switched)
|
2008-04-21 01:18:28 +02:00
|
|
|
vo_vm_close(vo);
|
2002-05-08 22:24:35 +02:00
|
|
|
#endif
|
2008-04-04 08:57:58 +02:00
|
|
|
// uninit() shouldn't get called unless initialization went past vo_init()
|
2008-04-20 08:34:27 +02:00
|
|
|
vo_x11_uninit(vo);
|
2001-04-10 00:27:27 +02:00
|
|
|
}
|
2001-03-21 20:10:55 +01:00
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static int preinit(struct vo *vo, const char *arg)
|
2002-01-26 17:01:26 +01:00
|
|
|
{
|
2002-04-07 04:10:39 +02:00
|
|
|
XvPortID xv_p;
|
2004-06-14 06:53:03 +02:00
|
|
|
int busy_ports = 0;
|
2003-09-12 17:50:35 +02:00
|
|
|
unsigned int i;
|
2005-02-20 23:43:25 +01:00
|
|
|
strarg_t ck_src_arg = { 0, NULL };
|
|
|
|
strarg_t ck_method_arg = { 0, NULL };
|
2008-04-20 05:04:10 +02:00
|
|
|
struct xvctx *ctx = talloc_zero(vo, struct xvctx);
|
2008-04-04 07:04:11 +02:00
|
|
|
vo->priv = ctx;
|
2008-05-13 19:52:25 +02:00
|
|
|
int xv_adaptor = -1;
|
2005-02-20 23:43:25 +01:00
|
|
|
|
2012-08-03 05:55:02 +02:00
|
|
|
if (!vo_init(vo))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
struct vo_x11_state *x11 = vo->x11;
|
|
|
|
|
2009-03-07 09:51:40 +01:00
|
|
|
const opt_t subopts[] =
|
2009-05-13 04:58:57 +02:00
|
|
|
{
|
2005-02-20 23:43:25 +01:00
|
|
|
/* name arg type arg var test */
|
2010-01-08 00:05:30 +01:00
|
|
|
{ "port", OPT_ARG_INT, &x11->xv_port, int_pos },
|
2010-01-01 14:18:49 +01:00
|
|
|
{ "adaptor", OPT_ARG_INT, &xv_adaptor, int_non_neg },
|
2005-02-20 23:43:25 +01:00
|
|
|
{ "ck", OPT_ARG_STR, &ck_src_arg, xv_test_ck },
|
|
|
|
{ "ck-method", OPT_ARG_STR, &ck_method_arg, xv_test_ckm },
|
|
|
|
{ NULL }
|
|
|
|
};
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-04-21 02:43:03 +02:00
|
|
|
x11->xv_port = 0;
|
2003-09-06 15:40:00 +02:00
|
|
|
|
2005-02-20 23:43:25 +01:00
|
|
|
/* parse suboptions */
|
2008-12-01 15:15:17 +01:00
|
|
|
if (subopt_parse(arg, subopts) != 0) {
|
|
|
|
return -1;
|
2002-02-17 09:24:43 +01:00
|
|
|
}
|
2005-02-20 23:43:25 +01:00
|
|
|
|
|
|
|
/* modify colorkey settings according to the given options */
|
2008-04-21 02:43:03 +02:00
|
|
|
xv_setup_colorkeyhandling(vo, ck_method_arg.str, ck_src_arg.str);
|
2005-02-20 23:43:25 +01:00
|
|
|
|
2004-06-14 06:53:03 +02:00
|
|
|
/* check for Xvideo extension */
|
2008-04-04 07:04:11 +02:00
|
|
|
unsigned int ver, rel, req, ev, err;
|
2008-12-01 15:15:17 +01:00
|
|
|
if (Success != XvQueryExtension(x11->display, &ver, &rel, &req, &ev, &err)) {
|
libvo, libao: remove useless video and audio output drivers
Some of these have only limited use, and some of these have no use at
all. Remove them. They make maintainance harder and nobody needs them.
It's possible that many of the removed drivers were very useful a dozen
of years ago, but now it's 2012.
Note that some of these could be added back, in case they were more
useful than I thought. But right now, they are just a burden.
Reason for removal for each module:
vo_3dfx, vo_dfbmga, vo_dxr3, vo_ivtv, vo_mga, vo_s3fb,
vo_tdfxfb, vo_xmga, vo_tdfx_vid:
All of these are for very specific and outdated hardware. Some
of them require non-standard kernel drivers or do direct HW
access.
vo_dga: the most crappy and ancient way to get fast output on X.
vo_aa: there's vo_caca for the same purpose.
vo_ggi: this never lived, and is entirely useless.
vo_mpegpes: for DVB cards, I can't test this and it's crappy.
vo_fbdev, vo_fbdev2: there's vo_directfb2
vo_bl: what is this even? But it's neither important, nor alive.
vo_svga, vo_vesa: you want to use this? You can't be serious.
vo_wii: I can't test this, and who the hell uses this?
vo_xvr100: some Sun thing.
vo_xover: only useful in connection with xvr100.
ao_nas: still alive, but I doubt it has any meaning today.
ao_sun: Sun.
ao_win32: use ao_dsound or ao_portaudio instead.
ao_ivtv: removed along vo_ivtv.
Also get rid of anything SDL related. SDL 1.x is total crap for video
output, and will be replaced with SDL 2.x soon (perhaps), so if you
want to use SDL, write output drivers for SDL 2.x.
Additionally, I accidentally damaged Sun support, which made me
completely remove Sun/Solaris support. Nobody cares about this anyway.
Some left overs from previous commits removing modules were cleaned up.
2012-07-28 20:20:17 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_ERR, "[VO_XV] Sorry, Xv not supported by this X11 version/driver\n[VO_XV] ******** Try with -vo x11 *********\n");
|
2008-04-04 08:57:58 +02:00
|
|
|
goto error;
|
2002-04-07 04:10:39 +02:00
|
|
|
}
|
2004-06-14 06:53:03 +02:00
|
|
|
|
|
|
|
/* check for Xvideo support */
|
|
|
|
if (Success !=
|
2008-12-01 15:15:17 +01:00
|
|
|
XvQueryAdaptors(x11->display, DefaultRootWindow(x11->display),
|
|
|
|
&ctx->adaptors, &ctx->ai)) {
|
2009-07-07 00:15:02 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_ERR, "[VO_XV] XvQueryAdaptors failed.\n");
|
2008-04-04 08:57:58 +02:00
|
|
|
goto error;
|
2002-04-07 04:10:39 +02:00
|
|
|
}
|
|
|
|
|
2004-06-14 06:53:03 +02:00
|
|
|
/* check adaptors */
|
2008-12-01 15:15:17 +01:00
|
|
|
if (x11->xv_port) {
|
2003-09-07 20:58:56 +02:00
|
|
|
int port_found;
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
for (port_found = 0, i = 0; !port_found && i < ctx->adaptors; i++) {
|
|
|
|
if ((ctx->ai[i].type & XvInputMask)
|
|
|
|
&& (ctx->ai[i].type & XvImageMask)) {
|
2008-04-04 07:04:11 +02:00
|
|
|
for (xv_p = ctx->ai[i].base_id;
|
2008-12-01 15:15:17 +01:00
|
|
|
xv_p < ctx->ai[i].base_id + ctx->ai[i].num_ports;
|
|
|
|
++xv_p) {
|
|
|
|
if (xv_p == x11->xv_port) {
|
2003-09-07 20:58:56 +02:00
|
|
|
port_found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-01 15:15:17 +01:00
|
|
|
if (port_found) {
|
2008-04-21 02:43:03 +02:00
|
|
|
if (XvGrabPort(x11->display, x11->xv_port, CurrentTime))
|
|
|
|
x11->xv_port = 0;
|
2008-12-01 15:15:17 +01:00
|
|
|
} else {
|
2009-07-07 00:15:02 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_WARN, "[VO_XV] Invalid port parameter, overriding with port 0.\n");
|
2008-04-21 02:43:03 +02:00
|
|
|
x11->xv_port = 0;
|
2003-09-07 20:58:56 +02:00
|
|
|
}
|
2003-09-06 15:40:00 +02:00
|
|
|
}
|
2004-06-14 06:53:03 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
for (i = 0; i < ctx->adaptors && x11->xv_port == 0; i++) {
|
2008-05-13 19:52:25 +02:00
|
|
|
/* check if adaptor number has been specified */
|
|
|
|
if (xv_adaptor != -1 && xv_adaptor != i)
|
2008-12-01 15:15:17 +01:00
|
|
|
continue;
|
2008-05-15 20:19:35 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
if ((ctx->ai[i].type & XvInputMask) && (ctx->ai[i].type & XvImageMask)) {
|
2008-04-04 07:04:11 +02:00
|
|
|
for (xv_p = ctx->ai[i].base_id;
|
|
|
|
xv_p < ctx->ai[i].base_id + ctx->ai[i].num_ports; ++xv_p)
|
2008-12-01 15:15:17 +01:00
|
|
|
if (!XvGrabPort(x11->display, xv_p, CurrentTime)) {
|
2008-04-21 02:43:03 +02:00
|
|
|
x11->xv_port = xv_p;
|
2008-06-15 14:13:29 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_V,
|
|
|
|
"[VO_XV] Using Xv Adapter #%d (%s)\n",
|
2008-06-17 01:18:10 +02:00
|
|
|
i, ctx->ai[i].name);
|
2004-06-14 06:53:03 +02:00
|
|
|
break;
|
2008-12-01 15:15:17 +01:00
|
|
|
} else {
|
2009-07-07 00:15:02 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_WARN, "[VO_XV] Could not grab port %i.\n",
|
2008-12-01 15:15:17 +01:00
|
|
|
(int) xv_p);
|
2004-06-14 06:53:03 +02:00
|
|
|
++busy_ports;
|
|
|
|
}
|
|
|
|
}
|
2002-04-07 04:10:39 +02:00
|
|
|
}
|
2008-12-01 15:15:17 +01:00
|
|
|
if (!x11->xv_port) {
|
2004-06-14 06:53:03 +02:00
|
|
|
if (busy_ports)
|
2009-07-07 00:15:02 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_ERR,
|
|
|
|
"[VO_XV] Could not find free Xvideo port - maybe another process is already\n"\
|
|
|
|
"[VO_XV] using it. Close all video applications, and try again. If that does\n"\
|
2012-10-11 02:04:08 +02:00
|
|
|
"[VO_XV] not help, see 'mpv -vo help' for other (non-xv) video out drivers.\n");
|
2004-06-14 06:53:03 +02:00
|
|
|
else
|
2009-07-07 00:15:02 +02:00
|
|
|
mp_tmsg(MSGT_VO, MSGL_ERR,
|
|
|
|
"[VO_XV] It seems there is no Xvideo support for your video card available.\n"\
|
|
|
|
"[VO_XV] Run 'xvinfo' to verify its Xv support and read\n"\
|
|
|
|
"[VO_XV] DOCS/HTML/en/video.html#xv!\n"\
|
2012-10-11 02:04:08 +02:00
|
|
|
"[VO_XV] See 'mpv -vo help' for other (non-xv) video out drivers.\n"\
|
2009-07-07 00:15:02 +02:00
|
|
|
"[VO_XV] Try -vo x11.\n");
|
2008-04-04 08:57:58 +02:00
|
|
|
goto error;
|
2002-04-07 04:10:39 +02:00
|
|
|
}
|
|
|
|
|
2008-04-20 08:34:27 +02:00
|
|
|
if (!vo_xv_init_colorkey(vo)) {
|
2008-12-01 15:15:17 +01:00
|
|
|
goto error; // bail out, colorkey setup failed
|
2002-10-23 02:36:55 +02:00
|
|
|
}
|
2008-04-20 08:34:27 +02:00
|
|
|
vo_xv_enable_vsync(vo);
|
|
|
|
vo_xv_get_max_img_dim(vo, &ctx->max_width, &ctx->max_height);
|
2002-10-23 02:36:55 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
ctx->fo = XvListImageFormats(x11->display, x11->xv_port,
|
|
|
|
(int *) &ctx->formats);
|
2002-04-11 23:07:00 +02:00
|
|
|
|
2002-02-17 09:24:43 +01:00
|
|
|
return 0;
|
2008-04-04 08:57:58 +02:00
|
|
|
|
2008-12-01 15:15:17 +01:00
|
|
|
error:
|
|
|
|
uninit(vo); // free resources
|
2008-04-04 08:57:58 +02:00
|
|
|
return -1;
|
2002-01-26 17:01:26 +01:00
|
|
|
}
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2008-04-04 07:04:11 +02:00
|
|
|
static int control(struct vo *vo, uint32_t request, void *data)
|
2002-02-09 01:47:26 +01:00
|
|
|
{
|
2008-04-04 07:04:11 +02:00
|
|
|
struct xvctx *ctx = vo->priv;
|
2008-04-21 02:14:37 +02:00
|
|
|
struct vo_x11_state *x11 = vo->x11;
|
2008-12-01 15:15:17 +01:00
|
|
|
switch (request) {
|
|
|
|
case VOCTRL_PAUSE:
|
|
|
|
return (ctx->is_paused = 1);
|
|
|
|
case VOCTRL_RESUME:
|
|
|
|
return (ctx->is_paused = 0);
|
|
|
|
case VOCTRL_QUERY_FORMAT:
|
|
|
|
return query_format(ctx, *((uint32_t *) data));
|
|
|
|
case VOCTRL_DRAW_IMAGE:
|
|
|
|
return draw_image(vo, data);
|
|
|
|
case VOCTRL_GET_PANSCAN:
|
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_FULLSCREEN:
|
|
|
|
vo_x11_fullscreen(vo);
|
|
|
|
/* indended, fallthrough to update panscan on fullscreen/windowed switch */
|
|
|
|
case VOCTRL_SET_PANSCAN:
|
2009-09-04 18:49:35 +02:00
|
|
|
resize(vo);
|
2008-12-01 15:15:17 +01:00
|
|
|
return VO_TRUE;
|
2011-12-05 05:36:20 +01:00
|
|
|
case VOCTRL_SET_EQUALIZER: {
|
|
|
|
vo->want_redraw = true;
|
|
|
|
struct voctrl_set_equalizer_args *args = data;
|
|
|
|
return vo_xv_set_eq(vo, x11->xv_port, args->name, args->value);
|
|
|
|
}
|
|
|
|
case VOCTRL_GET_EQUALIZER: {
|
|
|
|
struct voctrl_get_equalizer_args *args = data;
|
|
|
|
return vo_xv_get_eq(vo, x11->xv_port, args->name, args->valueptr);
|
|
|
|
}
|
2009-11-15 14:21:40 +01:00
|
|
|
case VOCTRL_SET_YUV_COLORSPACE:;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
struct mp_csp_details* given_cspc = data;
|
|
|
|
int is_709 = given_cspc->format == MP_CSP_BT_709;
|
|
|
|
vo_xv_set_eq(vo, x11->xv_port, "bt_709", is_709 * 200 - 100);
|
2011-12-05 05:36:20 +01:00
|
|
|
vo->want_redraw = true;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
return true;
|
2009-11-15 14:21:40 +01:00
|
|
|
case VOCTRL_GET_YUV_COLORSPACE:;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
struct mp_csp_details* cspc = data;
|
|
|
|
*cspc = (struct mp_csp_details) MP_CSP_DETAILS_DEFAULTS;
|
2009-11-15 14:21:40 +01:00
|
|
|
int bt709_enabled;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
if (vo_xv_get_eq(vo, x11->xv_port, "bt_709", &bt709_enabled))
|
|
|
|
cspc->format = bt709_enabled == 100 ? MP_CSP_BT_709 : MP_CSP_BT_601;
|
2009-11-15 14:21:40 +01:00
|
|
|
return true;
|
2008-12-01 15:15:17 +01:00
|
|
|
case VOCTRL_ONTOP:
|
|
|
|
vo_x11_ontop(vo);
|
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_UPDATE_SCREENINFO:
|
|
|
|
update_xinerama_info(vo);
|
|
|
|
return VO_TRUE;
|
2011-12-05 04:24:18 +01:00
|
|
|
case VOCTRL_REDRAW_FRAME:
|
|
|
|
return redraw_frame(vo);
|
2011-10-06 20:46:01 +02:00
|
|
|
case VOCTRL_SCREENSHOT: {
|
|
|
|
struct voctrl_screenshot_args *args = data;
|
|
|
|
args->out_image = get_screenshot(vo);
|
|
|
|
return true;
|
|
|
|
}
|
2004-06-14 06:53:03 +02:00
|
|
|
}
|
|
|
|
return VO_NOTIMPL;
|
2002-02-09 01:47:26 +01:00
|
|
|
}
|
2008-04-04 07:04:11 +02:00
|
|
|
|
|
|
|
const struct vo_driver video_out_xv = {
|
|
|
|
.is_new = 1,
|
|
|
|
.info = &info,
|
|
|
|
.preinit = preinit,
|
|
|
|
.config = config,
|
|
|
|
.control = control,
|
|
|
|
.draw_slice = draw_slice,
|
|
|
|
.draw_osd = draw_osd,
|
|
|
|
.flip_page = flip_page,
|
|
|
|
.check_events = check_events,
|
|
|
|
.uninit = uninit
|
|
|
|
};
|