1 From 6eded7dd8bcf00c6c4f354cd2edfaabc8e82e8b7 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Fri, 9 Oct 2020 10:40:27 +0100
4 Subject: [PATCH] staging: bcm2835-codec: Allow decode res changed
5 before STREAMON(CAPTURE)
7 The V4L2 stateful video decoder API requires that you can STREAMON
8 on only the OUTPUT queue, feed in buffers, and wait for the
10 This requires that we enable the MMAL output port at the same time
11 as the input port, because the output port is the one that creates
12 the SOURCE_CHANGED event.
14 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
16 .../bcm2835-codec/bcm2835-v4l2-codec.c | 137 +++++++++++++++---
17 1 file changed, 117 insertions(+), 20 deletions(-)
19 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
20 +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
21 @@ -1498,6 +1498,7 @@ static int vidioc_s_fmt(struct bcm2835_c
23 struct vchiq_mmal_port *port;
24 bool update_capture_port = false;
25 + bool reenable_port = false;
28 v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
29 @@ -1575,6 +1576,24 @@ static int vidioc_s_fmt(struct bcm2835_c
33 + if (port->enabled) {
35 + * This should only ever happen with DECODE and the MMAL output
36 + * port that has been enabled for resolution changed events.
37 + * In this case no buffers have been allocated or sent to the
38 + * component, so warn on that.
40 + WARN_ON(ctx->dev->role != DECODE ||
41 + f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
42 + atomic_read(&port->buffers_with_vpu));
44 + ret = vchiq_mmal_port_disable(ctx->dev->instance, port);
46 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Error disabling port update buffer count, ret %d\n",
48 + reenable_port = true;
51 setup_mmal_port_format(ctx, q_data, port);
52 ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
54 @@ -1589,6 +1608,14 @@ static int vidioc_s_fmt(struct bcm2835_c
55 port->minimum_buffer.size);
58 + if (reenable_port) {
59 + ret = vchiq_mmal_port_enable(ctx->dev->instance,
63 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
66 v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
67 f->type, q_data->crop_width, q_data->height,
68 q_data->fmt->fourcc, q_data->sizeimage);
69 @@ -2467,9 +2494,11 @@ static int bcm2835_codec_create_componen
71 setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
72 &ctx->component->input[0]);
73 + ctx->component->input[0].cb_ctx = ctx;
75 setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
76 &ctx->component->output[0]);
77 + ctx->component->output[0].cb_ctx = ctx;
79 ret = vchiq_mmal_port_set_format(dev->instance,
80 &ctx->component->input[0]);
81 @@ -2724,6 +2753,24 @@ static void bcm2835_codec_buffer_cleanup
82 bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
85 +static void bcm2835_codec_flush_buffers(struct bcm2835_codec_ctx *ctx,
86 + struct vchiq_mmal_port *port)
90 + while (atomic_read(&port->buffers_with_vpu)) {
91 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
92 + __func__, atomic_read(&port->buffers_with_vpu));
93 + ret = wait_for_completion_timeout(&ctx->frame_cmplt,
96 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
98 + atomic_read(&port->buffers_with_vpu));
103 static int bcm2835_codec_start_streaming(struct vb2_queue *q,
106 @@ -2731,7 +2778,7 @@ static int bcm2835_codec_start_streaming
107 struct bcm2835_codec_dev *dev = ctx->dev;
108 struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
109 struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
113 v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
114 __func__, q->type, count);
115 @@ -2746,6 +2793,34 @@ static int bcm2835_codec_start_streaming
116 ctx->component_enabled = true;
119 + if (port->enabled) {
120 + unsigned int num_buffers;
122 + init_completion(&ctx->frame_cmplt);
125 + * This should only ever happen with DECODE and the MMAL output
126 + * port that has been enabled for resolution changed events.
127 + * In this case no buffers have been allocated or sent to the
128 + * component, so warn on that.
130 + WARN_ON(ctx->dev->role != DECODE);
131 + WARN_ON(q->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
132 + WARN_ON(atomic_read(&port->buffers_with_vpu));
135 + * Disable will reread the port format, so retain buffer count.
137 + num_buffers = port->current_buffer.num;
139 + ret = vchiq_mmal_port_disable(dev->instance, port);
141 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Error disabling port update buffer count, ret %d\n",
143 + bcm2835_codec_flush_buffers(ctx, port);
144 + port->current_buffer.num = num_buffers;
147 if (count < port->minimum_buffer.num)
148 count = port->minimum_buffer.num;
150 @@ -2760,6 +2835,22 @@ static int bcm2835_codec_start_streaming
154 + if (dev->role == DECODE &&
155 + q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
156 + !ctx->component->output[0].enabled) {
158 + * Decode needs to enable the MMAL output/V4L2 CAPTURE
159 + * port at this point too so that we have everything
160 + * set up for dynamic resolution changes.
162 + ret = vchiq_mmal_port_enable(dev->instance,
163 + &ctx->component->output[0],
166 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
170 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
172 * Create the EOS buffer.
173 @@ -2771,7 +2862,6 @@ static int bcm2835_codec_start_streaming
174 &q_data->eos_buffer.mmal);
175 q_data->eos_buffer_in_use = false;
177 - port->cb_ctx = ctx;
178 ret = vchiq_mmal_port_enable(dev->instance,
181 @@ -2779,14 +2869,17 @@ static int bcm2835_codec_start_streaming
182 v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n",
185 - port->cb_ctx = ctx;
186 - ret = vchiq_mmal_port_enable(dev->instance,
190 - v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
192 + if (!port->enabled) {
193 + ret = vchiq_mmal_port_enable(dev->instance,
197 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
201 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Done, ret %d\n",
206 @@ -2825,17 +2918,21 @@ static void bcm2835_codec_stop_streaming
207 __func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
210 - while (atomic_read(&port->buffers_with_vpu)) {
211 - v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
212 - __func__, atomic_read(&port->buffers_with_vpu));
213 - ret = wait_for_completion_timeout(&ctx->frame_cmplt,
216 - v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
218 - atomic_read(&port->buffers_with_vpu));
221 + bcm2835_codec_flush_buffers(ctx, port);
223 + if (dev->role == DECODE &&
224 + q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
225 + ctx->component->input[0].enabled) {
227 + * For decode we need to keep the MMAL output port enabled for
228 + * resolution changed events whenever the input is enabled.
230 + ret = vchiq_mmal_port_enable(dev->instance,
231 + &ctx->component->output[0],
234 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
238 /* If both ports disabled, then disable the component */