[vlc-devel] [PATCH v2 12/20] mmal/deinterlace: implement draining of extra pictures in deinterlacer

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


Fix the source picture was released after turning it into a MMAL_BUFFER_HEADER_T.
Not sure how this could work.

The while loop to create output picture is turned into single calls. One in the
filter function and others in the drain calls.
The assert done before returning a valid picture is moved up in the Filter
callback.

We no longer return pictures chained using vlc_picture_chain_AppendChain().
---
 modules/hw/mmal/deinterlace.c | 37 ++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/modules/hw/mmal/deinterlace.c b/modules/hw/mmal/deinterlace.c
index 70814303bb6..c6b4efddbe3 100644
--- a/modules/hw/mmal/deinterlace.c
+++ b/modules/hw/mmal/deinterlace.c
@@ -215,7 +215,6 @@ static picture_t *but_to_pic(filter_t * p_filter, MMAL_BUFFER_HEADER_T *out_buf)
 static picture_t *deinterlace(filter_t * p_filter, picture_t * p_pic)
 {
     filter_sys_t * const sys = p_filter->p_sys;
-    picture_t *ret_pics = NULL;
     MMAL_STATUS_T err;
     MMAL_BUFFER_HEADER_T * out_buf = NULL;
 
@@ -262,8 +261,6 @@ static picture_t *deinterlace(filter_t * p_filter, picture_t * p_pic)
             goto fail;
         }
 
-        picture_Release(p_pic);
-
         // Add a sequence to the flags so we can track what we have actually
         // deinterlaced
         pic_buf->flags = (pic_buf->flags & ~(0xfU * MMAL_BUFFER_HEADER_FLAG_USER0)) | (sys->seq_in * (MMAL_BUFFER_HEADER_FLAG_USER0));
@@ -277,9 +274,6 @@ static picture_t *deinterlace(filter_t * p_filter, picture_t * p_pic)
         }
     }
 
-    // Return anything that is in the out Q
-    picture_t * chain_tail = ret_pics;
-
     // Advanced di has a 3 frame latency, so if the seq delta is greater
     // than that then we are expecting at least two frames of output. Wait
     // for one of those.
@@ -287,21 +281,16 @@ static picture_t *deinterlace(filter_t * p_filter, picture_t * p_pic)
     // seq_out is last frame we removed from Q
     // So after 4 frames sent (1st time we want to wait), 0 rx seq_in=5, seq_out=15, delta=5
 
-    while ((out_buf = (seq_delta(sys->seq_in, sys->seq_out) >= 5 ? mmal_queue_timedwait(sys->out_q, 1000) : mmal_queue_get(sys->out_q))) != NULL)
+    out_buf = seq_delta(sys->seq_in, sys->seq_out) >= 5 ? mmal_queue_timedwait(sys->out_q, 1000) : mmal_queue_get(sys->out_q);
+    if (out_buf == NULL)
+        goto fail;
     {
         picture_t * out_pic = but_to_pic(p_filter, out_buf);
         if (unlikely(out_pic == NULL))
-            break;
-
-        vlc_picture_chain_AppendChain( chain_tail, out_pic );
-        chain_tail = out_pic;
+            goto fail;
+        return out_pic;
     }
 
-    // Crash on lockup
-    assert(ret_pics != NULL || seq_delta(sys->seq_in, sys->seq_out) < 5);
-
-    return ret_pics;
-
 fail:
     if (out_buf != NULL)
         mmal_buffer_header_release(out_buf);
@@ -309,6 +298,21 @@ fail:
     return NULL;
 }
 
+static picture_t *drain(filter_t * p_filter)
+{
+    filter_sys_t * const sys = p_filter->p_sys;
+    MMAL_BUFFER_HEADER_T * out_buf;
+    out_buf = seq_delta(sys->seq_in, sys->seq_out) >= 5 ? mmal_queue_timedwait(sys->out_q, 1000) : mmal_queue_get(sys->out_q);
+    if (out_buf == NULL)
+        return NULL;
+
+    picture_t * out_pic = but_to_pic(p_filter, out_buf);
+    if (unlikely(out_pic == NULL))
+        mmal_buffer_header_release(out_buf);
+
+    return out_pic;
+}
+
 static void di_flush(filter_t *p_filter)
 {
     filter_sys_t * const sys = p_filter->p_sys;
@@ -417,6 +421,7 @@ static bool is_fmt_valid_in(const vlc_fourcc_t fmt)
 
 static const struct vlc_filter_operations filter_ops = {
     .filter_video = deinterlace, .flush = di_flush, .close = CloseMmalDeinterlace,
+    .drain_video = drain,
 };
 
 static const struct vlc_filter_operations filter_pass_ops = {
-- 
2.26.2



More information about the vlc-devel mailing list