[vlc-devel] [PATCH 9/9] d3d11_deinterlace: merge 2 fields in a picture to deinterlace it
Steve Lhomme
robux4 at ycbcr.xyz
Mon Nov 16 13:44:20 CET 2020
---
modules/hw/d3d11/Makefile.am | 4 +-
modules/hw/d3d11/d3d11_deinterlace.c | 127 ++++++++++++++++++++++++++-
2 files changed, 127 insertions(+), 4 deletions(-)
diff --git a/modules/hw/d3d11/Makefile.am b/modules/hw/d3d11/Makefile.am
index a18e160faec..b305dcc5914 100644
--- a/modules/hw/d3d11/Makefile.am
+++ b/modules/hw/d3d11/Makefile.am
@@ -5,7 +5,9 @@ libdirect3d11_filters_plugin_la_SOURCES = hw/d3d11/d3d11_filters.h \
hw/d3d11/d3d11_deinterlace.c \
hw/d3d11/d3d11_device.c \
hw/d3d11/d3d11_surface.c \
- hw/d3d11/d3d11_processor.c hw/d3d11/d3d11_processor.h
+ hw/d3d11/d3d11_processor.c hw/d3d11/d3d11_processor.h \
+ video_output/win32/d3d11_quad.c video_output/win32/d3d11_quad.h \
+ video_output/win32/d3d11_shaders.c video_output/win32/d3d11_shaders.h
libdirect3d11_filters_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(d3d11dir)'
libdirect3d11_filters_plugin_la_LIBADD = libchroma_copy.la libdeinterlace_common.la libd3d11_common.la
if HAVE_WINSTORE
diff --git a/modules/hw/d3d11/d3d11_deinterlace.c b/modules/hw/d3d11/d3d11_deinterlace.c
index 0d7bc095b8a..c96e42a674e 100644
--- a/modules/hw/d3d11/d3d11_deinterlace.c
+++ b/modules/hw/d3d11/d3d11_deinterlace.c
@@ -38,6 +38,7 @@
#include "d3d11_processor.h"
#include "../../video_chroma/d3d11_fmt.h"
#include "../../video_filter/deinterlace/common.h"
+#include "../../video_output/win32/d3d11_quad.h"
typedef struct
{
@@ -46,6 +47,12 @@ typedef struct
struct deinterlace_ctx context;
const d3d_format_t *output_format;
+
+ // field merging
+ d3d_quad_t quadFieldFirst;
+ display_info_t display;
+ d3d11_shader_compiler_t shaders;
+ d3d_vertex_shader_t vshader;
} filter_sys_t;
struct filter_mode_t
@@ -219,15 +226,62 @@ picture_t *AllocPicture( filter_t *p_filter )
return pic;
}
+struct render_to_merged
+{
+ filter_sys_t *sys;
+ ID3D11RenderTargetView *renderTargets[D3D11_MAX_RENDER_TARGET];
+};
+
+static bool SelectRenderPlane(void *opaque, size_t plane_index)
+{
+ struct render_to_merged *render_output = opaque;
+ filter_sys_t *sys = render_output->sys;
+ if (unlikely(plane_index >= ARRAY_SIZE(render_output->renderTargets)))
+ return false;
+
+ ID3D11DeviceContext_OMSetRenderTargets(sys->d3d_dev->d3dcontext, 1,
+ &render_output->renderTargets[plane_index], NULL);
+ return true;
+}
+
void MergeFields( filter_t *p_filter, picture_t *merged, picture_t *fields[2])
{
- vlc_assert_unreachable(); // TODO add b_merge_fields support
+ filter_sys_t *sys = p_filter->p_sys;
+
+ struct render_to_merged render_output;
+ render_output.sys = sys;
+
+ picture_sys_d3d11_t *psys_merged = ActiveD3D11PictureSys(merged);
+ // TODO move this in AllocPicture
+ D3D11_CreateRenderTargets(sys->d3d_dev, psys_merged->resource[0], sys->output_format, render_output.renderTargets);
+ // D3D11_ClearRenderTargets(sys->d3d_dev, sys->output_format, render_output.renderTargets);
+
+ picture_sys_d3d11_t *psys_Field1 = ActiveD3D11PictureSys(fields[0]);
+ picture_sys_d3d11_t *psys_Field2 = ActiveD3D11PictureSys(fields[1]);
+ D3D11_RenderMergeQuad(sys->d3d_dev, &sys->vshader, &sys->quadFieldFirst,
+ psys_Field1->renderSrc, psys_Field2->renderSrc,
+ SelectRenderPlane, &render_output);
+
+ for ( size_t i = 0; i < ARRAY_SIZE( render_output.renderTargets ); i++ )
+ {
+ if ( !render_output.renderTargets[i] )
+ break;
+ ID3D11RenderTargetView_Release( render_output.renderTargets[i] );
+ }
}
static void D3D11CloseDeinterlace(filter_t *filter)
{
filter_sys_t *sys = filter->p_sys;
Flush(filter);
+
+ if ( sys->context.b_merge_fields )
+ {
+ D3D11_ReleaseQuad(&sys->quadFieldFirst);
+ D3D11_ReleaseVertexShader(&sys->vshader);
+ D3D11_ReleaseShaders(&sys->shaders);
+ }
+
D3D11_ReleaseProcessor( &sys->d3d_proc );
vlc_video_context_Release(filter->vctx_out);
@@ -272,6 +326,20 @@ int D3D11OpenDeinterlace(filter_t *filter)
if (unlikely(sys->output_format == NULL))
goto error;
+ InitDeinterlacingContext( &sys->context );
+
+ sys->context.b_merge_fields = filter->fmt_in.video.i_num_fields == 1;
+
+ video_format_t outfmt = filter->fmt_out.video;
+ if (sys->context.b_merge_fields)
+ {
+ outfmt.i_num_fields = 2;
+ outfmt.i_height *= 2;
+ outfmt.i_visible_height *= 2;
+ outfmt.i_y_offset *= 2;
+ outfmt.i_frame_rate /= 2; // we turn 2 pictures into 1
+ }
+
d3d11_device_lock(sys->d3d_dev);
if (D3D11_CreateProcessor(filter, sys->d3d_dev, D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST,
@@ -345,8 +413,6 @@ int D3D11OpenDeinterlace(filter_t *filter)
goto error;
}
- InitDeinterlacingContext( &sys->context );
-
sys->context.settings = p_mode->settings;
sys->context.settings.b_use_frame_history = rateCaps.PastFrames != 0 ||
rateCaps.FutureFrames != 0;
@@ -364,6 +430,61 @@ int D3D11OpenDeinterlace(filter_t *filter)
{
goto error;
}
+
+ if ( sys->context.b_merge_fields )
+ {
+ sys->quadFieldFirst.textureFormat = sys->output_format;
+ sys->quadFieldFirst.i_width = filter->fmt_in.video.i_width;
+ sys->quadFieldFirst.i_height = filter->fmt_in.video.i_height;
+
+ sys->display = (display_info_t) {
+ out_fmt.primaries,
+ out_fmt.transfer,
+ out_fmt.space,
+ out_fmt.color_range == COLOR_RANGE_FULL,
+ out_fmt.transfer == TRANSFER_FUNC_SMPTE_ST2084 ? MAX_PQ_BRIGHTNESS : DEFAULT_SRGB_BRIGHTNESS,
+ sys->output_format,
+ };
+
+ if (D3D11_AllocateQuad(filter, sys->d3d_dev, filter->fmt_in.video.projection_mode, &sys->quadFieldFirst) != VLC_SUCCESS)
+ {
+ msg_Err(filter, "Could not allocate quad buffers.");
+ goto error;
+ }
+ if (D3D11_SetupQuad( filter, sys->d3d_dev, &out_fmt, &sys->quadFieldFirst, &sys->display) != VLC_SUCCESS)
+ {
+ msg_Err(filter, "Could not Create the main quad picture.");
+ goto error;
+ }
+
+ D3D11_InitShaders(VLC_OBJECT(filter), &sys->shaders);
+
+ D3D11_CompilePixelShader(filter, &sys->shaders, sys->d3d_dev, false, 2,
+ &sys->display, true,
+ filter->fmt_in.video.transfer, filter->fmt_in.video.primaries, filter->fmt_in.video.color_range == COLOR_RANGE_FULL,
+ &sys->quadFieldFirst);
+
+ hr = D3D11_CompileFlatVertexShader(filter, &sys->shaders, sys->d3d_dev, &sys->vshader);
+ if (FAILED(hr))
+ goto error;
+
+ RECT source_rect;
+ source_rect.left = 0;
+ source_rect.top = 0;
+ source_rect.right = filter->fmt_in.video.i_width;
+ source_rect.bottom = filter->fmt_in.video.i_height;
+
+ RECT dst_rect;
+ dst_rect.left = 0;
+ dst_rect.top = 0;
+ dst_rect.right = out_fmt.i_width;
+ dst_rect.bottom = out_fmt.i_height;
+
+ D3D11_UpdateQuadPosition(filter, sys->d3d_dev, &sys->quadFieldFirst, &source_rect,
+ filter->fmt_in.video.orientation);
+ D3D11_UpdateViewport( &sys->quadFieldFirst, &dst_rect, sys->display.pixelFormat );
+ }
+
d3d11_device_unlock(sys->d3d_dev);
filter->fmt_out.video = out_fmt;
--
2.26.2
More information about the vlc-devel
mailing list