bcm2835-codec: Return empty buffers to the VPU instead of queueing to vbuf2
authorDave Stevenson <dave.stevenson@raspberrypi.com>
Mon, 28 Mar 2022 10:52:48 +0000 (11:52 +0100)
committerPhil Elwell <8911409+pelwell@users.noreply.github.com>
Mon, 28 Mar 2022 12:22:15 +0000 (13:22 +0100)
The encoder can skip frames totally should rate control overshoot
the target bitrate too far. In this situation it generates an
output buffer of length 0.
V4L2 treats a buffer of length 0 as an end of stream flag, which is
not appropriate in this case, therefore we can not return that buffer
to the client.

The driver was returning the buffer to videobuf2 in the QUEUED state,
however that buffer was then not dequeued again, so the number of
buffers was reduced each time this happened. In the pathological
case of using GStreamer's videotestsrc in mode 1 for noise, this happens
sufficiently frequently to totally stall the pipeline.

If the port is still enabled then return the buffer straight back to
the VPU rather than to videobuf2.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c

index ebda39a..8abdd7f 100644 (file)
@@ -1159,10 +1159,15 @@ static void op_buffer_cb(struct vchiq_mmal_instance *instance,
                v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: Empty buffer - flags %04x",
                         __func__, mmal_buf->mmal_flags);
                if (!(mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS)) {
-                       vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_QUEUED);
-                       if (!port->enabled &&
-                           atomic_read(&port->buffers_with_vpu))
-                               complete(&ctx->frame_cmplt);
+                       if (!port->enabled) {
+                               vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_QUEUED);
+                               if (atomic_read(&port->buffers_with_vpu))
+                                       complete(&ctx->frame_cmplt);
+                       } else {
+                               vchiq_mmal_submit_buffer(ctx->dev->instance,
+                                                        &ctx->component->output[0],
+                                                        mmal_buf);
+                       }
                        return;
                }
        }