7d5162d4fc76db65b59e38aab921272d5d80f29c
[openwrt/staging/blogic.git] /
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
5 interlaced streams
6
7 The video decoder can support decoding interlaced streams, so add
8 the required plumbing to signal this correctly.
9
10 The encoder and ISP do NOT support interlaced data, so trying to
11 configure an interlaced format on those nodes will be rejected.
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
14 ---
15 .../bcm2835-codec/bcm2835-v4l2-codec.c | 84 +++++++++++++++++--
16 1 file changed, 77 insertions(+), 7 deletions(-)
17
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;
22 bool selection_set;
23 struct v4l2_fract aspect_ratio;
24 + enum v4l2_field field;
25
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);
34 + int ret;
35 +
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",
37 __func__,
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;
42
43 + ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
44 + &ctx->component->output[0],
45 + MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
46 + &interlace,
47 + &interlace_size);
48 + if (!ret) {
49 + switch (interlace.mode) {
50 + case MMAL_INTERLACE_PROGRESSIVE:
51 + default:
52 + q_data->field = V4L2_FIELD_NONE;
53 + break;
54 + case MMAL_INTERLACE_FIELDS_INTERLEAVED_UPPER_FIRST:
55 + q_data->field = V4L2_FIELD_INTERLACED_TB;
56 + break;
57 + case MMAL_INTERLACE_FIELDS_INTERLEAVED_LOWER_FIRST:
58 + q_data->field = V4L2_FIELD_INTERLACED_BT;
59 + break;
60 + }
61 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: interlace mode %u, v4l2 field %u\n",
62 + __func__, interlace.mode, q_data->field);
63 + } else {
64 + q_data->field = V4L2_FIELD_NONE;
65 + }
66 +
67 queue_res_chg_event(ctx);
68 }
69
70 @@ -1101,6 +1130,22 @@ static void op_buffer_cb(struct vchiq_mm
71 vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
72
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)) {
77 + case 0:
78 + case MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST: /* Bogus */
79 + vb2->field = V4L2_FIELD_NONE;
80 + break;
81 + case MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED:
82 + vb2->field = V4L2_FIELD_INTERLACED_BT;
83 + break;
84 + case (MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
85 + MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST):
86 + vb2->field = V4L2_FIELD_INTERLACED_TB;
87 + break;
88 + }
89 +
90 if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
91 vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
92
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));
105
106 - f->fmt.pix_mp.field = V4L2_FIELD_NONE;
107 + if (ctx->dev->role == DECODE) {
108 + switch (f->fmt.pix_mp.field) {
109 + /*
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.
113 + */
114 + default:
115 + case V4L2_FIELD_NONE:
116 + case V4L2_FIELD_ANY:
117 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
118 + break;
119 + case V4L2_FIELD_INTERLACED:
120 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
121 + break;
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;
126 + break;
127 + case V4L2_FIELD_INTERLACED_BT:
128 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED_BT;
129 + break;
130 + }
131 + } else {
132 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
133 + }
134
135 return 0;
136 }
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;
140
141 + q_data->field = f->fmt.pix_mp.field;
142 +
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",
152 - __func__);
153 - return -EINVAL;
154 - }
155 }
156
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;
163
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;
171
172 ctx->colorspace = V4L2_COLORSPACE_REC709;
173 ctx->bitrate = 10 * 1000 * 1000;