[vlc-devel] [PATCH v1 08/33] deinterlace: add a filter callback using the video sink

Steve Lhomme robux4 at ycbcr.xyz
Fri Sep 25 16:46:44 CEST 2020


It's sending pictures with vlc_video_sink_PutPicture() rather than attaching
pictures to each other with vlc_picture_chain_AppendChain().

The old DoDeinterlacing() still works the same.
---
 modules/hw/d3d11/d3d11_deinterlace.c          | 11 ++++
 modules/hw/d3d9/dxva2_deinterlace.c           |  7 +++
 modules/video_filter/deinterlace/common.c     | 63 ++++++++++++++++---
 modules/video_filter/deinterlace/common.h     |  6 ++
 .../video_filter/deinterlace/deinterlace.c    |  7 +++
 5 files changed, 86 insertions(+), 8 deletions(-)

diff --git a/modules/hw/d3d11/d3d11_deinterlace.c b/modules/hw/d3d11/d3d11_deinterlace.c
index b2c8d99447a..333c4dfd498 100644
--- a/modules/hw/d3d11/d3d11_deinterlace.c
+++ b/modules/hw/d3d11/d3d11_deinterlace.c
@@ -174,6 +174,16 @@ static picture_t *Deinterlace(filter_t *p_filter, picture_t *p_pic)
     return res;
 }
 
+static int DeinterlaceInto(filter_t *p_filter, picture_t *p_pic, struct vlc_video_sink *sink)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+
+    d3d11_device_lock( p_sys->d3d_dev );
+    int res = DoDeinterlacingInto( p_filter, &p_sys->context, p_pic, sink );
+    d3d11_device_unlock( p_sys->d3d_dev );
+    return res;
+}
+
 static const struct filter_mode_t *GetFilterMode(const char *mode)
 {
     if ( mode == NULL || !strcmp( mode, "auto" ) )
@@ -351,6 +361,7 @@ int D3D11OpenDeinterlace(vlc_object_t *obj)
     filter->fmt_out.video   = out_fmt;
     filter->vctx_out        = vlc_video_context_Hold(filter->vctx_in);
     filter->pf_video_filter = Deinterlace;
+    filter->pf_video_filter_into = DeinterlaceInto;
     filter->pf_flush        = Flush;
     filter->p_sys = sys;
 
diff --git a/modules/hw/d3d9/dxva2_deinterlace.c b/modules/hw/d3d9/dxva2_deinterlace.c
index 7c0c4ec6920..cbc8398f821 100644
--- a/modules/hw/d3d9/dxva2_deinterlace.c
+++ b/modules/hw/d3d9/dxva2_deinterlace.c
@@ -268,6 +268,12 @@ static picture_t *Deinterlace(filter_t *p_filter, picture_t *p_pic)
     return DoDeinterlacing( p_filter, &p_sys->context, p_pic );
 }
 
