summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-11-17 21:07:41 +0100
committerwm4 <wm4@nowhere>2015-11-17 21:21:19 +0100
commit0ec35fa111391b8069640ba2f616746a1b5530a5 (patch)
treee5356e8ab396e1c370a7784843f3101d3195469f
parent25fe9e89e7db1658acac84ec8ac0a292b2e86165 (diff)
downloadmpv-0ec35fa111391b8069640ba2f616746a1b5530a5.tar.bz2
mpv-0ec35fa111391b8069640ba2f616746a1b5530a5.tar.xz
videotoolbox: make decoder format customizable
Because apparently there's no ideal universally working format. The weird OpenGL texture format for kCVPixelFormatType_32BGRA is from: http://stackoverflow.com/questions/22077544/draw-an-iosurface-to-an-opengl-context (Which apparently got it from the linked Apple example code.)
-rw-r--r--DOCS/man/options.rst8
-rw-r--r--options/options.c4
-rw-r--r--options/options.h1
-rw-r--r--video/decode/videotoolbox.c4
-rw-r--r--video/out/opengl/hwdec.c11
-rw-r--r--video/out/opengl/hwdec.h6
-rw-r--r--video/out/opengl/hwdec_osx.c24
-rw-r--r--video/out/vo_opengl.c4
-rw-r--r--video/out/vo_opengl_cb.c5
9 files changed, 54 insertions, 13 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index fe76296d5f..cdc0e75094 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -618,6 +618,14 @@ Video
to temporarily set the ``hwdec`` option just during OpenGL context
initialization with ``mpv_opengl_cb_init_gl()``.
+``--videotoolbox-format=<name>``
+ Set the internal pixel format used by ``--hwdec=videotoolbox`` on OSX. The
+ choice of the format can influence performance considerably. On the other
+ hand, there doesn't appear to be a good way to detect the best format for
+ the given hardware. ``nv12``, the default works better on modern hardware,
+ while ``uyvy422`` appears to be better for old hardware. ``rgb0`` also
+ works.
+
``--panscan=<0.0-1.0>``
Enables pan-and-scan functionality (cropping the sides of e.g. a 16:9
video to make it fit a 4:3 display without black bands). The range
diff --git a/options/options.c b/options/options.c
index a42d818c83..fb9237938c 100644
--- a/options/options.c
+++ b/options/options.c
@@ -308,6 +308,9 @@ const m_option_t mp_opts[] = {
OPT_CHOICE_C("hwdec", hwdec_api, 0, mp_hwdec_names),
OPT_CHOICE_C("hwdec-preload", vo.hwdec_preload_api, 0, mp_hwdec_names),
OPT_STRING("hwdec-codecs", hwdec_codecs, 0),
+#if HAVE_VIDEOTOOLBOX_HWACCEL
+ OPT_IMAGEFORMAT("videotoolbox-format", videotoolbox_format, 0),
+#endif
OPT_SUBSTRUCT("sws", vo.sws_opts, sws_conf, 0),
@@ -804,6 +807,7 @@ const struct MPOpts mp_default_opts = {
.screenshot_template = "mpv-shot%n",
.hwdec_codecs = "h264,vc1,wmv3,hevc,mpeg2video",
+ .videotoolbox_format = IMGFMT_NV12,
.index_mode = 1,
diff --git a/options/options.h b/options/options.h
index 49387f388b..7c9046f50b 100644
--- a/options/options.h
+++ b/options/options.h
@@ -268,6 +268,7 @@ typedef struct MPOpts {
int hwdec_api;
char *hwdec_codecs;
+ int videotoolbox_format;
int w32_priority;
diff --git a/video/decode/videotoolbox.c b/video/decode/videotoolbox.c
index 470f6b6cf3..c5035f3a5b 100644
--- a/video/decode/videotoolbox.c
+++ b/video/decode/videotoolbox.c
@@ -31,7 +31,7 @@ static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
const char *decoder)
{
hwdec_request_api(info, "videotoolbox");
- if (!info || !info->hwctx)
+ if (!info || !info->hwctx || info->hwctx->type != HWDEC_VIDEOTOOLBOX)
return HWDEC_ERR_NO_CTX;
switch (mp_codec_to_av_codec_id(decoder)) {
case AV_CODEC_ID_H264:
@@ -88,7 +88,7 @@ static int init_decoder(struct lavc_ctx *ctx, int w, int h)
av_videotoolbox_default_free(ctx->avctx);
AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context();
- vtctx->cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
+ vtctx->cv_pix_fmt_type = (uintptr_t)ctx->hwdec_info->hwctx->priv;
int err = av_videotoolbox_default_init2(ctx->avctx, vtctx);
if (err < 0) {
diff --git a/video/out/opengl/hwdec.c b/video/out/opengl/hwdec.c
index 2a8c1eb14b..3c3a9785a6 100644
--- a/video/out/opengl/hwdec.c
+++ b/video/out/opengl/hwdec.c
@@ -55,6 +55,7 @@ static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = {
};
static struct gl_hwdec *load_hwdec_driver(struct mp_log *log, GL *gl,
+ struct mpv_global *global,
const struct gl_hwdec_driver *drv,
bool is_auto)
{
@@ -62,6 +63,7 @@ static struct gl_hwdec *load_hwdec_driver(struct mp_log *log, GL *gl,
*hwdec = (struct gl_hwdec) {
.driver = drv,
.log = mp_log_new(hwdec, log, drv->api_name),
+ .global = global,
.gl = gl,
.gl_texture_target = GL_TEXTURE_2D,
.probing = is_auto,
@@ -76,13 +78,13 @@ static struct gl_hwdec *load_hwdec_driver(struct mp_log *log, GL *gl,
}
struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl,
- const char *api_name)
+ struct mpv_global *g, const char *api_name)
{
bool is_auto = api_name && strcmp(api_name, "auto") == 0;
for (int n = 0; mpgl_hwdec_drivers[n]; n++) {
const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n];
if (is_auto || (api_name && strcmp(drv->api_name, api_name) == 0)) {
- struct gl_hwdec *r = load_hwdec_driver(log, gl, drv, is_auto);
+ struct gl_hwdec *r = load_hwdec_driver(log, gl, g, drv, is_auto);
if (r)
return r;
}
@@ -91,9 +93,10 @@ struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl,
}
// Like gl_hwdec_load_api(), but use HWDEC_... identifiers.
-struct gl_hwdec *gl_hwdec_load_api_id(struct mp_log *log, GL *gl, int id)
+struct gl_hwdec *gl_hwdec_load_api_id(struct mp_log *log, GL *gl,
+ struct mpv_global *g, int id)
{
- return gl_hwdec_load_api(log, gl, m_opt_choice_str(mp_hwdec_names, id));
+ return gl_hwdec_load_api(log, gl, g, m_opt_choice_str(mp_hwdec_names, id));
}
void gl_hwdec_uninit(struct gl_hwdec *hwdec)
diff --git a/video/out/opengl/hwdec.h b/video/out/opengl/hwdec.h
index 6f07536f57..ac1771c28d 100644
--- a/video/out/opengl/hwdec.h
+++ b/video/out/opengl/hwdec.h
@@ -9,6 +9,7 @@ struct mp_hwdec_info;
struct gl_hwdec {
const struct gl_hwdec_driver *driver;
struct mp_log *log;
+ struct mpv_global *global;
GL *gl;
struct mp_hwdec_ctx *hwctx;
// For free use by hwdec driver
@@ -45,8 +46,9 @@ struct gl_hwdec_driver {
};
struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl,
- const char *api_name);
-struct gl_hwdec *gl_hwdec_load_api_id(struct mp_log *log, GL *gl, int id);
+ struct mpv_global *g, const char *api_name);
+struct gl_hwdec *gl_hwdec_load_api_id(struct mp_log *log, GL *gl,
+ struct mpv_global *g, int id);
void gl_hwdec_uninit(struct gl_hwdec *hwdec);
diff --git a/video/out/opengl/hwdec_osx.c b/video/out/opengl/hwdec_osx.c
index 84e8abca41..d1212e220f 100644
--- a/video/out/opengl/hwdec_osx.c
+++ b/video/out/opengl/hwdec_osx.c
@@ -26,6 +26,8 @@
#include "video/mp_image_pool.h"
#include "hwdec.h"
+#include "common/global.h"
+#include "options/options.h"
struct vt_gl_plane_format {
GLenum gl_format;
@@ -55,7 +57,23 @@ static struct vt_format vt_formats[] = {
{ GL_RED, GL_UNSIGNED_BYTE, GL_RED },
{ GL_RG, GL_UNSIGNED_BYTE, GL_RG } ,
}
- }
+ },
+ {
+ .cvpixfmt = kCVPixelFormatType_422YpCbCr8,
+ .imgfmt = IMGFMT_UYVY,
+ .planes = 1,
+ .gl = {
+ { GL_RGB_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, GL_RGB }
+ }
+ },
+ {
+ .cvpixfmt = kCVPixelFormatType_32BGRA,
+ .imgfmt = IMGFMT_RGB0,
+ .planes = 1,
+ .gl = {
+ { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, GL_RGBA }
+ }
+ },
};
static struct vt_format *vt_get_gl_format(uint32_t cvpixfmt)
@@ -134,7 +152,8 @@ static int create(struct gl_hwdec *hw)
return -1;
struct priv *p = talloc_zero(hw, struct priv);
- struct vt_format *f = vt_get_gl_format_from_imgfmt(IMGFMT_NV12);
+ struct vt_format *f =
+ vt_get_gl_format_from_imgfmt(hw->global->opts->videotoolbox_format);
if (!f)
return -1;
@@ -143,6 +162,7 @@ static int create(struct gl_hwdec *hw)
hw->hwctx = &p->hwctx;
hw->hwctx->download_image = download_image;
hw->hwctx->type = HWDEC_VIDEOTOOLBOX;
+ hw->hwctx->priv = (void *)(uintptr_t)f->cvpixfmt;
hw->gl_texture_target = GL_TEXTURE_RECTANGLE;
hw->gl->GenTextures(MP_MAX_PLANES, p->gl_planes);
diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c
index 23a22a3f7e..1147aba79a 100644
--- a/video/out/vo_opengl.c
+++ b/video/out/vo_opengl.c
@@ -205,7 +205,7 @@ static void request_hwdec_api(struct gl_priv *p, const char *api_name)
if (p->hwdec)
return;
- p->hwdec = gl_hwdec_load_api(p->vo->log, p->gl, api_name);
+ p->hwdec = gl_hwdec_load_api(p->vo->log, p->gl, p->vo->global, api_name);
gl_video_set_hwdec(p->renderer, p->hwdec);
if (p->hwdec)
p->hwdec_info.hwctx = p->hwdec->hwctx;
@@ -439,7 +439,7 @@ static int preinit(struct vo *vo)
if (hwdec == HWDEC_NONE)
hwdec = vo->global->opts->hwdec_api;
if (hwdec != HWDEC_NONE) {
- p->hwdec = gl_hwdec_load_api_id(p->vo->log, p->gl, hwdec);
+ p->hwdec = gl_hwdec_load_api_id(p->vo->log, p->gl, vo->global, hwdec);
gl_video_set_hwdec(p->renderer, p->hwdec);
if (p->hwdec)
p->hwdec_info.hwctx = p->hwdec->hwctx;
diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c
index 687b9e3528..b90031d922 100644
--- a/video/out/vo_opengl_cb.c
+++ b/video/out/vo_opengl_cb.c
@@ -58,6 +58,7 @@ struct vo_priv {
struct mpv_opengl_cb_context {
struct mp_log *log;
+ struct mpv_global *global;
struct mp_client_api *client_api;
pthread_mutex_t lock;
@@ -130,6 +131,7 @@ struct mpv_opengl_cb_context *mp_opengl_create(struct mpv_global *g,
ctx->gl = talloc_zero(ctx, GL);
+ ctx->global = g;
ctx->log = mp_log_new(ctx, g->log, "opengl-cb");
ctx->client_api = client_api;
@@ -178,7 +180,8 @@ int mpv_opengl_cb_init_gl(struct mpv_opengl_cb_context *ctx, const char *exts,
if (!ctx->renderer)
return MPV_ERROR_UNSUPPORTED;
- ctx->hwdec = gl_hwdec_load_api_id(ctx->log, ctx->gl, ctx->hwdec_api);
+ ctx->hwdec = gl_hwdec_load_api_id(ctx->log, ctx->gl, ctx->global,
+ ctx->hwdec_api);
gl_video_set_hwdec(ctx->renderer, ctx->hwdec);
if (ctx->hwdec)
ctx->hwdec_info.hwctx = ctx->hwdec->hwctx;