[vlc-devel] [PATCH 09/19] vaapi: implement draining of extra pictures in x2 deinterlacer

Steve Lhomme robux4 at ycbcr.xyz
Tue Oct 13 15:51:52 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 | 100 ++++++++++++++++++++++++-------------
 1 file changed, 65 insertions(+), 35 deletions(-)

diff --git a/modules/hw/vaapi/filters.c b/modules/hw/vaapi/filters.c
index bd933ac8c63..2673edc078e 100644
--- a/modules/hw/vaapi/filters.c
+++ b/modules/hw/vaapi/filters.c
@@ -51,6 +51,9 @@ typedef struct
     struct va_filter_desc       va;
     picture_pool_t *            dest_pics;
     bool                        b_pipeline_fast;
+
+    picture_t *                 cur; // X2 Deinterlacer
+
     void *                      p_data;
 } filter_sys_t;
 
@@ -308,6 +311,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;
@@ -854,53 +858,73 @@ 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;
 
-    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;
 
+    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 = (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 +940,11 @@ Deinterlace_Flush(filter_t *filter)
             p_deint_data->history.pp_pics[--p_deint_data->history.num_pics];
         picture_Release(pic);
     }
+    if (filter_sys->cur != NULL)
+    {
+        picture_Release( filter_sys->cur );
+        filter_sys->cur = NULL;
+    }
 
     for (unsigned int i = 0; i < METADATA_SIZE; ++i)
     {
@@ -1083,6 +1112,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