summaryrefslogtreecommitdiffstats
path: root/video/decode
diff options
context:
space:
mode:
Diffstat (limited to 'video/decode')
-rw-r--r--video/decode/lavc.h1
-rw-r--r--video/decode/vaapi.c108
-rw-r--r--video/decode/vd_lavc.c2
3 files changed, 108 insertions, 3 deletions
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index 681f151ad0..32b827b964 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -18,6 +18,7 @@ enum hwdec_type {
HWDEC_VDA = 2,
HWDEC_CRYSTALHD = 3,
HWDEC_VAAPI = 4,
+ HWDEC_VAAPI_COPY = 5,
};
typedef struct lavc_ctx {
diff --git a/video/decode/vaapi.c b/video/decode/vaapi.c
index 8bec94d950..82c46de81e 100644
--- a/video/decode/vaapi.c
+++ b/video/decode/vaapi.c
@@ -25,6 +25,8 @@
#include <libavcodec/vaapi.h>
#include <libavutil/common.h>
+#include <X11/Xlib.h>
+
#include "lavc.h"
#include "mpvcore/mp_common.h"
#include "mpvcore/av_common.h"
@@ -54,6 +56,7 @@
struct priv {
struct mp_vaapi_ctx *ctx;
VADisplay display;
+ Display *x11_display;
// libavcodec shared struct
struct vaapi_context *va_context;
@@ -64,6 +67,8 @@ struct priv {
struct va_surface_pool *pool;
int rt_format;
+
+ bool printed_readback_warning;
};
struct profile_entry {
@@ -342,6 +347,38 @@ static struct mp_image *allocate_image(struct lavc_ctx *ctx, int format,
return NULL;
}
+
+static void destroy_va_dummy_ctx(struct priv *p)
+{
+ if (p->x11_display)
+ XCloseDisplay(p->x11_display);
+ p->x11_display = NULL;
+ va_destroy(p->ctx);
+ p->ctx = NULL;
+}
+
+// Creates a "private" VADisplay, disconnected from the VO. We just create a
+// new X connection, because that's simpler. (We could also pass the X
+// connection along with struct mp_hwdec_info, if we wanted.)
+static bool create_va_dummy_ctx(struct priv *p)
+{
+ p->x11_display = XOpenDisplay(NULL);
+ if (!p->x11_display)
+ goto destroy_ctx;
+ VADisplay *display = vaGetDisplay(p->x11_display);
+ if (!display)
+ goto destroy_ctx;
+ p->ctx = va_initialize(display);
+ if (!p->ctx) {
+ vaTerminate(display);
+ goto destroy_ctx;
+ }
+ return true;
+destroy_ctx:
+ destroy_va_dummy_ctx(p);
+ return false;
+}
+
static void uninit(struct lavc_ctx *ctx)
{
struct priv *p = ctx->hwdec_priv;
@@ -350,21 +387,31 @@ static void uninit(struct lavc_ctx *ctx)
return;
destroy_decoder(ctx);
-
va_surface_pool_release(p->pool);
+
+ if (p->x11_display)
+ destroy_va_dummy_ctx(p);
+
talloc_free(p);
ctx->hwdec_priv = NULL;
}
-static int init(struct lavc_ctx *ctx)
+static int init_with_vactx(struct lavc_ctx *ctx, struct mp_vaapi_ctx *vactx)
{
struct priv *p = talloc_ptrtype(NULL, p);
*p = (struct priv) {
- .ctx = ctx->hwdec_info->vaapi_ctx,
+ .ctx = vactx,
.va_context = &p->va_context_storage,
.rt_format = VA_RT_FORMAT_YUV420
};
+ if (!p->ctx)
+ create_va_dummy_ctx(p);
+ if (!p->ctx) {
+ talloc_free(p);
+ return -1;
+ }
+
p->display = p->ctx->display;
p->pool = va_surface_pool_alloc(p->display, p->rt_format);
@@ -378,6 +425,12 @@ static int init(struct lavc_ctx *ctx)
return 0;
}
+static int init(struct lavc_ctx *ctx)
+{
+ if (!ctx->hwdec_info->vaapi_ctx)
+ return -1;
+ return init_with_vactx(ctx, ctx->hwdec_info->vaapi_ctx);
+}
static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
const char *decoder)
@@ -389,6 +442,44 @@ static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
return 0;
}
+static int probe_copy(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
+ const char *decoder)
+{
+ struct priv dummy = {0};
+ if (!create_va_dummy_ctx(&dummy))
+ return HWDEC_ERR_NO_CTX;
+ destroy_va_dummy_ctx(&dummy);
+ if (!find_codec(mp_codec_to_av_codec_id(decoder)))
+ return HWDEC_ERR_NO_CODEC;
+ return 0;
+}
+
+static int init_copy(struct lavc_ctx *ctx)
+{
+ return init_with_vactx(ctx, NULL);
+}
+
+static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *img)
+{
+ struct priv *p = ctx->hwdec_priv;
+
+ struct va_surface *surface = va_surface_in_mp_image(img);
+ if (surface) {
+ struct mp_image *simg =
+ va_surface_download(surface, p->ctx->image_formats);
+ if (simg) {
+ if (!p->printed_readback_warning) {
+ mp_msg(MSGT_VO, MSGL_WARN, "[vaapi] Using GPU readback. This "
+ "is usually inefficient.\n");
+ p->printed_readback_warning = true;
+ }
+ talloc_free(img);
+ return simg;
+ }
+ }
+ return img;
+}
+
const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
.type = HWDEC_VAAPI,
.image_formats = (const int[]) {IMGFMT_VAAPI, IMGFMT_VAAPI_MPEG2_IDCT,
@@ -398,3 +489,14 @@ const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
.uninit = uninit,
.allocate_image = allocate_image,
};
+
+const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = {
+ .type = HWDEC_VAAPI_COPY,
+ .image_formats = (const int[]) {IMGFMT_VAAPI, IMGFMT_VAAPI_MPEG2_IDCT,
+ IMGFMT_VAAPI_MPEG2_MOCO, 0},
+ .probe = probe_copy,
+ .init = init_copy,
+ .uninit = uninit,
+ .allocate_image = allocate_image,
+ .process_image = copy_image,
+};
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index c658d92a35..7fbf9d8401 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -86,6 +86,7 @@ const struct vd_lavc_hwdec mp_vd_lavc_vdpau;
const struct vd_lavc_hwdec mp_vd_lavc_vdpau_old;
const struct vd_lavc_hwdec mp_vd_lavc_vda;
const struct vd_lavc_hwdec mp_vd_lavc_vaapi;
+const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy;
static const struct vd_lavc_hwdec mp_vd_lavc_crystalhd = {
.type = HWDEC_CRYSTALHD,
@@ -114,6 +115,7 @@ static const struct vd_lavc_hwdec *hwdec_list[] = {
&mp_vd_lavc_crystalhd,
#if CONFIG_VAAPI
&mp_vd_lavc_vaapi,
+ &mp_vd_lavc_vaapi_copy,
#endif
NULL
};