summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/cfg-mplayer.h7
-rw-r--r--core/defaultopts.c1
-rw-r--r--core/mplayer.c4
-rw-r--r--core/options.h2
-rw-r--r--video/out/gl_common.c4
-rw-r--r--video/out/vo_vdpau.c4
-rw-r--r--video/out/vo_x11.c134
-rw-r--r--video/out/vo_xv.c408
-rw-r--r--video/out/x11_common.c1108
-rw-r--r--video/out/x11_common.h84
10 files changed, 781 insertions, 975 deletions
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index eb3b805622..9bf6d53d6d 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -36,9 +36,6 @@
extern char *lirc_configfile;
-/* only used at startup (setting these values from configfile) */
-extern int stop_xscreensaver;
-
extern int mp_msg_color;
extern int mp_msg_module;
@@ -615,8 +612,8 @@ const m_option_t mplayer_opts[]={
{"refreshrate",&vo_refresh_rate,CONF_TYPE_INT,CONF_RANGE, 0,100, NULL},
{"wid", &WinID, CONF_TYPE_INT64, 0, 0, 0, NULL},
#ifdef CONFIG_X11
- {"stop-xscreensaver", &stop_xscreensaver, CONF_TYPE_FLAG, 0, 0, 1, NULL},
- {"fstype", &vo_fstype_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
+ OPT_MAKE_FLAGS("stop-xscreensaver", vo_stop_screensaver, 0),
+ OPT_STRINGLIST("fstype", vo_fstype_list, 0),
#endif
{"heartbeat-cmd", &heartbeat_cmd, CONF_TYPE_STRING, 0, 0, 0, NULL},
{"mouseinput", &vo_nomouse_input, CONF_TYPE_FLAG, 0, 1, 0, NULL},
diff --git a/core/defaultopts.c b/core/defaultopts.c
index a7da8bb4e3..d0205cb3d3 100644
--- a/core/defaultopts.c
+++ b/core/defaultopts.c
@@ -25,6 +25,7 @@ void set_default_mplayer_options(struct MPOpts *opts)
.vo_gamma_contrast = 1000,
.vo_gamma_saturation = 1000,
.vo_gamma_hue = 1000,
+ .vo_stop_screensaver = 1,
.osd_level = 1,
.osd_duration = 1000,
.loop_times = -1,
diff --git a/core/mplayer.c b/core/mplayer.c
index bdebd3bab2..8aba5517fd 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -3284,7 +3284,7 @@ static void run_playloop(struct MPContext *mpctx)
vo_check_events(vo);
#ifdef CONFIG_X11
- if (stop_xscreensaver && vo->x11) {
+ if (vo->x11) {
xscreensaver_heartbeat(vo->x11);
}
#endif
@@ -4299,7 +4299,7 @@ static bool handle_help_options(struct MPContext *mpctx)
opt_exit = 1;
}
#ifdef CONFIG_X11
- if (vo_fstype_list && strcmp(vo_fstype_list[0], "help") == 0) {
+ if (opts->vo_fstype_list && strcmp(opts->vo_fstype_list[0], "help") == 0) {
fstype_help();
mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
opt_exit = 1;
diff --git a/core/options.h b/core/options.h
index d1c58fdda9..10eb7135fd 100644
--- a/core/options.h
+++ b/core/options.h
@@ -35,6 +35,8 @@ typedef struct MPOpts {
int requested_input_range;
int requested_output_range;
int cursor_autohide_delay;
+ char** vo_fstype_list;
+ int vo_stop_screensaver;
// ranges -100 - 100, 1000 if the vo default should be used
int vo_gamma_gamma;
diff --git a/video/out/gl_common.c b/video/out/gl_common.c
index dc249f4a73..887195bf18 100644
--- a/video/out/gl_common.c
+++ b/video/out/gl_common.c
@@ -1392,12 +1392,12 @@ MPGLContext *mpgl_init(enum MPGLType type, struct vo *vo)
ctx->create_window_gl3 = create_window_x11_gl3;
ctx->releaseGlContext = releaseGlContext_x11;
ctx->swapGlBuffers = swapGlBuffers_x11;
- ctx->update_xinerama_info = update_xinerama_info;
+ ctx->update_xinerama_info = vo_x11_update_screeninfo;
ctx->border = vo_x11_border;
ctx->check_events = vo_x11_check_events;
ctx->fullscreen = vo_x11_fullscreen;
ctx->ontop = vo_x11_ontop;
- ctx->vo_init = vo_init;
+ ctx->vo_init = vo_x11_init;
ctx->vo_uninit = vo_x11_uninit;
break;
#endif
diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c
index bc2db52f6a..0777ec084a 100644
--- a/video/out/vo_vdpau.c
+++ b/video/out/vo_vdpau.c
@@ -1511,7 +1511,7 @@ static int preinit(struct vo *vo, const char *arg)
if (vc->deint < 0)
vc->deint = 0;
- if (!vo_init(vo))
+ if (!vo_x11_init(vo))
return -1;
// After this calling uninit() should work to free resources
@@ -1632,7 +1632,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
vo_x11_ontop(vo);
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
- update_xinerama_info(vo);
+ vo_x11_update_screeninfo(vo);
return VO_TRUE;
case VOCTRL_NEWFRAME:
vc->deint_queue_pos = next_deint_queue_pos(vo, true);
diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c
index 72ae992eac..9b13ae2893 100644
--- a/video/out/vo_x11.c
+++ b/video/out/vo_x11.c
@@ -88,6 +88,7 @@ struct priv {
int dst_width;
XVisualInfo vinfo;
+ int ximage_depth;
int firstTime;
@@ -123,6 +124,56 @@ static void check_events(struct vo *vo)
flip_page(vo);
}
+/* Scan the available visuals on this Display/Screen. Try to find
+ * the 'best' available TrueColor visual that has a decent color
+ * depth (at least 15bit). If there are multiple visuals with depth
+ * >= 15bit, we prefer visuals with a smaller color depth. */
+static int find_depth_from_visuals(Display * dpy, int screen,
+ Visual ** visual_return)
+{
+ XVisualInfo visual_tmpl;
+ XVisualInfo *visuals;
+ int nvisuals, i;
+ int bestvisual = -1;
+ int bestvisual_depth = -1;
+
+ visual_tmpl.screen = screen;
+ visual_tmpl.class = TrueColor;
+ visuals = XGetVisualInfo(dpy,
+ VisualScreenMask | VisualClassMask,
+ &visual_tmpl, &nvisuals);
+ if (visuals != NULL)
+ {
+ for (i = 0; i < nvisuals; i++)
+ {
+ mp_msg(MSGT_VO, MSGL_V,
+ "vo: X11 truecolor visual %#lx, depth %d, R:%lX G:%lX B:%lX\n",
+ visuals[i].visualid, visuals[i].depth,
+ visuals[i].red_mask, visuals[i].green_mask,
+ visuals[i].blue_mask);
+ /*
+ * Save the visual index and its depth, if this is the first
+ * truecolor visul, or a visual that is 'preferred' over the
+ * previous 'best' visual.
+ */
+ if (bestvisual_depth == -1
+ || (visuals[i].depth >= 15
+ && (visuals[i].depth < bestvisual_depth
+ || bestvisual_depth < 15)))
+ {
+ bestvisual = i;
+ bestvisual_depth = visuals[i].depth;
+ }
+ }
+
+ if (bestvisual != -1 && visual_return != NULL)
+ *visual_return = visuals[bestvisual].visual;
+
+ XFree(visuals);
+ }
+ return bestvisual_depth;
+}
+
static void getMyXImage(struct priv *p, int foo)
{
struct vo *vo = p->vo;
@@ -298,8 +349,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
if (p->depth != 15 && p->depth != 16 && p->depth != 24 && p->depth != 32) {
Visual *visual;
- p->depth = vo_find_depth_from_visuals(vo->x11->display, vo->x11->screen,
- &visual);
+ p->depth = find_depth_from_visuals(vo->x11->display, vo->x11->screen,
+ &visual);
}
if (!XMatchVisualInfo(vo->x11->display, vo->x11->screen, p->depth,
DirectColor, &p->vinfo)
@@ -327,8 +378,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
vo_x11_create_vo_window(vo, &p->vinfo, vo->dx, vo->dy, vo->dwidth,
vo->dheight, flags, theCmap, "x11");
- if (WinID > 0)
- p->depth = vo_x11_update_geometry(vo, true);
#ifdef CONFIG_XF86VM
if (vm) {
@@ -343,6 +392,15 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
#endif
}
+ if (WinID > 0) {
+ unsigned depth, dummy_uint;
+ int dummy_int;
+ Window dummy_win;
+ XGetGeometry(vo->x11->display, vo->x11->window, &dummy_win, &dummy_int,
+ &dummy_int, &dummy_uint, &dummy_uint, &dummy_uint, &depth);
+ p->depth = depth;
+ }
+
int i;
for (i = 0; i < p->total_buffers; i++)
freeMyXImage(p, i);
@@ -570,13 +628,14 @@ static int redraw_frame(struct vo *vo)
static int query_format(struct vo *vo, uint32_t format)
{
+ struct priv *p = vo->priv;
mp_msg(MSGT_VO, MSGL_DBG2,
"vo_x11: query_format was called: %x (%s)\n", format,
vo_format_name(format));
if (IMGFMT_IS_RGB(format)) {
for (int n = 0; fmt2Xfmt[n].mpfmt; n++) {
if (fmt2Xfmt[n].mpfmt == format) {
- if (IMGFMT_RGB_DEPTH(format) == vo->x11->depthonscreen) {
+ if (IMGFMT_RGB_DEPTH(format) == p->ximage_depth) {
return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
VFCAP_OSD | VFCAP_FLIP;
} else {
@@ -593,6 +652,64 @@ static int query_format(struct vo *vo, uint32_t format)
return 0;
}
+static void find_x11_depth(struct vo *vo)
+{
+ struct vo_x11_state *x11 = vo->x11;
+ struct priv *p = vo->priv;
+ XImage *mXImage = NULL;
+ int depth, bpp, ximage_depth;
+ unsigned int mask;
+ XWindowAttributes attribs;
+
+ // get color depth (from root window, or the best visual):
+ XGetWindowAttributes(x11->display, x11->rootwin, &attribs);
+ depth = attribs.depth;
+
+ if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
+ {
+ Visual *visual;
+
+ depth = find_depth_from_visuals(x11->display, x11->screen, &visual);
+ if (depth != -1)
+ mXImage = XCreateImage(x11->display, visual, depth, ZPixmap,
+ 0, NULL, 1, 1, 8, 1);
+ } else
+ mXImage =
+ XGetImage(x11->display, x11->rootwin, 0, 0, 1, 1, AllPlanes, ZPixmap);
+
+ ximage_depth = depth; // display depth on screen
+
+ // get bits/pixel from XImage structure:
+ if (mXImage == NULL)
+ {
+ mask = 0;
+ } else
+ {
+ /* for the depth==24 case, the XImage structures might use
+ * 24 or 32 bits of data per pixel. */
+ bpp = mXImage->bits_per_pixel;
+ if ((ximage_depth + 7) / 8 != (bpp + 7) / 8)
+ ximage_depth = bpp; // by A'rpi
+ mask =
+ mXImage->red_mask | mXImage->green_mask | mXImage->blue_mask;
+ mp_msg(MSGT_VO, MSGL_V,
+ "vo: X11 color mask: %X (R:%lX G:%lX B:%lX)\n", mask,
+ mXImage->red_mask, mXImage->green_mask, mXImage->blue_mask);
+ XDestroyImage(mXImage);
+ }
+ if (((ximage_depth + 7) / 8) == 2)
+ {
+ if (mask == 0x7FFF)
+ ximage_depth = 15;
+ else if (mask == 0xFFFF)
+ ximage_depth = 16;
+ }
+
+ mp_msg(MSGT_VO, MSGL_V, "vo: X11 depth %d and %d bpp.\n", depth,
+ ximage_depth);
+
+ p->ximage_depth = ximage_depth;
+}
static void uninit(struct vo *vo)
{
@@ -624,8 +741,9 @@ static int preinit(struct vo *vo, const char *arg)
return ENOSYS;
}
- if (!vo_init(vo))
+ if (!vo_x11_init(vo))
return -1; // Can't open X11
+ find_x11_depth(vo);
return 0;
}
@@ -649,13 +767,13 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_GET_EQUALIZER:
{
struct voctrl_get_equalizer_args *args = data;
- return vo_x11_get_equalizer(args->name, args->valueptr);
+ return vo_x11_get_equalizer(vo, args->name, args->valueptr);
}
case VOCTRL_ONTOP:
vo_x11_ontop(vo);
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
- update_xinerama_info(vo);
+ vo_x11_update_screeninfo(vo);
return VO_TRUE;
case VOCTRL_REDRAW_FRAME:
return redraw_frame(vo);
diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c
index 90cc112ad2..8d52db96fa 100644
--- a/video/out/vo_xv.c
+++ b/video/out/vo_xv.c
@@ -64,7 +64,21 @@ static const vo_info_t info = {
""
};
+#define CK_METHOD_NONE 0 // no colorkey drawing
+#define CK_METHOD_BACKGROUND 1 // set colorkey as window background
+#define CK_METHOD_AUTOPAINT 2 // let xv draw the colorkey
+#define CK_METHOD_MANUALFILL 3 // manually draw the colorkey
+#define CK_SRC_USE 0 // use specified / default colorkey
+#define CK_SRC_SET 1 // use and set specified / default colorkey
+#define CK_SRC_CUR 2 // use current colorkey (get it from xv)
+
struct xvctx {
+ struct xv_ck_info_s {
+ int method; // CK_METHOD_* constants
+ int source; // CK_SRC_* constants
+ } xv_ck_info;
+ unsigned long xv_colorkey;
+ unsigned int xv_port;
XvAdaptorInfo *ai;
XvImageFormatValues *fo;
unsigned int formats, adaptors, xv_format;
@@ -116,14 +130,342 @@ static int find_xv_format(int imgfmt)
return 0;
}
-static void read_xv_csp(struct vo *vo)
+static int xv_find_atom(struct vo *vo, uint32_t xv_port, const char *name,
+ bool get, int *min, int *max)
+{
+ Atom atom = None;
+ int howmany = 0;
+ XvAttribute *attributes = XvQueryPortAttributes(vo->x11->display, xv_port,
+ &howmany);
+ for (int i = 0; i < howmany && attributes; i++) {
+ int flag = get ? XvGettable : XvSettable;
+ if (attributes[i].flags & flag) {
+ atom = XInternAtom(vo->x11->display, attributes[i].name, True);
+ *min = attributes[i].min_value;
+ *max = attributes[i].max_value;
+/* since we have SET_DEFAULTS first in our list, we can check if it's available
+ then trigger it if it's ok so that the other values are at default upon query */
+ if (atom != None) {
+ if (!strcmp(attributes[i].name, "XV_BRIGHTNESS") &&
+ (!strcasecmp(name, "brightness")))
+ break;
+ else if (!strcmp(attributes[i].name, "XV_CONTRAST") &&
+ (!strcasecmp(name, "contrast")))
+ break;
+ else if (!strcmp(attributes[i].name, "XV_SATURATION") &&
+ (!strcasecmp(name, "saturation")))
+ break;
+ else if (!strcmp(attributes[i].name, "XV_HUE") &&
+ (!strcasecmp(name, "hue")))
+ break;
+ if (!strcmp(attributes[i].name, "XV_RED_INTENSITY") &&
+ (!strcasecmp(name, "red_intensity")))
+ break;
+ else if (!strcmp(attributes[i].name, "XV_GREEN_INTENSITY")
+ && (!strcasecmp(name, "green_intensity")))
+ break;
+ else if (!strcmp(attributes[i].name, "XV_BLUE_INTENSITY")
+ && (!strcasecmp(name, "blue_intensity")))
+ break;
+ else if ((!strcmp(attributes[i].name, "XV_ITURBT_709") //NVIDIA
+ || !strcmp(attributes[i].name, "XV_COLORSPACE")) //ATI
+ && (!strcasecmp(name, "bt_709")))
+ break;
+ atom = None;
+ continue;
+ }
+ }
+ }
+ XFree(attributes);
+ return atom;
+}
+
+static int xv_set_eq(struct vo *vo, uint32_t xv_port, const char *name,
+ int value)
+{
+ mp_dbg(MSGT_VO, MSGL_V, "xv_set_eq called! (%s, %d)\n", name, value);
+
+ int min, max;
+ int atom = xv_find_atom(vo, xv_port, name, false, &min, &max);
+ if (atom != None) {
+ // -100 -> min
+ // 0 -> (max+min)/2
+ // +100 -> max
+ int port_value = (value + 100) * (max - min) / 200 + min;
+ XvSetPortAttribute(vo->x11->display, xv_port, atom, port_value);
+ return VO_TRUE;
+ }
+ return VO_FALSE;
+}
+
+static int xv_get_eq(struct vo *vo, uint32_t xv_port, const char *name,
+ int *value)
+{
+ int min, max;
+ int atom = xv_find_atom(vo, xv_port, name, true, &min, &max);
+ if (atom != None) {
+ int port_value = 0;
+ XvGetPortAttribute(vo->x11->display, xv_port, atom, &port_value);
+
+ *value = (port_value - min) * 200 / (max - min) - 100;
+ mp_dbg(MSGT_VO, MSGL_V, "xv_get_eq called! (%s, %d)\n",
+ name, *value);
+ return VO_TRUE;
+ }
+ return VO_FALSE;
+}
+
+static Atom xv_intern_atom_if_exists(struct vo *vo, char const *atom_name)
+{
+ struct xvctx *ctx = vo->priv;
+ XvAttribute *attributes;
+ int attrib_count, i;
+ Atom xv_atom = None;
+
+ attributes = XvQueryPortAttributes(vo->x11->display, ctx->xv_port,
+ &attrib_count);
+ if (attributes != NULL) {
+ for (i = 0; i < attrib_count; ++i) {
+ if (strcmp(attributes[i].name, atom_name) == 0) {
+ xv_atom = XInternAtom(vo->x11->display, atom_name, False);
+ break;
+ }
+ }
+ XFree(attributes);
+ }
+
+ return xv_atom;
+}
+
+// Try to enable vsync for xv.
+// Returns -1 if not available, 0 on failure and 1 on success.
+static int xv_enable_vsync(struct vo *vo)
+{
+ struct xvctx *ctx = vo->priv;
+ Atom xv_atom = xv_intern_atom_if_exists(vo, "XV_SYNC_TO_VBLANK");
+ if (xv_atom == None)
+ return -1;
+ return XvSetPortAttribute(vo->x11->display, ctx->xv_port, xv_atom, 1)
+ == Success;
+}
+
+// Get maximum supported source image dimensions.
+// If querying the dimensions fails, don't change *width and *height.
+static void xv_get_max_img_dim(struct vo *vo, uint32_t *width, uint32_t *height)
+{
+ struct xvctx *ctx = vo->priv;
+ XvEncodingInfo *encodings;
+ unsigned int num_encodings, idx;
+
+ XvQueryEncodings(vo->x11->display, ctx->xv_port, &num_encodings, &encodings);
+
+ if (encodings) {
+ for (idx = 0; idx < num_encodings; ++idx) {
+ if (strcmp(encodings[idx].name, "XV_IMAGE") == 0) {
+ *width = encodings[idx].width;
+ *height = encodings[idx].height;
+ break;
+ }
+ }
+ }
+
+ mp_msg(MSGT_VO, MSGL_V,
+ "[xv] Maximum source image dimensions: %ux%u\n",
+ *width, *height);
+
+ XvFreeEncodingInfo(encodings);
+}
+
+static void xv_print_ck_info(struct xvctx *xv)
+{
+ mp_msg(MSGT_VO, MSGL_V, "[xv] ");
+
+ switch (xv->xv_ck_info.method) {
+ case CK_METHOD_NONE:
+ mp_msg(MSGT_VO, MSGL_V, "Drawing no colorkey.\n");
+ return;
+ case CK_METHOD_AUTOPAINT:
+ mp_msg(MSGT_VO, MSGL_V, "Colorkey is drawn by Xv.");
+ break;
+ case CK_METHOD_MANUALFILL:
+ mp_msg(MSGT_VO, MSGL_V, "Drawing colorkey manually.");
+ break;
+ case CK_METHOD_BACKGROUND:
+ mp_msg(MSGT_VO, MSGL_V, "Colorkey is drawn as window background.");
+ break;
+ }
+
+ mp_msg(MSGT_VO, MSGL_V, "\n[xv] ");
+
+ switch (xv->xv_ck_info.source) {
+ case CK_SRC_CUR:
+ mp_msg(MSGT_VO, MSGL_V, "Using colorkey from Xv (0x%06lx).\n",
+ xv->xv_colorkey);
+ break;
+ case CK_SRC_USE:
+ if (xv->xv_ck_info.method == CK_METHOD_AUTOPAINT) {
+ mp_msg(MSGT_VO, MSGL_V, "Ignoring colorkey from mpv (0x%06lx).\n",
+ xv->xv_colorkey);
+ } else {
+ mp_msg(MSGT_VO, MSGL_V,
+ "Using colorkey from mpv (0x%06lx). Use -colorkey to change.\n",
+ xv->xv_colorkey);
+ }
+ break;
+ case CK_SRC_SET:
+ mp_msg(MSGT_VO, MSGL_V, "Setting and using colorkey from mpv (0x%06lx)."
+ " Use -colorkey to change.\n", xv->xv_colorkey);
+ break;
+ }
+}
+
+/* NOTE: If vo_colorkey has bits set after the first 3 low order bytes
+ * we don't draw anything as this means it was forced to off. */
+static int xv_init_colorkey(struct vo *vo)
+{
+ struct xvctx *ctx = vo->priv;
+ Display *display = vo->x11->display;
+ Atom xv_atom;
+ int rez;
+
+ /* check if colorkeying is needed */
+ xv_atom = xv_intern_atom_if_exists(vo, "XV_COLORKEY");
+ if (xv_atom != None && !(vo_colorkey & 0xFF000000)) {
+ if (ctx->xv_ck_info.source == CK_SRC_CUR) {
+ int colorkey_ret;
+
+ rez = XvGetPortAttribute(display, ctx->xv_port, xv_atom,
+ &colorkey_ret);
+ if (rez == Success)
+ ctx->xv_colorkey = colorkey_ret;
+ else {
+ mp_msg(MSGT_VO, MSGL_FATAL, "[xv] Couldn't get colorkey!"
+ "Maybe the selected Xv port has no overlay.\n");
+ return 0; // error getting colorkey
+ }
+ } else {
+ ctx->xv_colorkey = vo_colorkey;
+
+ /* check if we have to set the colorkey too */
+ if (ctx->xv_ck_info.source == CK_SRC_SET) {
+ xv_atom = XInternAtom(display, "XV_COLORKEY", False);
+
+ rez = XvSetPortAttribute(display, ctx->xv_port, xv_atom,
+ vo_colorkey);
+ if (rez != Success) {
+ mp_msg(MSGT_VO, MSGL_FATAL, "[xv] Couldn't set colorkey!\n");
+ return 0; // error setting colorkey
+ }
+ }
+ }
+
+ xv_atom = xv_intern_atom_if_exists(vo, "XV_AUTOPAINT_COLORKEY");
+
+ /* should we draw the colorkey ourselves or activate autopainting? */
+ if (ctx->xv_ck_info.method == CK_METHOD_AUTOPAINT) {
+ rez = !Success;
+
+ if (xv_atom != None) // autopaint is supported
+ rez = XvSetPortAttribute(display, ctx->xv_port, xv_atom, 1);
+
+ if (rez != Success)
+ ctx->xv_ck_info.method = CK_METHOD_MANUALFILL;
+ } else {
+ // disable colorkey autopainting if supported
+ if (xv_atom != None)
+ XvSetPortAttribute(display, ctx->xv_port, xv_atom, 0);
+ }
+ } else // do no colorkey drawing at all
+ ctx->xv_ck_info.method = CK_METHOD_NONE;
+
+ xv_print_ck_info(ctx);
+
+ return 1;
+}
+
+/* Draw the colorkey on the video window.
+ *
+ * Draws the colorkey depending on the set method ( colorkey_handling ).
+ *
+ * Also draws the black bars ( when the video doesn't fit the display in
+ * fullscreen ) separately, so they don't overlap with the video area. */
+static void xv_draw_colorkey(struct vo *vo, int32_t x, int32_t y,
+ int32_t w, int32_t h)
{
struct xvctx *ctx = vo->priv;
struct vo_x11_state *x11 = vo->x11;
+ if (ctx->xv_ck_info.method == CK_METHOD_MANUALFILL ||
+ ctx->xv_ck_info.method == CK_METHOD_BACKGROUND)
+ {
+ //less tearing than XClearWindow()
+ XSetForeground(x11->display, x11->vo_gc, ctx->xv_colorkey);
+ XFillRectangle(x11->display, x11->window, x11->vo_gc, x, y, w, h);
+ }
+}
+
+// Tests if a valid argument for the ck suboption was given.
+static int xv_test_ck(void *arg)
+{
+ strarg_t *strarg = (strarg_t *)arg;
+
+ if (strargcmp(strarg, "use") == 0 ||
+ strargcmp(strarg, "set") == 0 ||
+ strargcmp(strarg, "cur") == 0)
+ return 1;
+
+ return 0;
+}
+
+// Tests if a valid arguments for the ck-method suboption was given.
+static int xv_test_ckm(void *arg)
+{
+ strarg_t *strarg = (strarg_t *)arg;
+
+ if (strargcmp(strarg, "bg") == 0 ||
+ strargcmp(strarg, "man") == 0 ||
+ strargcmp(strarg, "auto") == 0)
+ return 1;
+
+ return 0;
+}
+
+/* Modify the colorkey_handling var according to str
+ *
+ * Checks if a valid pointer ( not NULL ) to the string
+ * was given. And in that case modifies the colorkey_handling
+ * var to reflect the requested behaviour.
+ * If nothing happens the content of colorkey_handling stays
+ * the same.
+ */
+static void xv_setup_colorkeyhandling(struct xvctx *ctx,
+ const char *ck_method_str,
+ const char *ck_str)
+{
+ /* check if a valid pointer to the string was passed */
+ if (ck_str) {
+ if (strncmp(ck_str, "use", 3) == 0)
+ ctx->xv_ck_info.source = CK_SRC_USE;
+ else if (strncmp(ck_str, "set", 3) == 0)
+ ctx->xv_ck_info.source = CK_SRC_SET;
+ }
+ /* check if a valid pointer to the string was passed */
+ if (ck_method_str) {
+ if (strncmp(ck_method_str, "bg", 2) == 0)
+ ctx->xv_ck_info.method = CK_METHOD_BACKGROUND;
+ else if (strncmp(ck_method_str, "man", 3) == 0)
+ ctx->xv_ck_info.method = CK_METHOD_MANUALFILL;
+ else if (strncmp(ck_method_str, "auto", 4) == 0)
+ ctx->xv_ck_info.method = CK_METHOD_AUTOPAINT;
+ }
+}
+
+static void read_xv_csp(struct vo *vo)
+{
+ struct xvctx *ctx = vo->priv;
struct mp_csp_details *cspc = &ctx->cached_csp;
*cspc = (struct mp_csp_details) MP_CSP_DETAILS_DEFAULTS;
int bt709_enabled;
- if (vo_xv_get_eq(vo, x11->xv_port, "bt_709", &bt709_enabled))
+ if (xv_get_eq(vo, ctx->xv_port, "bt_709", &bt709_enabled))
cspc->format = bt709_enabled == 100 ? MP_CSP_BT_709 : MP_CSP_BT_601;
}
@@ -140,7 +482,7 @@ static void resize(struct vo *vo)
struct mp_rect *dst = &ctx->dst_rect;
int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0;
vo_x11_clearwindow_part(vo, vo->x11->window, dw, dh);
- vo_xv_draw_colorkey(vo, dst->x0, dst->y0, dw, dh);
+ xv_draw_colorkey(vo, dst->x0, dst->y0, dw, dh);
read_xv_csp(vo);
}
@@ -204,8 +546,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
xswa.border_pixel = 0;
xswamask = CWBorderPixel;
- if (x11->xv_ck_info.method == CK_METHOD_BACKGROUND) {
- xswa.background_pixel = x11->xv_colorkey;
+ if (ctx->xv_ck_info.method == CK_METHOD_BACKGROUND) {
+ xswa.background_pixel = ctx->xv_colorkey;
xswamask |= CWBackPixel;
}
@@ -226,7 +568,7 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
}
mp_msg(MSGT_VO, MSGL_V, "using Xvideo port %d for hw scaling\n",
- x11->xv_port);
+ ctx->xv_port);
// In case config has been called before
for (i = 0; i < ctx->total_buffers; i++)
@@ -264,7 +606,7 @@ static void allocate_xvimage(struct vo *vo, int foo)
}
if (ctx->Shmem_Flag) {
ctx->xvimage[foo] =
- (XvImage *) XvShmCreateImage(x11->display, x11->xv_port,
+ (XvImage *) XvShmCreateImage(x11->display, ctx->xv_port,
ctx->xv_format, NULL,
aligned_w, ctx->image_height,
&ctx->Shminfo[foo]);
@@ -284,7 +626,7 @@ static void allocate_xvimage(struct vo *vo, int foo)
#endif
{
ctx->xvimage[foo] =
- (XvImage *) XvCreateImage(x11->display, x11->xv_port,
+ (XvImage *) XvCreateImage(x11->display, ctx->xv_port,
ctx->xv_format, NULL, aligned_w,
ctx->image_height);
ctx->xvimage[foo]->data = av_malloc(ctx->xvimage[foo]->data_size);
@@ -323,7 +665,7 @@ static inline void put_xvimage(struct vo *vo, XvImage *xvi)
int sw = src->x1 - src->x0, sh = src->y1 - src->y0;
#ifdef HAVE_SHM
if (ctx->Shmem_Flag) {
- XvShmPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi,
+ XvShmPutImage(x11->display, ctx->xv_port, x11->window, x11->vo_gc, xvi,
src->x0, src->y0, sw, sh,
dst->x0, dst->y0, dw, dh,
True);
@@ -331,7 +673,7 @@ static inline void put_xvimage(struct vo *vo, XvImage *xvi)
} else
#endif
{
- XvPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi,
+ XvPutImage(x11->display, ctx->xv_port, x11->window, x11->vo_gc, xvi,
src->x0, src->y0, sw, sh,
dst->x0, dst->y0, dw, dh);
}
@@ -504,11 +846,14 @@ static int preinit(struct vo *vo, const char *arg)
unsigned int i;
strarg_t ck_src_arg = { 0, NULL };
strarg_t ck_method_arg = { 0, NULL };
- struct xvctx *ctx = talloc_zero(vo, struct xvctx);
+ struct xvctx *ctx = talloc_ptrtype(vo, ctx);
+ *ctx = (struct xvctx) {
+ .xv_ck_info = { CK_METHOD_MANUALFILL, CK_SRC_CUR },
+ };
vo->priv = ctx;
int xv_adaptor = -1;
- if (!vo_init(vo))
+ if (!vo_x11_init(vo))
return -1;
struct vo_x11_state *x11 = vo->x11;
@@ -516,22 +861,20 @@ static int preinit(struct vo *vo, const char *arg)
const opt_t subopts[] =
{
/* name arg type arg var test */
- { "port", OPT_ARG_INT, &x11->xv_port, int_pos },
+ { "port", OPT_ARG_INT, &ctx->xv_port, int_pos },
{ "adaptor", OPT_ARG_INT, &xv_adaptor, int_non_neg },
{ "ck", OPT_ARG_STR, &ck_src_arg, xv_test_ck },
{ "ck-method", OPT_ARG_STR, &ck_method_arg, xv_test_ckm },
{ NULL }
};
- x11->xv_port = 0;
-
/* parse suboptions */
if (subopt_parse(arg, subopts) != 0) {
return -1;
}
/* modify colorkey settings according to the given options */
- xv_setup_colorkeyhandling(vo, ck_method_arg.str, ck_src_arg.str);
+ xv_setup_colorkeyhandling(ctx, ck_method_arg.str, ck_src_arg.str);
/* check for Xvideo extension */
unsigned int ver, rel, req, ev, err;
@@ -549,7 +892,7 @@ static int preinit(struct vo *vo, const char *arg)
}
/* check adaptors */
- if (x11->xv_port) {
+ if (ctx->xv_port) {
int port_found;
for (port_found = 0, i = 0; !port_found && i < ctx->adaptors; i++) {
@@ -558,7 +901,7 @@ static int preinit(struct vo *vo, const char *arg)
for (xv_p = ctx->ai[i].base_id;
xv_p < ctx->ai[i].base_id + ctx->ai[i].num_ports;
++xv_p) {
- if (xv_p == x11->xv_port) {
+ if (xv_p == ctx->xv_port) {
port_found = 1;
break;
}
@@ -566,15 +909,15 @@ static int preinit(struct vo *vo, const char *arg)
}
}
if (port_found) {
- if (XvGrabPort(x11->display, x11->xv_port, CurrentTime))
- x11->xv_port = 0;
+ if (XvGrabPort(x11->display, ctx->xv_port, CurrentTime))
+ ctx->xv_port = 0;
} else {
mp_tmsg(MSGT_VO, MSGL_WARN, "[VO_XV] Invalid port parameter, overriding with port 0.\n");
- x11->xv_port = 0;
+ ctx->xv_port = 0;
}
}
- for (i = 0; i < ctx->adaptors && x11->xv_port == 0; i++) {
+ for (i = 0; i < ctx->adaptors && ctx->xv_port == 0; i++) {
/* check if adaptor number has been specified */
if (xv_adaptor != -1 && xv_adaptor != i)
continue;
@@ -583,7 +926,7 @@ static int preinit(struct vo *vo, const char *arg)
for (xv_p = ctx->ai[i].base_id;
xv_p < ctx->ai[i].base_id + ctx->ai[i].num_ports; ++xv_p)
if (!XvGrabPort(x11->display, xv_p, CurrentTime)) {
- x11->xv_port = xv_p;
+ ctx->xv_port = xv_p;
mp_msg(MSGT_VO, MSGL_V,
"[VO_XV] Using Xv Adapter #%d (%s)\n",
i, ctx->ai[i].name);
@@ -595,7 +938,7 @@ static int preinit(struct vo *vo, const char *arg)
}
}
}
- if (!x11->xv_port) {
+ if (!ctx->xv_port) {
if (busy_ports)
mp_tmsg(MSGT_VO, MSGL_ERR,
"[VO_XV] Could not find free Xvideo port - maybe another process is already\n"\
@@ -611,13 +954,13 @@ static int preinit(struct vo *vo, const char *arg)
goto error;
}
- if (!vo_xv_init_colorkey(vo)) {
+ if (!xv_init_colorkey(vo)) {
goto error; // bail out, colorkey setup failed
}
- vo_xv_enable_vsync(vo);
- vo_xv_get_max_img_dim(vo, &ctx->max_width, &ctx->max_height);
+ xv_enable_vsync(vo);
+ xv_get_max_img_dim(vo, &ctx->max_width, &ctx->max_height);
- ctx->fo = XvListImageFormats(x11->display, x11->xv_port,
+ ctx->fo = XvListImageFormats(x11->display, ctx->xv_port,
(int *) &ctx->formats);
return 0;
@@ -630,7 +973,6 @@ static int preinit(struct vo *vo, const char *arg)
static int control(struct vo *vo, uint32_t request, void *data)
{
struct xvctx *ctx = vo->priv;
- struct vo_x11_state *x11 = vo->x11;
switch (request) {
case VOCTRL_PAUSE:
return (ctx->is_paused = 1);
@@ -647,16 +989,16 @@ static int control(struct vo *vo, uint32_t request, void *data)
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);
+ return xv_set_eq(vo, ctx->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);
+ return xv_get_eq(vo, ctx->xv_port, args->name, args->valueptr);
}
case VOCTRL_SET_YUV_COLORSPACE:;
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);
+ xv_set_eq(vo, ctx->xv_port, "bt_709", is_709 * 200 - 100);
read_xv_csp(vo);
vo->want_