1 From 6c7a2caf88dda1aa4459b80d399da37dff6c6942 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Fri, 18 Dec 2020 19:56:31 +0000
4 Subject: [PATCH] staging/bcm2835-codec: Add support for decoding
7 The video decoder can support decoding interlaced streams, so add
8 the required plumbing to signal this correctly.
10 The encoder and ISP do NOT support interlaced data, so trying to
11 configure an interlaced format on those nodes will be rejected.
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
15 .../bcm2835-codec/bcm2835-v4l2-codec.c | 84 +++++++++++++++++--
16 1 file changed, 77 insertions(+), 7 deletions(-)
18 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
19 +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
20 @@ -619,6 +619,7 @@ struct bcm2835_codec_q_data {
21 unsigned int crop_height;
23 struct v4l2_fract aspect_ratio;
24 + enum v4l2_field field;
26 unsigned int sizeimage;
27 unsigned int sequence;
28 @@ -986,6 +987,10 @@ static void handle_fmt_changed(struct bc
29 struct bcm2835_codec_q_data *q_data;
30 struct mmal_msg_event_format_changed *format =
31 (struct mmal_msg_event_format_changed *)mmal_buf->buffer;
32 + struct mmal_parameter_video_interlace_type interlace;
33 + int interlace_size = sizeof(interlace);
36 v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
38 format->buffer_size_min,
39 @@ -1029,6 +1034,30 @@ static void handle_fmt_changed(struct bc
40 q_data->aspect_ratio.numerator = format->es.video.par.num;
41 q_data->aspect_ratio.denominator = format->es.video.par.den;
43 + ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
44 + &ctx->component->output[0],
45 + MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
49 + switch (interlace.mode) {
50 + case MMAL_INTERLACE_PROGRESSIVE:
52 + q_data->field = V4L2_FIELD_NONE;
54 + case MMAL_INTERLACE_FIELDS_INTERLEAVED_UPPER_FIRST:
55 + q_data->field = V4L2_FIELD_INTERLACED_TB;
57 + case MMAL_INTERLACE_FIELDS_INTERLEAVED_LOWER_FIRST:
58 + q_data->field = V4L2_FIELD_INTERLACED_BT;
61 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: interlace mode %u, v4l2 field %u\n",
62 + __func__, interlace.mode, q_data->field);
64 + q_data->field = V4L2_FIELD_NONE;
67 queue_res_chg_event(ctx);
70 @@ -1101,6 +1130,22 @@ static void op_buffer_cb(struct vchiq_mm
71 vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
73 vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
74 + switch (mmal_buf->mmal_flags &
75 + (MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
76 + MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST)) {
78 + case MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST: /* Bogus */
79 + vb2->field = V4L2_FIELD_NONE;
81 + case MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED:
82 + vb2->field = V4L2_FIELD_INTERLACED_BT;
84 + case (MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
85 + MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST):
86 + vb2->field = V4L2_FIELD_INTERLACED_TB;
90 if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
91 vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
93 @@ -1272,7 +1317,7 @@ static int vidioc_g_fmt(struct bcm2835_c
94 f->fmt.pix_mp.width = q_data->crop_width;
95 f->fmt.pix_mp.height = q_data->height;
96 f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc;
97 - f->fmt.pix_mp.field = V4L2_FIELD_NONE;
98 + f->fmt.pix_mp.field = q_data->field;
99 f->fmt.pix_mp.colorspace = ctx->colorspace;
100 f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage;
101 f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
102 @@ -1347,7 +1392,33 @@ static int vidioc_try_fmt(struct bcm2835
103 memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
104 sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
106 - f->fmt.pix_mp.field = V4L2_FIELD_NONE;
107 + if (ctx->dev->role == DECODE) {
108 + switch (f->fmt.pix_mp.field) {
110 + * All of this is pretty much guesswork as we'll set the
111 + * interlace format correctly come format changed, and signal
112 + * it appropriately on each buffer.
115 + case V4L2_FIELD_NONE:
116 + case V4L2_FIELD_ANY:
117 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
119 + case V4L2_FIELD_INTERLACED:
120 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
122 + case V4L2_FIELD_TOP:
123 + case V4L2_FIELD_BOTTOM:
124 + case V4L2_FIELD_INTERLACED_TB:
125 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED_TB;
127 + case V4L2_FIELD_INTERLACED_BT:
128 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED_BT;
132 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
137 @@ -1430,6 +1501,8 @@ static int vidioc_s_fmt(struct bcm2835_c
138 ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
139 ctx->quant = f->fmt.pix_mp.quantization;
141 + q_data->field = f->fmt.pix_mp.field;
143 /* All parameters should have been set correctly by try_fmt */
144 q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
145 q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
146 @@ -2429,11 +2502,6 @@ static int bcm2835_codec_buf_prepare(str
147 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
148 if (vbuf->field == V4L2_FIELD_ANY)
149 vbuf->field = V4L2_FIELD_NONE;
150 - if (vbuf->field != V4L2_FIELD_NONE) {
151 - v4l2_err(&ctx->dev->v4l2_dev, "%s field isn't supported\n",
157 if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
158 @@ -2735,6 +2803,7 @@ static int bcm2835_codec_open(struct fil
159 ctx->q_data[V4L2_M2M_SRC].crop_width,
160 ctx->q_data[V4L2_M2M_SRC].height,
161 ctx->q_data[V4L2_M2M_SRC].fmt);
162 + ctx->q_data[V4L2_M2M_SRC].field = V4L2_FIELD_NONE;
164 ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
165 ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
166 @@ -2749,6 +2818,7 @@ static int bcm2835_codec_open(struct fil
167 ctx->q_data[V4L2_M2M_DST].fmt);
168 ctx->q_data[V4L2_M2M_DST].aspect_ratio.numerator = 1;
169 ctx->q_data[V4L2_M2M_DST].aspect_ratio.denominator = 1;
170 + ctx->q_data[V4L2_M2M_DST].field = V4L2_FIELD_NONE;
172 ctx->colorspace = V4L2_COLORSPACE_REC709;
173 ctx->bitrate = 10 * 1000 * 1000;