[vlc-devel] [PATCH 10/19] vdpau: implement draining of extra pictures in deinterlacer

Steve Lhomme robux4 at ycbcr.xyz
Tue Oct 13 15:51:53 CEST 2020


We no longer return pictures chained using vlc_picture_chain_AppendChain().

The original code was returning the source picture, with a few metadata changed
and a secondary picture attached.

The secondary picture, with a different date, is prepared during the drain. We
keep a reference to the primary picture while waiting for the drain. This kept
picture is released during a Flush or on Close.

The last_pts that was used locally when chaining picture is kept as
prev_last_pts to generate the secondary picture(s) during the drain.
---
 modules/hw/vdpau/deinterlace.c | 62 ++++++++++++++++++++++++----------
 1 file changed, 44 insertions(+), 18 deletions(-)

diff --git a/modules/hw/vdpau/deinterlace.c b/modules/hw/vdpau/deinterlace.c
index 842110c87aa..90a473aabcc 100644
--- a/modules/hw/vdpau/deinterlace.c
+++ b/modules/hw/vdpau/deinterlace.c
@@ -34,12 +34,14 @@
 typedef struct
 {
     vlc_tick_t last_pts;
+    vlc_tick_t prev_last_pts;
+    picture_t  *last_pic;
 } filter_sys_t;
 
 static picture_t *Deinterlace(filter_t *filter, picture_t *src)
 {
     filter_sys_t *sys = filter->p_sys;
-    vlc_tick_t last_pts = sys->last_pts;
+    sys->prev_last_pts = sys->last_pts;
 
     sys->last_pts = src->date;
 
@@ -49,66 +51,89 @@ static picture_t *Deinterlace(filter_t *filter, picture_t *src)
     if (f1->structure != VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
         return src; /* cannot deinterlace twice */
 
+    sys->last_pic = picture_Hold(src);
+
+    src->i_nb_fields = 1;
+
+    if (src->b_progressive || src->b_top_field_first)
+        f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
+    else
+        f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
+
+    dst->b_progressive = true;
+    return src;
+}
+
+static picture_t *Drain(filter_t *filter)
+{
+    filter_sys_t *sys = filter->p_sys;
+    if (sys->last_pic == NULL) // second drain call
+        return NULL;
+
+    const picture_t *src = sys->last_pic;
+    vlc_vdp_video_field_t *f1 = VDPAU_FIELD_FROM_PICCTX(src->context);
 #ifdef VOUT_CORE_GETS_A_CLUE
     picture_t *dst = filter_NewPicture(filter);
 #else
     picture_t *dst = picture_NewFromFormat(&src->format);
 #endif
     if (dst == NULL)
-        return src; /* cannot deinterlace without copying fields */
+        goto error; /* cannot deinterlace without copying fields */
 
     vlc_vdp_video_field_t *f2 = vlc_vdp_video_copy(f1); // shallow copy
     if (unlikely(f2 == NULL))
     {
         picture_Release(dst);
-        return src;
+        dst = NULL;
+        goto error;
     }
 
     picture_CopyProperties(dst, src);
     dst->context = &f2->context;
 
-    if (last_pts != VLC_TICK_INVALID)
-        dst->date = (3 * src->date - last_pts) / 2;
+    if (sys->prev_last_pts != VLC_TICK_INVALID)
+        dst->date = (3 * src->date - sys->prev_last_pts) / 2;
     else
     if (filter->fmt_in.video.i_frame_rate != 0)
         dst->date = src->date + vlc_tick_from_samples(filter->fmt_in.video.i_frame_rate_base
                             ,filter->fmt_in.video.i_frame_rate);
     dst->b_top_field_first = !src->b_top_field_first;
     dst->i_nb_fields = 1;
-    src->i_nb_fields = 1;
-
-    assert(!picture_HasChainedPics(src));
-    vlc_picture_chain_AppendChain( src, dst );
 
     if (src->b_progressive || src->b_top_field_first)
-    {
-        f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
         f2->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
-    }
     else
-    {
-        f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
         f2->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
-    }
 
-    src->b_progressive = true;
     dst->b_progressive = true;
-    return src;
+
+error :
+    picture_Release(sys->last_pic);
+    sys->last_pic = NULL;
+    return dst;
 }
 
 static void Flush(filter_t *filter)
 {
     filter_sys_t *sys = filter->p_sys;
+    if (sys->last_pic)
+    {
+        picture_Release(sys->last_pic);
+        sys->last_pic = NULL;
+    }
     sys->last_pts = VLC_TICK_INVALID;
+    sys->prev_last_pts = VLC_TICK_INVALID;
 }
 
 static void Close(filter_t *filter)
 {
+    filter_sys_t *sys = filter->p_sys;
+    Flush(filter);
     vlc_video_context_Release(filter->vctx_out);
 }
 
 static const struct vlc_filter_operations filter_ops = {
-    .filter_video = Deinterlace, .close = Close,
+    .filter_video = Deinterlace, .drain_video = Drain, .close = Close,
     .flush = Flush,
 };
 
@@ -132,6 +157,7 @@ static int Open(filter_t *filter)
      * The other modes and IVTC should be checked. */
 
     sys->last_pts = VLC_TICK_INVALID;
+    sys->prev_last_pts = VLC_TICK_INVALID;
 
     filter->ops = &filter_ops;
     filter->p_sys = sys;
-- 
2.26.2



More information about the vlc-devel mailing list