[vlc-devel] [PATCH] Enable DXVA2 deinterlacing frame doubling

Oliver Collyer ovcollyer at mac.com
Wed Jun 21 17:44:47 CEST 2017


(Sorry I don't think it worked with my attachment, inlining the patch this time)

The current DXVA2 deinterlacing module lacked the frame-doubling that gives interlaced sources proper smooth output, this patch addresses this.

It was also hardcoded to assume 1080i60 input frame rate, this version now correctly deduces the frame rate, taking inspiration from similar code in the software deinterlace.c.
---
 modules/video_output/win32/dxva2_deinterlace.c | 107 ++++++++++++++++++-------
 1 file changed, 77 insertions(+), 30 deletions(-)

diff --git a/modules/video_output/win32/dxva2_deinterlace.c b/modules/video_output/win32/dxva2_deinterlace.c
index b01e46b282..4aeaafe8a2 100644
--- a/modules/video_output/win32/dxva2_deinterlace.c
+++ b/modules/video_output/win32/dxva2_deinterlace.c
@@ -38,6 +38,13 @@
 #include <dxva2api.h>
 #include "../../video_chroma/d3d9_fmt.h"
 
+#define METADATA_SIZE 3
+
+typedef struct {
+    mtime_t pi_date[METADATA_SIZE];
+    int     pi_nb_fields[METADATA_SIZE];
+} metadata_history_t;
+
 struct filter_sys_t
 {
     HINSTANCE                      hdecoder_dll;
@@ -46,6 +53,7 @@ struct filter_sys_t
     IDirect3DDevice9               *d3ddev;
     IDirectXVideoProcessor         *processor;
     IDirect3DSurface9              *hw_surface;
+    metadata_history_t             meta;
 };
 
 static picture_t *Deinterlace(filter_t *filter, picture_t *src)
@@ -56,20 +64,35 @@ static picture_t *Deinterlace(filter_t *filter, picture_t *src)
     DXVA2_VideoSample sample = {0};
     D3DSURFACE_DESC dstDesc;
 
+    for (int i = 1; i < METADATA_SIZE; i ++) {
+        sys->meta.pi_date[i-1]      = sys->meta.pi_date[i];
+        sys->meta.pi_nb_fields[i-1] = sys->meta.pi_nb_fields[i];
+    }
+    sys->meta.pi_date[METADATA_SIZE-1]      = src->date;
+    sys->meta.pi_nb_fields[METADATA_SIZE-1] = src->i_nb_fields;
+
+    mtime_t i_field_dur = 0;
+    int i = 0;
+    for ( ; i < METADATA_SIZE-1; i ++)
+        if (sys->meta.pi_date[i] > VLC_TS_INVALID)
+            break;
+    if (i < METADATA_SIZE-1) {
+        int i_fields_total = 0;
+        for (int j = i; j < METADATA_SIZE-1; j ++)
+            i_fields_total += sys->meta.pi_nb_fields[j];
+        i_field_dur = (src->date - sys->meta.pi_date[i]) / i_fields_total;
+    }
+
     hr = IDirect3DSurface9_GetDesc( src->p_sys->surface, &dstDesc );
     if (FAILED(hr))
         return src; /* cannot deinterlace without copying fields */
 
-    picture_t *dst = filter_NewPicture(filter);
-    if (dst == NULL)
-        return src; /* cannot deinterlace without copying fields */
-
     sample.SrcSurface = src->p_sys->surface;
     sample.SampleFormat.SampleFormat = src->b_top_field_first ?
                 DXVA2_SampleFieldInterleavedEvenFirst :
                 DXVA2_SampleFieldInterleavedOddFirst;
     sample.Start = 0;
-    sample.End = sample.Start + 333666;
+    sample.End = sample.Start + i_field_dur * 20;
     sample.SampleData = DXVA2_SampleData_RFF_TFF_Present;
     if (src->b_top_field_first)
         sample.SampleData |= DXVA2_SampleData_TFF;
@@ -78,35 +101,53 @@ static picture_t *Deinterlace(filter_t *filter, picture_t *src)
     sample.DstRect        = sample.SrcRect;
     sample.PlanarAlpha    = DXVA2_Fixed32OpaqueAlpha();
 
-    params.TargetFrame = sample.Start;
-    params.TargetRect  = sample.DstRect;
-    params.DestData    = sample.SampleData;
-    params.Alpha       = DXVA2_Fixed32OpaqueAlpha();
-    params.DestFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
-    params.BackgroundColor.Alpha = 0xFFFF;
-
-    hr = IDirectXVideoProcessor_VideoProcessBlt( sys->processor,
-                                                 sys->hw_surface,
-                                                 &params,
-                                                 &sample,
-                                                 1, NULL );
-    if (FAILED(hr))
-        goto error;
+    picture_t *dst[2] = {NULL, NULL};
+    for (int i = 0; i < 2; i ++) {
+        dst[i] = filter_NewPicture(filter);
+        if (dst[i] == NULL)
+            goto error;
+        if (i)
+            dst[i-1]->p_next = dst[i];
+
+        params.TargetFrame = sample.Start + (sample.End - sample.Start) * i / 2;
+        params.TargetRect  = sample.DstRect;
+        params.DestData    = sample.SampleData;
+        params.Alpha       = DXVA2_Fixed32OpaqueAlpha();
+        params.DestFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
+        params.BackgroundColor.Alpha = 0xFFFF;
+
+        hr = IDirectXVideoProcessor_VideoProcessBlt( sys->processor,
+                                                     sys->hw_surface,
+                                                     &params,
+                                                     &sample,
+                                                     1, NULL );
+        if (FAILED(hr))
+            goto error;
+
+        hr = IDirect3DDevice9_StretchRect( sys->d3ddev,
+                                           sys->hw_surface, NULL,
+                                           dst[i]->p_sys->surface, NULL,
+                                           D3DTEXF_NONE);
+        if (FAILED(hr))
+            goto error;
+
+        picture_CopyProperties(dst[i], src);
+        dst[i]->b_progressive = true;
+        dst[i]->i_nb_fields = 1;
+    }
 
-    hr = IDirect3DDevice9_StretchRect( sys->d3ddev,
-                                       sys->hw_surface, NULL,
-                                       dst->p_sys->surface, NULL,
-                                       D3DTEXF_NONE);
-    if (FAILED(hr))
-        goto error;
+    dst[0]->date = src->date;
+    if (dst[0]->date > VLC_TS_INVALID)
+        dst[1]->date = dst[0]->date + i_field_dur;
+    else
+        dst[1]->date = VLC_TS_INVALID;
 
-    picture_CopyProperties(dst, src);
     picture_Release(src);
-    dst->b_progressive = true;
-    dst->i_nb_fields = 1;
-    return dst;
+    return dst[0];
 error:
-    picture_Release(dst);
+    for (int i = 0; i < 2; i ++)
+        if (dst[i])
+            picture_Release(dst[i]);
     return src;
 }
 
@@ -239,6 +280,12 @@ static int Open(vlc_object_t *obj)
 
     sys->hdecoder_dll = hdecoder_dll;
     sys->d3d9_dll     = d3d9_dll;
+
+    for (int i = 0; i < METADATA_SIZE; i ++) {
+        sys->meta.pi_date[i] = VLC_TS_INVALID;
+        sys->meta.pi_nb_fields[i] = 2;
+    }
+
     filter->pf_video_filter = Deinterlace;
     filter->p_sys = sys;
 
-- 
2.11.0



More information about the vlc-devel mailing list