+static int DeinterlaceInto(filter_t *p_filter, picture_t *p_pic, struct vlc_video_sink *sink)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    return DoDeinterlacingInto( p_filter, &p_sys->context, p_pic, sink );
+}
+
 static const struct filter_mode_t *GetFilterMode(const char *mode)
 {
     if ( mode == NULL || !strcmp( mode, "auto" ) )
@@ -502,6 +508,7 @@ int D3D9OpenDeinterlace(vlc_object_t *obj)
     filter->fmt_out.video   = out_fmt;
     filter->vctx_out        = vlc_video_context_Hold(filter->vctx_in);
     filter->pf_video_filter = Deinterlace;
+    filter->pf_video_filter_into = DeinterlaceInto;
     filter->pf_flush        = Flush;
     filter->p_sys = sys;
 
diff --git a/modules/video_filter/deinterlace/common.c b/modules/video_filter/deinterlace/common.c
index 94a6280e37e..955e88f1e2b 100644
--- a/modules/video_filter/deinterlace/common.c
+++ b/modules/video_filter/deinterlace/common.c
@@ -124,10 +124,10 @@ void GetDeinterlacingOutput( const struct deinterlace_ctx *p_context,
 
 #define CUSTOM_PTS -1
 
-picture_t *DoDeinterlacing( filter_t *p_filter,
-                            struct deinterlace_ctx *p_context, picture_t *p_pic )
+static int Deinterlace( filter_t *p_filter,
+                            struct deinterlace_ctx *p_context, picture_t *p_pic,
+                            picture_t *p_dst[DEINTERLACE_DST_SIZE] )
 {
-    picture_t *p_dst[DEINTERLACE_DST_SIZE];
     int i_double_rate_alloc_end;
     /* Remember the frame offset that we should use for this frame.
        The value in p_sys will be updated to reflect the correct value
@@ -142,7 +142,7 @@ picture_t *DoDeinterlacing( filter_t *p_filter,
     if( p_dst[0] == NULL )
     {
         picture_Release( p_pic );
-        return NULL;
+        return VLC_ENOMEM;
     }
     picture_CopyProperties( p_dst[0], p_pic );
 
@@ -236,7 +236,6 @@ picture_t *DoDeinterlacing( filter_t *p_filter,
             p_dst[i]           = AllocPicture( p_filter );
             if( p_dst[i] )
             {
-                vlc_picture_chain_AppendChain( p_dst[i-1], p_dst[i] );
                 picture_CopyProperties( p_dst[i], p_pic );
             }
             else
@@ -341,7 +340,7 @@ picture_t *DoDeinterlacing( filter_t *p_filter,
     }
 
     picture_Release( p_pic );
-    return p_dst[0];
+    return VLC_SUCCESS;
 
 drop:
     picture_Release( p_dst[0] );
@@ -352,8 +351,56 @@ drop:
     }
 #ifndef NDEBUG
     picture_Release( p_pic );
-    return NULL;
+    return VLC_EGENERIC;
 #else
-    return p_pic;
+    p_dst[0] = p_pic;
+    return VLC_SUCCESS;
 #endif
 }
+
+picture_t *DoDeinterlacing( filter_t *p_filter,
+                            struct deinterlace_ctx *p_context, picture_t *p_pic )
+{
+    picture_t *p_dst[DEINTERLACE_DST_SIZE];
+    int res = Deinterlace(p_filter, p_context, p_pic, p_dst);
+    if (res != VLC_SUCCESS)
+        return NULL;
+    if (p_dst[0])
+    {
+        // attach pictures consecutively
+        for (size_t i=1; p_dst[i] != NULL && i<ARRAY_SIZE(p_dst); i++)
+            vlc_picture_chain_AppendChain( p_dst[i-1], p_dst[i] );
+    }
+    return p_dst[0];
+}
+
+int DoDeinterlacingInto( filter_t *p_filter, struct deinterlace_ctx *p_context,
+                         picture_t *p_pic, struct vlc_video_sink *sink )
+{
+    picture_t *p_dst[DEINTERLACE_DST_SIZE];
+    int res = Deinterlace(p_filter, p_context, p_pic, p_dst);
+    if (res != VLC_SUCCESS)
+        return res;
+
+    // push picture(s) to the sink
+    for (size_t i=0; i<ARRAY_SIZE(p_dst); i++)
+    {
+        if (!p_dst[i])
+            break;
+        res = vlc_video_sink_PutPicture( sink, p_dst[i] );
+        if (unlikely(res != VLC_SUCCESS))
+        {
+            if (i == 0)
+                res = VLC_EGENERIC; // nothing was pushed
+            for (; i<ARRAY_SIZE(p_dst); i++)
+            {
+                if (p_dst[i])
+                {
+                    msg_Err(p_filter, "dropping filtered picture %zu", i);
+                    picture_Release( p_dst[i] );
+                }
+            }
+        }
+    }
+    return res;
+}
diff --git a/modules/video_filter/deinterlace/common.h b/modules/video_filter/deinterlace/common.h
index 144523647c2..ed989dd1a7d 100644
--- a/modules/video_filter/deinterlace/common.h
+++ b/modules/video_filter/deinterlace/common.h
@@ -117,6 +117,12 @@ void GetDeinterlacingOutput( const struct deinterlace_ctx *,
  */
 picture_t *DoDeinterlacing( filter_t *, struct deinterlace_ctx *, picture_t * );
 
+/**
+ * @brief Do the deinterlacing of the picture using pf_render_ordered() or pf_render_single_pic() calls.
+ * @return VLC_SUCCESS if pictures we pushed to the sink.
+ */
+int DoDeinterlacingInto( filter_t *, struct deinterlace_ctx *, picture_t *, struct vlc_video_sink * );
+
 /**
  * @brief Flush the deinterlacer context
  */
diff --git a/modules/video_filter/deinterlace/deinterlace.c b/modules/video_filter/deinterlace/deinterlace.c
index 1676a07f8ca..46ecf303e20 100644
--- a/modules/video_filter/deinterlace/deinterlace.c
+++ b/modules/video_filter/deinterlace/deinterlace.c
@@ -452,6 +452,12 @@ picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
     return DoDeinterlacing( p_filter, &p_sys->context, p_pic );
 }
 
+static int DeinterlaceInto(filter_t *p_filter, picture_t *p_pic, struct vlc_video_sink *sink)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    return DoDeinterlacingInto( p_filter, &p_sys->context, p_pic, sink );
+}
+
 /*****************************************************************************
  * Flush
  *****************************************************************************/
@@ -644,6 +650,7 @@ notsupp:
     p_filter->fmt_out.video = fmt;
     p_filter->fmt_out.i_codec = fmt.i_chroma;
     p_filter->pf_video_filter = Deinterlace;
+    p_filter->pf_video_filter_into = DeinterlaceInto;
     p_filter->pf_flush = Flush;
     p_filter->pf_video_mouse  = Mouse;
 
-- 
2.26.2



More information about the vlc-devel mailing list