[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