summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--player/command.c3
-rw-r--r--video/decode/d3d11va.c3
-rw-r--r--video/filter/vf.c21
-rw-r--r--video/filter/vf.h1
-rw-r--r--video/filter/vf_d3d11vpp.c114
-rw-r--r--video/img_format.c10
-rw-r--r--video/img_format.h12
-rw-r--r--video/out/opengl/hwdec.c2
-rw-r--r--video/out/opengl/hwdec_d3d11egl.c471
-rw-r--r--video/out/opengl/hwdec_d3d11eglrgb.c293
-rw-r--r--wscript_build.py1
11 files changed, 484 insertions, 447 deletions
diff --git a/player/command.c b/player/command.c
index ecd6252e26..6a45222558 100644
--- a/player/command.c
+++ b/player/command.c
@@ -2295,7 +2295,8 @@ static int probe_deint_filters(struct MPContext *mpctx)
if (check_output_format(mpctx, IMGFMT_VAAPI) &&
probe_deint_filter(mpctx, "vavpp"))
return 0;
- if (check_output_format(mpctx, IMGFMT_D3D11VA) &&
+ if ((check_output_format(mpctx, IMGFMT_D3D11VA) ||
+ check_output_format(mpctx, IMGFMT_D3D11NV12)) &&
probe_deint_filter(mpctx, "d3d11vpp"))
return 0;
if (probe_deint_filter(mpctx, "yadif"))
diff --git a/video/decode/d3d11va.c b/video/decode/d3d11va.c
index dd4535bdd7..8ce026bc96 100644
--- a/video/decode/d3d11va.c
+++ b/video/decode/d3d11va.c
@@ -195,6 +195,9 @@ static struct mp_image *d3d11va_update_image_attribs(struct lavc_ctx *s,
}
}
+ if (img->params.hw_subfmt == IMGFMT_NV12)
+ mp_image_setfmt(img, IMGFMT_D3D11NV12);
+
return img;
}
diff --git a/video/filter/vf.c b/video/filter/vf.c
index 9c741a4bfa..b59dcca76b 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -518,7 +518,23 @@ static void query_formats(uint8_t *fmts, struct vf_instance *vf)
static bool is_conv_filter(struct vf_instance *vf)
{
- return vf && strcmp(vf->info->name, "scale") == 0;
+ return vf && (strcmp(vf->info->name, "scale") == 0 || vf->autoinserted);
+}
+
+static const char *find_conv_filter(uint8_t *fmts_out)
+{
+ for (int n = 0; filter_list[n]; n++) {
+ if (filter_list[n]->test_conversion) {
+ for (int a = IMGFMT_START; a < IMGFMT_END; a++) {
+ for (int b = IMGFMT_START; b < IMGFMT_END; b++) {
+ if (fmts_out[b - IMGFMT_START] &&
+ filter_list[n]->test_conversion(a, b))
+ return filter_list[n]->name;
+ }
+ }
+ }
+ }
+ return "scale";
}
static void update_formats(struct vf_chain *c, struct vf_instance *vf,
@@ -539,7 +555,8 @@ static void update_formats(struct vf_chain *c, struct vf_instance *vf,
// filters after vf work, but vf can't output any format the filters
// after it accept), try to insert a conversion filter.
MP_INFO(c, "Using conversion filter.\n");
- struct vf_instance *conv = vf_open(c, "scale", NULL);
+ const char *filter = find_conv_filter(vf->last_outfmts);
+ struct vf_instance *conv = vf_open(c, filter, NULL);
if (conv) {
conv->autoinserted = true;
conv->next = vf->next;
diff --git a/video/filter/vf.h b/video/filter/vf.h
index 02f6f2c8fd..49296fb9b2 100644
--- a/video/filter/vf.h
+++ b/video/filter/vf.h
@@ -37,6 +37,7 @@ typedef struct vf_info {
const void *priv_defaults;
const struct m_option *options;
void (*print_help)(struct mp_log *log);
+ bool (*test_conversion)(int in, int out);
} vf_info_t;
typedef struct vf_instance {
diff --git a/video/filter/vf_d3d11vpp.c b/video/filter/vf_d3d11vpp.c
index 6b6441fecd..6647a615ec 100644
--- a/video/filter/vf_d3d11vpp.c
+++ b/video/filter/vf_d3d11vpp.c
@@ -42,7 +42,13 @@ struct vf_priv_s {
ID3D11VideoProcessorEnumerator *vp_enum;
D3D11_VIDEO_FRAME_FORMAT d3d_frame_format;
- struct mp_image_params params;
+ DXGI_FORMAT out_format;
+ bool out_shared;
+ bool out_rgb;
+
+ bool require_filtering;
+
+ struct mp_image_params params, out_params;
int c_w, c_h;
struct mp_image_pool *pool;
@@ -53,12 +59,6 @@ struct vf_priv_s {
int interlaced_only;
};
-struct d3d11va_surface {
- ID3D11Texture2D *texture;
- int subindex;
- ID3D11VideoDecoderOutputView *surface;
-};
-
static void release_tex(void *arg)
{
ID3D11Texture2D *texture = arg;
@@ -66,24 +66,25 @@ static void release_tex(void *arg)
ID3D11Texture2D_Release(texture);
}
-static struct mp_image *alloc_surface(ID3D11Device *dev, DXGI_FORMAT format,
- int hw_subfmt, int w, int h, bool shared)
+static struct mp_image *alloc_pool(void *pctx, int fmt, int w, int h)
{
+ struct vf_instance *vf = pctx;
+ struct vf_priv_s *p = vf->priv;
HRESULT hr;
ID3D11Texture2D *texture = NULL;
D3D11_TEXTURE2D_DESC texdesc = {
.Width = w,
.Height = h,
- .Format = format,
+ .Format = p->out_format,
.MipLevels = 1,
.ArraySize = 1,
.SampleDesc = { .Count = 1 },
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
- .MiscFlags = shared ? D3D11_RESOURCE_MISC_SHARED : 0,
+ .MiscFlags = p->out_shared ? D3D11_RESOURCE_MISC_SHARED : 0,
};
- hr = ID3D11Device_CreateTexture2D(dev, &texdesc, NULL, &texture);
+ hr = ID3D11Device_CreateTexture2D(p->vo_dev, &texdesc, NULL, &texture);
if (FAILED(hr))
return NULL;
@@ -91,9 +92,9 @@ static struct mp_image *alloc_surface(ID3D11Device *dev, DXGI_FORMAT format,
if (!mpi)
abort();
- mp_image_setfmt(mpi, IMGFMT_D3D11VA);
+ mp_image_setfmt(mpi, p->out_params.imgfmt);
mp_image_set_size(mpi, w, h);
- mpi->params.hw_subfmt = hw_subfmt;
+ mpi->params.hw_subfmt = p->out_params.hw_subfmt;
mpi->planes[1] = (void *)texture;
mpi->planes[2] = (void *)(intptr_t)0;
@@ -101,14 +102,6 @@ static struct mp_image *alloc_surface(ID3D11Device *dev, DXGI_FORMAT format,
return mpi;
}
-static struct mp_image *alloc_pool_nv12(void *pctx, int fmt, int w, int h)
-{
- ID3D11Device *dev = pctx;
- assert(fmt == IMGFMT_D3D11VA);
-
- return alloc_surface(dev, DXGI_FORMAT_NV12, IMGFMT_NV12, w, h, false);
-}
-
static void flush_frames(struct vf_instance *vf)
{
struct vf_priv_s *p = vf->priv;
@@ -149,7 +142,6 @@ static int recreate_video_proc(struct vf_instance *vf)
destroy_video_proc(vf);
- // Note: we skip any deinterlacing considerations for now.
D3D11_VIDEO_PROCESSOR_CONTENT_DESC vpdesc = {
.InputFrameFormat = p->d3d_frame_format,
.InputWidth = p->c_w,
@@ -221,9 +213,21 @@ static int recreate_video_proc(struct vf_instance *vf)
ID3D11VideoContext_VideoProcessorSetStreamColorSpace(p->video_ctx,
p->video_proc,
0, &csp);
- ID3D11VideoContext_VideoProcessorSetOutputColorSpace(p->video_ctx,
- p->video_proc,
- &csp);
+ if (p->out_rgb) {
+ if (p->params.colorspace != MP_CSP_BT_601 &&
+ p->params.colorspace != MP_CSP_BT_709)
+ {
+ MP_WARN(vf, "Unsupported video colorspace (%s/%s). Consider "
+ "disabling hardware decoding, or using "
+ "--hwdec=d3d11va-copy to get correct output.\n",
+ m_opt_choice_str(mp_csp_names, p->params.colorspace),
+ m_opt_choice_str(mp_csp_levels_names, p->params.colorlevels));
+ }
+ } else {
+ ID3D11VideoContext_VideoProcessorSetOutputColorSpace(p->video_ctx,
+ p->video_proc,
+ &csp);
+ }
return 0;
fail:
@@ -239,7 +243,7 @@ static int render(struct vf_instance *vf)
ID3D11VideoProcessorInputView *in_view = NULL;
ID3D11VideoProcessorOutputView *out_view = NULL;
struct mp_image *in = NULL, *out = NULL;
- out = mp_image_pool_get(p->pool, IMGFMT_D3D11VA, p->params.w, p->params.h);
+ out = mp_image_pool_get(p->pool, p->out_params.imgfmt, p->params.w, p->params.h);
if (!out)
goto cleanup;
@@ -323,6 +327,10 @@ static int render(struct vf_instance *vf)
goto cleanup;
}
+ // Make sure the texture is updated correctly on the shared context.
+ // (I'm not sure if this is correct, though it won't harm.)
+ ID3D11DeviceContext_Flush(p->device_ctx);
+
res = 0;
cleanup:
if (in_view)
@@ -338,7 +346,6 @@ cleanup:
return res;
}
-
static int filter_out(struct vf_instance *vf)
{
struct vf_priv_s *p = vf->priv;
@@ -347,7 +354,7 @@ static int filter_out(struct vf_instance *vf)
return 0;
// no filtering
- if (!mp_refqueue_should_deint(p->queue)) {
+ if (!mp_refqueue_should_deint(p->queue) && !p->require_filtering) {
struct mp_image *in = mp_refqueue_get(p->queue, 0);
vf_add_output_frame(vf, mp_image_new_ref(in));
mp_refqueue_next(p->queue);
@@ -368,16 +375,34 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
destroy_video_proc(vf);
+ *out = *in;
+
+ if (vf_next_query_format(vf, IMGFMT_D3D11VA) ||
+ vf_next_query_format(vf, IMGFMT_D3D11NV12))
+ {
+ out->imgfmt = vf_next_query_format(vf, IMGFMT_D3D11VA)
+ ? IMGFMT_D3D11VA : IMGFMT_D3D11NV12;
+ out->hw_subfmt = IMGFMT_NV12;
+ p->out_format = DXGI_FORMAT_NV12;
+ p->out_shared = false;
+ p->out_rgb = false;
+ } else {
+ out->imgfmt = IMGFMT_D3D11RGB;
+ out->hw_subfmt = IMGFMT_RGB0;
+ p->out_format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ p->out_shared = true;
+ p->out_rgb = true;
+ }
+
+ p->require_filtering = in->hw_subfmt != out->hw_subfmt;
+
p->params = *in;
+ p->out_params = *out;
p->pool = mp_image_pool_new(20);
- mp_image_pool_set_allocator(p->pool, alloc_pool_nv12, p->vo_dev);
+ mp_image_pool_set_allocator(p->pool, alloc_pool, vf);
mp_image_pool_set_lru(p->pool);
- *out = *in;
- out->imgfmt = IMGFMT_D3D11VA;
- out->hw_subfmt = IMGFMT_NV12;
-
return 0;
}
@@ -406,11 +431,27 @@ static void uninit(struct vf_instance *vf)
static int query_format(struct vf_instance *vf, unsigned int imgfmt)
{
- if (imgfmt == IMGFMT_D3D11VA)
- return vf_next_query_format(vf, IMGFMT_D3D11VA);
+ if (imgfmt == IMGFMT_D3D11VA ||
+ imgfmt == IMGFMT_D3D11NV12 ||
+ imgfmt == IMGFMT_D3D11RGB)
+ {
+ return vf_next_query_format(vf, IMGFMT_D3D11VA) ||
+ vf_next_query_format(vf, IMGFMT_D3D11NV12) ||
+ vf_next_query_format(vf, IMGFMT_D3D11RGB);
+ }
return 0;
}
+static bool test_conversion(int in, int out)
+{
+ return (in == IMGFMT_D3D11VA ||
+ in == IMGFMT_D3D11NV12 ||
+ in == IMGFMT_D3D11RGB) &&
+ (out == IMGFMT_D3D11VA ||
+ out == IMGFMT_D3D11NV12 ||
+ out == IMGFMT_D3D11RGB);
+}
+
static int control(struct vf_instance *vf, int request, void* data)
{
struct vf_priv_s *p = vf->priv;
@@ -480,6 +521,7 @@ static const m_option_t vf_opts_fields[] = {
const vf_info_t vf_info_d3d11vpp = {
.description = "D3D11 Video Post-Process Filter",
.name = "d3d11vpp",
+ .test_conversion = test_conversion,
.open = vf_open,
.priv_size = sizeof(struct vf_priv_s),
.priv_defaults = &(const struct vf_priv_s) {
diff --git a/video/img_format.c b/video/img_format.c
index fe2ca14bf4..24545a8501 100644
--- a/video/img_format.c
+++ b/video/img_format.c
@@ -36,6 +36,8 @@ struct mp_imgfmt_entry {
static const struct mp_imgfmt_entry mp_imgfmt_list[] = {
// not in ffmpeg
{"vdpau_output", IMGFMT_VDPAU_OUTPUT},
+ {"d3d11_nv12", IMGFMT_D3D11NV12},
+ {"d3d11_rgb", IMGFMT_D3D11RGB},
// FFmpeg names have an annoying "_vld" suffix
{"videotoolbox", IMGFMT_VIDEOTOOLBOX},
{"vaapi", IMGFMT_VAAPI},
@@ -120,12 +122,20 @@ static struct mp_imgfmt_desc mp_only_imgfmt_desc(int mpfmt)
{
switch (mpfmt) {
case IMGFMT_VDPAU_OUTPUT:
+ case IMGFMT_D3D11RGB:
return (struct mp_imgfmt_desc) {
.id = mpfmt,
.avformat = AV_PIX_FMT_NONE,
.flags = MP_IMGFLAG_BE | MP_IMGFLAG_LE | MP_IMGFLAG_RGB |
MP_IMGFLAG_HWACCEL,
};
+ case IMGFMT_D3D11NV12:
+ return (struct mp_imgfmt_desc) {
+ .id = mpfmt,
+ .avformat = AV_PIX_FMT_NONE,
+ .flags = MP_IMGFLAG_BE | MP_IMGFLAG_LE | MP_IMGFLAG_YUV |
+ MP_IMGFLAG_HWACCEL,
+ };
}
return (struct mp_imgfmt_desc) {0};
}
diff --git a/video/img_format.h b/video/img_format.h
index 73c06787b1..b6f5830b8a 100644
--- a/video/img_format.h
+++ b/video/img_format.h
@@ -198,7 +198,17 @@ enum mp_imgfmt {
IMGFMT_VDPAU, // VdpVideoSurface
IMGFMT_VDPAU_OUTPUT, // VdpOutputSurface
IMGFMT_VAAPI,
- IMGFMT_D3D11VA, // ID3D11VideoDecoderOutputView (NV12/P010/P016)
+ // NV12/P010/P016
+ // plane 1: ID3D11Texture2D
+ // plane 2: slice index casted to pointer
+ // plane 3: ID3D11VideoDecoderOutputView (can be absent in filters/VO)
+ IMGFMT_D3D11VA,
+ // Like IMGFMT_D3D11VA, but format is restricted to NV12.
+ IMGFMT_D3D11NV12,
+ // Like IMGFMT_D3D11VA, but format is restricted to a certain RGB format.
+ // Also, it must have a share handle, have been flushed, and not be a
+ // texture array slice.
+ IMGFMT_D3D11RGB,
IMGFMT_DXVA2, // IDirect3DSurface9 (NV12/P010/P016)
IMGFMT_MMAL, // MMAL_BUFFER_HEADER_T
IMGFMT_VIDEOTOOLBOX, // CVPixelBufferRef
diff --git a/video/out/opengl/hwdec.c b/video/out/opengl/hwdec.c
index fac0c3ff9a..8c8286119d 100644
--- a/video/out/opengl/hwdec.c
+++ b/video/out/opengl/hwdec.c
@@ -30,6 +30,7 @@ extern const struct gl_hwdec_driver gl_hwdec_videotoolbox;
extern const struct gl_hwdec_driver gl_hwdec_vdpau;
extern const struct gl_hwdec_driver gl_hwdec_dxva2egl;
extern const struct gl_hwdec_driver gl_hwdec_d3d11egl;
+extern const struct gl_hwdec_driver gl_hwdec_d3d11eglrgb;
extern const struct gl_hwdec_driver gl_hwdec_dxva2gldx;
extern const struct gl_hwdec_driver gl_hwdec_dxva2;
@@ -49,6 +50,7 @@ static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = {
#if HAVE_D3D_HWACCEL
#if HAVE_EGL_ANGLE
&gl_hwdec_d3d11egl,
+ &gl_hwdec_d3d11eglrgb,
&gl_hwdec_dxva2egl,
#endif
#if HAVE_GL_DXINTEROP
diff --git a/video/out/opengl/hwdec_d3d11egl.c b/video/out/opengl/hwdec_d3d11egl.c
index 1810105d5a..cd4a0f03d9 100644
--- a/video/out/opengl/hwdec_d3d11egl.c
+++ b/video/out/opengl/hwdec_d3d11egl.c
@@ -39,24 +39,9 @@ struct priv {
struct mp_hwdec_ctx hwctx;
ID3D11Device *d3d11_device;
- ID3D11DeviceContext *device_ctx;
- ID3D11VideoDevice *video_dev;
- ID3D11VideoContext *video_ctx;
-
EGLDisplay egl_display;
- EGLConfig egl_config;
- EGLSurface egl_surface;
-
- ID3D11Texture2D *texture;
- ID3D11VideoProcessor *video_proc;
- ID3D11VideoProcessorEnumerator *vp_enum;
- ID3D11VideoProcessorOutputView *out_view;
-
- struct mp_image_params image_params;
- int c_w, c_h;
EGLStreamKHR egl_stream;
-
GLuint gl_textures[3];
// EGL_KHR_stream
@@ -83,23 +68,6 @@ struct priv {
const EGLAttrib *attrib_list);
};
-static void destroy_video_proc(struct gl_hwdec *hw)
-{
- struct priv *p = hw->priv;
-
- if (p->out_view)
- ID3D11VideoProcessorOutputView_Release(p->out_view);
- p->out_view = NULL;
-
- if (p->video_proc)
- ID3D11VideoProcessor_Release(p->video_proc);
- p->video_proc = NULL;
-
- if (p->vp_enum)
- ID3D11VideoProcessorEnumerator_Release(p->vp_enum);
- p->vp_enum = NULL;
-}
-
static void destroy_objects(struct gl_hwdec *hw)
{
struct priv *p = hw->priv;
@@ -113,18 +81,6 @@ static void destroy_objects(struct gl_hwdec *hw)
gl->DeleteTextures(1, &p->gl_textures[n]);
p->gl_textures[n] = 0;
}
-
- if (p->egl_display && p->egl_surface) {
- eglReleaseTexImage(p->egl_display, p->egl_surface, EGL_BACK_BUFFER);
- eglDestroySurface(p->egl_display, p->egl_surface);
- }
- p->egl_surface = NULL;
-
- if (p->texture)
- ID3D11Texture2D_Release(p->texture);
- p->texture = NULL;
-
- destroy_video_proc(hw);
}
static void destroy(struct gl_hwdec *hw)
@@ -135,18 +91,6 @@ static void destroy(struct gl_hwdec *hw)
hwdec_devices_remove(hw->devs, &p->hwctx);
- if (p->video_ctx)
- ID3D11VideoContext_Release(p->video_ctx);
- p->video_ctx = NULL;
-
- if (p->video_dev)
- ID3D11VideoDevice_Release(p->video_dev);
- p->video_dev = NULL;
-
- if (p->device_ctx)
- ID3D11DeviceContext_Release(p->device_ctx);
- p->device_ctx = NULL;
-
if (p->d3d11_device)
ID3D11Device_Release(p->d3d11_device);
p->d3d11_device = NULL;
@@ -165,99 +109,70 @@ static int create(struct gl_hwdec *hw)
return -1;
const char *exts = eglQueryString(egl_display, EGL_EXTENSIONS);
- if (!exts || !strstr(exts, "EGL_ANGLE_d3d_share_handle_client_buffer"))
+ if (!exts || !strstr(exts, "EGL_ANGLE_d3d_share_handle_client_buffer") ||
+ !strstr(exts, "EGL_ANGLE_stream_producer_d3d_texture_nv12") ||
+ !(strstr(hw->gl->extensions, "GL_OES_EGL_image_external_essl3") ||
+ hw->gl->es == 200) ||
+ !strstr(exts, "EGL_EXT_device_query"))
return -1;
- bool use_native_device = !!strstr(exts, "EGL_EXT_device_query");
-
HRESULT hr;
struct priv *p = talloc_zero(hw, struct priv);
hw->priv = p;
p->egl_display = egl_display;
- // Optional EGLStream stuff for working without video processor.
- if (strstr(exts, "EGL_ANGLE_stream_producer_d3d_texture_nv12") &&
- use_native_device &&
- (strstr(hw->gl->extensions, "GL_OES_EGL_image_external_essl3") ||
- hw->gl->es == 200))
+ p->CreateStreamKHR = (void *)eglGetProcAddress("eglCreateStreamKHR");
+ p->DestroyStreamKHR = (void *)eglGetProcAddress("eglDestroyStreamKHR");
+ p->StreamConsumerAcquireKHR =
+ (void *)eglGetProcAddress("eglStreamConsumerAcquireKHR");
+ p->StreamConsumerReleaseKHR =
+ (void *)eglGetProcAddress("eglStreamConsumerReleaseKHR");
+ p->StreamConsumerGLTextureExternalAttribsNV =
+ (void *)eglGetProcAddress("eglStreamConsumerGLTextureExternalAttribsNV");
+ p->CreateStreamProducerD3DTextureNV12ANGLE =
+ (void *)eglGetProcAddress("eglCreateStreamProducerD3DTextureNV12ANGLE");
+ p->StreamPostD3DTextureNV12ANGLE =
+ (void *)eglGetProcAddress("eglStreamPostD3DTextureNV12ANGLE");
+
+ if (!p->CreateStreamKHR || !p->DestroyStreamKHR ||
+ !p->StreamConsumerAcquireKHR || !p->StreamConsumerReleaseKHR ||
+ !p->StreamConsumerGLTextureExternalAttribsNV ||
+ !p->CreateStreamProducerD3DTextureNV12ANGLE ||
+ !p->StreamPostD3DTextureNV12ANGLE)
{
- MP_VERBOSE(hw, "Loading EGL_ANGLE_stream_producer_d3d_texture_nv12\n");
-
- p->CreateStreamKHR = (void *)eglGetProcAddress("eglCreateStreamKHR");
- p->DestroyStreamKHR = (void *)eglGetProcAddress("eglDestroyStreamKHR");
- p->StreamConsumerAcquireKHR =
- (void *)eglGetProcAddress("eglStreamConsumerAcquireKHR");
- p->StreamConsumerReleaseKHR =
- (void *)eglGetProcAddress("eglStreamConsumerReleaseKHR");
- p->StreamConsumerGLTextureExternalAttribsNV =
- (void *)eglGetProcAddress("eglStreamConsumerGLTextureExternalAttribsNV");
- p->CreateStreamProducerD3DTextureNV12ANGLE =
- (void *)eglGetProcAddress("eglCreateStreamProducerD3DTextureNV12ANGLE");
- p->StreamPostD3DTextureNV12ANGLE =
- (void *)eglGetProcAddress("eglStreamPostD3DTextureNV12ANGLE");
-
- if (!p->CreateStreamKHR || !p->DestroyStreamKHR ||
- !p->StreamConsumerAcquireKHR || !p->StreamConsumerReleaseKHR ||
- !p->StreamConsumerGLTextureExternalAttribsNV ||
- !p->CreateStreamProducerD3DTextureNV12ANGLE ||
- !p->StreamPostD3DTextureNV12ANGLE)
- {
- MP_ERR(hw, "Failed to load some EGLStream functions.\n");
- goto fail;
- }
-
- static const char *es2_exts[] = {"GL_NV_EGL_stream_consumer_external", 0};
- static const char *es3_exts[] = {"GL_NV_EGL_stream_consumer_external",
- "GL_OES_EGL_image_external_essl3", 0};
- hw->glsl_extensions = hw->gl->es == 200 ? es2_exts : es3_exts;
+ MP_ERR(hw, "Failed to load some EGLStream functions.\n");
+ goto fail;
}
- if (use_native_device) {
- PFNEGLQUERYDISPLAYATTRIBEXTPROC p_eglQueryDisplayAttribEXT =
- (void *)eglGetProcAddress("eglQueryDisplayAttribEXT");
- PFNEGLQUERYDEVICEATTRIBEXTPROC p_eglQueryDeviceAttribEXT =
- (void *)eglGetProcAddress("eglQueryDeviceAttribEXT");
- if (!p_eglQueryDisplayAttribEXT || !p_eglQueryDeviceAttribEXT)
- goto fail;
-
- EGLAttrib device = 0;
- if (!p_eglQueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &device))
- goto fail;
- EGLAttrib d3d_device = 0;
- if (!p_eglQueryDeviceAttribEXT((EGLDeviceEXT)device,
- EGL_D3D11_DEVICE_ANGLE, &d3d_device))
- {
- MP_ERR(hw, "Could not get EGL_D3D11_DEVICE_ANGLE from ANGLE.\n");
- goto fail;
- }
-
- p->d3d11_device = (ID3D11Device *)d3d_device;
- if (!p->d3d11_device)
- goto fail;
- ID3D11Device_AddRef(p->d3d11_device);
- } else {
- HANDLE d3d11_dll = GetModuleHandleW(L"d3d11.dll");
- if (!d3d11_dll) {
- MP_ERR(hw, "Failed to load D3D11 library\n");
- goto fail;
- }
-
- PFN_D3D11_CREATE_DEVICE CreateDevice =
- (void *)GetProcAddress(d3d11_dll, "D3D11CreateDevice");
- if (!CreateDevice)
- goto fail;
-
- hr = CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
- D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0,
- D3D11_SDK_VERSION, &p->d3d11_device, NULL, NULL);
- if (FAILED(hr)) {
- MP_ERR(hw, "Failed to create D3D11 Device: %s\n",
- mp_HRESULT_to_str(hr));
- goto fail;
- }
+ static const char *es2_exts[] = {"GL_NV_EGL_stream_consumer_external", 0};
+ static const char *es3_exts[] = {"GL_NV_EGL_stream_consumer_external",
+ "GL_OES_EGL_image_external_essl3", 0};
+ hw->glsl_extensions = hw->gl->es == 200 ? es2_exts : es3_exts;
+
+ PFNEGLQUERYDISPLAYATTRIBEXTPROC p_eglQueryDisplayAttribEXT =
+ (void *)eglGetProcAddress("eglQueryDisplayAttribEXT");
+ PFNEGLQUERYDEVICEATTRIBEXTPROC p_eglQueryDeviceAttribEXT =
+ (void *)eglGetProcAddress("eglQueryDeviceAttribEXT");
+ if (!p_eglQueryDisplayAttribEXT || !p_eglQueryDeviceAttribEXT)
+ goto fail;
+
+ EGLAttrib device = 0;
+ if (!p_eglQueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &device))
+ goto fail;
+ EGLAttrib d3d_device = 0;
+ if (!p_eglQueryDeviceAttribEXT((EGLDeviceEXT)device,
+ EGL_D3D11_DEVICE_ANGLE, &d3d_device))
+ {
+ MP_ERR(hw, "Could not get EGL_D3D11_DEVICE_ANGLE from ANGLE.\n");
+ goto fail;
}
+ p->d3d11_device = (ID3D11Device *)d3d_device;
+ if (!p->d3d11_device)
+ goto fail;
+ ID3D11Device_AddRef(p->d3d11_device);
+
ID3D10Multithread *multithread;
hr = ID3D11Device_QueryInterface(p->d3d11_device, &IID_ID3D10Multithread,
(void **)&multithread);
@@ -270,36 +185,6 @@ static int create(struct gl_hwdec *hw)
ID3D10Multithread_SetMultithreadProtected(multithread, TRUE);
ID3D10Multithread_Release(multithread);
- hr = ID3D11Device_QueryInterface(p->d3d11_device, &IID_ID3D11VideoDevice,
- (void **)&p->video_dev);
- if (FAILED(hr))
- goto fail;
-
- ID3D11Device_GetImmediateContext(p->d3d11_device, &p->device_ctx);
- if (!p->device_ctx)
- goto fail;
- hr = ID3D11DeviceContext_QueryInterface(p->device_ctx, &IID_ID3D11VideoContext,
- (void **)&p->video_ctx);
- if (FAILED(hr))
- goto fail;
-
- EGLint attrs[] = {
- EGL_BUFFER_SIZE, 32,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_ALPHA_SIZE, 8,
- EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
- EGL_NONE
- };
- EGLint count;
- if (!eglChooseConfig(p->egl_display, attrs, &p->egl_config, 1, &count) ||
- !count) {
- MP_ERR(hw, "Failed to get EGL surface configuration\n");
- goto fail;
- }
-
p->hwctx = (struct mp_hwdec_ctx){
.type = HWDEC_D3D11VA,
.driver_name = hw->driver->name,
@@ -313,18 +198,17 @@ fail:
return -1;
}
-static int create_egl_stream(struct gl_hwdec *hw, struct mp_image_params *params)
+static int reinit(struct gl_hwdec *hw, struct mp_image_params *params)
{
struct priv *p = hw->priv;
GL *gl = hw->gl;
- if (params->hw_subfmt != IMGFMT_NV12)
- return -1;
-
- if (!p->CreateStreamKHR)
- return -1; // extensions not available
+ destroy_objects(hw);
- MP_VERBOSE(hw, "Using EGL_KHR_stream path.\n");
+ if (params->hw_subfmt != IMGFMT_NV12) {
+ MP_FATAL(hw, "Format not supported.\n");
+ return -1;
+ }
// Hope that the given texture unit range is not "in use" by anything.
// The texture units need to be bound during init only, and are free for
@@ -380,227 +264,18 @@ fail:
return -1;
}
-static int reinit(struct gl_hwdec *hw, struct mp_image_params *params)
-{
- struct priv *p = hw->priv;
- GL *gl = hw->gl;
- HRESULT hr;
-
- destroy_objects(hw);
-
- p->image_params = *params;
-
- // If this does not work, use the video process instead.
- if (create_egl_stream(hw, params) >= 0)
- return 0;
-
- MP_VERBOSE(hw, "Using ID3D11VideoProcessor path.\n");
-
- D3D11_TEXTURE2D_DESC texdesc = {
- .Width = params->w,
- .Height = params->h,
- .Format = DXGI_FORMAT_B8G8R8A8_UNORM,
- .MipLevels = 1,
- .ArraySize = 1,
- .SampleDesc = { .Count = 1 },
- .Usage = D3D11_USAGE_DEFAULT,
- .BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
- .MiscFlags = D3D11_RESOURCE_MISC_SHARED,
- };
- hr = ID3D11Device_CreateTexture2D(p->d3d11_device, &texdesc, NULL, &p->texture);
- if (FAILED(hr)) {
- MP_ERR(hw, "Failed to create texture: %s\n", mp_HRESULT_to_str(hr));
- goto fail;
- }
-
- HANDLE share_handle = NULL;
- IDXGIResource *res;
-
- hr = IUnknown_QueryInterface(p->texture, &IID_IDXGIResource, (void **)&res);
- if (FAILED(hr))
- goto fail;
-
- hr = IDXGIResource_GetSharedHandle(res, &share_handle);
- if (FAILED(hr))
- share_handle = NULL;
-
- IDXGIResource_Release(res);
-
- if (!share_handle)
- goto fail;
-
- EGLint attrib_list[] = {
- EGL_WIDTH, params->w,
- EGL_HEIGHT, params->h,
- EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
- EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
- EGL_NONE
- };
- p->egl_surface = eglCreatePbufferFromClientBuffer(
- p->egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
- share_handle, p->egl_config, attrib_list);
- if (p->egl_surface == EGL_NO_SURFACE) {
- MP_ERR(hw, "Failed to create EGL surface\n");
- goto fail;
- }
-
- gl->GenTextures(1, &p->gl_textures[0]);
- gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[0]);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- eglBindTexImage(p->egl_display, p->egl_surface, EGL_BACK_BUFFER);
- gl->BindTexture(GL_TEXTURE_2D, 0);
-
- params->imgfmt = IMGFMT_RGB0;
- return 0;
-fail:
- destroy_objects(hw);
- return -1;
-}
-
-static int create_video_proc(struct gl_hwdec *hw, struct mp_image_params *params)
-{
- struct priv *p = hw->priv;
- HRESULT hr;
-
- destroy_video_proc(hw);
-
- // Note: we skip any deinterlacing considerations for now.
- D3D11_VIDEO_PROCESSOR_CONTENT_DESC vpdesc = {
- .InputWidth = p->c_w,
- .InputHeight = p->c_h,
- .OutputWidth = params->w,
- .OutputHeight = params->h,
- };
- hr = ID3D11VideoDevice_CreateVideoProcessorEnumerator(p->video_dev, &vpdesc,
- &p->vp_enum);
- if (FAILED(hr))
- goto fail;
-
- // Assume RateConversionIndex==0 always works fine for us.
- hr = ID3D11VideoDevice_CreateVideoProcessor(p->video_dev, p->vp_enum, 0,
- &p->video_proc);
- if (FAILED(hr)) {
- MP_ERR(hw, "Failed to create D3D11 video processor.\n");
- goto fail;
- }
-
- D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outdesc = {
- .ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D,
- };
- hr = ID3D11VideoDevice_CreateVideoProcessorOutputView(p->video_dev,
- (ID3D11Resource *)p->texture,
- p->vp_enum, &outdesc,
- &p->out_view);
- if (FAILED(hr))
- goto fail;
-
- // Note: libavcodec does not support cropping left/top with hwaccel.
- RECT src_rc = {
- .right = params->w,
- .bottom = params->h,
- };
- ID3D11VideoContext_VideoProcessorSetStreamSourceRect(p->video_ctx,
- p->video_proc,
- 0, TRUE, &src_rc);
-
- // This is supposed to stop drivers from fucking up the video quality.
- ID3D11VideoContext_VideoProcessorSetStreamAutoProcessingMode(p->video_ctx,
- p->video_proc,
- 0, FALSE);
-
- if (params->colorspace != MP_CSP_BT_601 &&
- params->colorspace != MP_CSP_BT_709)
- {
- MP_WARN(hw, "Unsupported video colorspace (%s/%s). Consider disabling "
- "hardware decoding, or using --hwdec=d3d11va-copy to get "
- "correct output.\n",
- m_opt_choice_str(mp_csp_names, params->colorspace),
- m_opt_choice_str(mp_csp_levels_names, params->colorlevels));
- }
-
- D3D11_VIDEO_PROCESSOR_COLOR_SPACE csp = {
- .YCbCr_Matrix = params->colorspace != MP_CSP_BT_601,
- .Nominal_Range = params->colorlevels == MP_CSP_LEVELS_TV ? 1 : 2,
- };
- ID3D11VideoContext_VideoProcessorSetStreamColorSpace(p->video_ctx,
- p->video_proc,
- 0, &csp);
-
- return 0;
-fail:
- destroy_video_proc(hw);
- return -1;
-}
-
-static int map_frame_video_proc(struct gl_hwdec *hw, ID3D11Texture2D *d3d_tex,
- int d3d_subindex, struct gl_hwdec_frame *out_frame)
+static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image,
+ struct gl_hwdec_frame *out_frame)
{
struct priv *p = hw->priv;
- HRESULT hr;
- ID3D11VideoProcessorInputView *in_view = NULL;
- D3D11_TEXTURE2D_DESC texdesc;
- ID3D11Texture2D_GetDesc(d3d_tex, &texdesc);
- if (!p->video_proc || p->c_w != texdesc.Width || p->c_h != texdesc.Height) {
- p->c_w = texdesc.Width;
- p->c_h = texdesc.Height;
- if (create_video_proc(hw, &p->image_params) < 0)
- return -1;
- }
-
- D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC indesc = {
- .FourCC = 0, // huh?
- .ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D,
- .Texture2D = {
- .ArraySlice = d3d_subindex,
- },
- };
- hr = ID3D11VideoDevice_CreateVideoProcessorInputView(p->video_dev,
- (ID3D11Resource *)d3d_tex,
- p->vp_enum, &indesc,
- &in_view);
<