[vlc-devel] [PATCH v2 10/20] vaapi: implement draining of extra pictures in x2 deinterlacer

Steve Lhomme robux4 at ycbcr.xyz
Wed Oct 14 14:39:10 CEST 2020


The picture used to create secondary pictures (cur) is kept as long as pictures
are produced by the drain. It comes from the picture history so it will be
released from there.

cur_frame was either 0 (primary output) or 1 (secondary output). The value is
used the same way in the filter and drain functions.

The i_field_dur duration shift is only done for the drained picture.

We no longer return pictures chained using vlc_picture_chain_AppendChain().
---
 modules/hw/vaapi/filters.c | 106 ++++++++++++++++++++++++-------------
 1 file changed, 69 insertions(+), 37 deletions(-)

diff --git a/modules/hw/vaapi/filters.c b/modules/hw/vaapi/filters.c
index bd933ac8c63..b4af91cfdaf 100644
--- a/modules/hw/vaapi/filters.c
+++ b/modules/hw/vaapi/filters.c
@@ -51,6 +51,10 @@ typedef struct
     struct va_filter_desc       va;
     picture_pool_t *            dest_pics;
     bool                        b_pipeline_fast;
+
+    picture_t *                 cur; // X2 Deinterlacer
+    vlc_tick_t                  src_date;
+
     void *                      p_data;
 } filter_sys_t;
 
@@ -308,6 +312,7 @@ Open(filter_t * filter,
         return VLC_ENOMEM;
     filter->p_sys = filter_sys;
 
+    filter_sys->cur    = NULL;
     filter_sys->p_data = p_data;
 
     filter_sys->va.conf = VA_INVALID_ID;
@@ -764,7 +769,7 @@ Deinterlace_UpdateHistory(struct deint_data * p_deint_data, picture_t * src)
     }
     p_deint_data->history.pp_pics[p_deint_data->history.num_pics++] = src;
 
-    return *p_deint_data->history.pp_cur_pic;
+    return p_deint_data->history.pp_cur_pic[0];
 }
 
 static void
