summaryrefslogtreecommitdiffstats
path: root/video/filter/vf_d3d11vpp.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/filter/vf_d3d11vpp.c')
-rw-r--r--video/filter/vf_d3d11vpp.c114
1 files changed, 78 insertions, 36 deletions
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) {