@@ -844,7 +849,6 @@ DeinterlaceX2(filter_t * filter, picture_t * src)
 {
     filter_sys_t *const         filter_sys = filter->p_sys;
     struct deint_data *const    p_deint_data = filter_sys->p_data;
-    const video_format_t *      fmt = &filter->fmt_out.video;
 
     /* TODO: could use the meta array and calculation from deinterlace/common
        but then it would also be appropriate to use the picture history array
@@ -854,53 +858,75 @@ DeinterlaceX2(filter_t * filter, picture_t * src)
     p_deint_data->meta[METADATA_SIZE-1].date        = src->date;
     p_deint_data->meta[METADATA_SIZE-1].i_nb_fields = src->i_nb_fields;
 
-    picture_t * cur = Deinterlace_UpdateHistory(p_deint_data, src);
+    filter_sys->cur = Deinterlace_UpdateHistory(p_deint_data, src);
     if (p_deint_data->history.num_pics < p_deint_data->history.sz)
         return NULL;
 
-    vlc_tick_t i_field_dur = 0;
-    unsigned int i = 0;
-    for ( ; i < METADATA_SIZE-1; i ++)
-        if (p_deint_data->meta[i].date != VLC_TICK_INVALID)
-            break;
-    if (i < METADATA_SIZE-1) {
-        unsigned int i_fields_total = 0;
-        for (unsigned int j = i; j < METADATA_SIZE-1; ++j)
-            i_fields_total += p_deint_data->meta[j].i_nb_fields;
-        i_field_dur = (src->date - p_deint_data->meta[i].date) / i_fields_total;
-    }
-    else if (fmt->i_frame_rate_base)
-        i_field_dur = vlc_tick_from_samples(fmt->i_frame_rate_base, fmt->i_frame_rate);
-
-    picture_t *dest[2] = {NULL, NULL};
-    for (i = 0; i < 2; ++i)
-    {
-        p_deint_data->cur_frame = i;
-        dest[i] = Filter(filter, cur,
+    p_deint_data->cur_frame = 0;
+    picture_t *dest = Filter(filter, filter_sys->cur,
                          Deinterlace_UpdateFilterParams,
                          Deinterlace_UpdateReferenceFrames,
                          Deinterlace_UpdatePipelineParams);
-        if (!dest[i])
-           goto error;
+    if (!dest)
+        goto error;
 
-        dest[i]->b_progressive = true;
-        dest[i]->i_nb_fields = 1;
-    }
+    dest->b_progressive = true;
+    dest->i_nb_fields = 1;
 
-    vlc_picture_chain_AppendChain( dest[0], dest[1] );
-    dest[0]->date = cur->date;
-    if (dest[0]->date != VLC_TICK_INVALID)
-        dest[1]->date = dest[0]->date + i_field_dur;
-    else
-        dest[1]->date = VLC_TICK_INVALID;
+    dest->date = filter_sys->cur->date;
+    filter_sys->src_date = src->date;
 
-    return dest[0];
+    return dest;
 
 error:
-    for (i = 0; i < 2; ++i)
-        if (dest[i])
-            picture_Release(dest[i]);
+    filter_sys->cur = NULL;
+    return NULL;
+}
 
+static picture_t *DrainX2(filter_t *filter)
+{
+    filter_sys_t *const         filter_sys = filter->p_sys;
+    struct deint_data *const    p_deint_data = filter_sys->p_data;
+    const video_format_t *      fmt = &filter->fmt_out.video;
+
+    if (filter_sys->cur == NULL)
+        return NULL;
+
+    p_deint_data->cur_frame = 1;
+    picture_t *dest = Filter(filter, filter_sys->cur,
+                        Deinterlace_UpdateFilterParams,
+                        Deinterlace_UpdateReferenceFrames,
+                        Deinterlace_UpdatePipelineParams);
+    if (unlikely(!dest))
+        goto error;
+
+    dest->b_progressive = true;
+    dest->i_nb_fields = 1;
+
+    if (filter_sys->cur->date != VLC_TICK_INVALID)
+    {
+        vlc_tick_t i_field_dur = 0;
+        unsigned int i = 0;
+        for ( ; i < METADATA_SIZE-1; i ++)
+            if (p_deint_data->meta[i].date != VLC_TICK_INVALID)
+                break;
+        if (i < METADATA_SIZE-1) {
+            unsigned int i_fields_total = 0;
+            for (unsigned int j = i; j < METADATA_SIZE-1; ++j)
+                i_fields_total += p_deint_data->meta[j].i_nb_fields;
+            i_field_dur = (filter_sys->src_date - p_deint_data->meta[i].date) / i_fields_total;
+        }
+        else if (fmt->i_frame_rate_base)
+            i_field_dur = vlc_tick_from_samples(fmt->i_frame_rate_base, fmt->i_frame_rate);
+
+        dest->date = filter_sys->cur->date + i_field_dur;
+    }
+    else
+        dest->date = VLC_TICK_INVALID;
+    return dest;
+
+error:
+    filter_sys->cur = NULL;
     return NULL;
 }
 
@@ -916,6 +942,11 @@ Deinterlace_Flush(filter_t *filter)
             p_deint_data->history.pp_pics[--p_deint_data->history.num_pics];
         picture_Release(pic);
     }
+    if (p_sys->cur != NULL)
+    {
+        picture_Release( p_sys->cur );
+        p_sys->cur = NULL;
+    }
 
     for (unsigned int i = 0; i < METADATA_SIZE; ++i)
     {
@@ -1083,6 +1114,7 @@ static void CloseDeinterlace(filter_t *filter)
 
 static const struct vlc_filter_operations DeinterlaceX2_ops = {
     .filter_video = DeinterlaceX2, .flush = Deinterlace_Flush, .close = CloseDeinterlace,
+    .drain_video  = DrainX2,
 };
 static const struct vlc_filter_operations Deinterlace_ops = {
     .filter_video = Deinterlace,   .flush = Deinterlace_Flush, .close = CloseDeinterlace,
-- 
2.26.2



More information about the vlc-devel mailing list