1823d6269b628660dacdded8aa0ba55a66964a27
[openwrt/staging/neocturne.git] /
1 From 3fbd7957bae36bbafb54dc7bf1624b158fa2a984 Mon Sep 17 00:00:00 2001
2 From: Dom Cobley <popcornmix@gmail.com>
3 Date: Fri, 6 Aug 2021 15:37:16 +0100
4 Subject: [PATCH] staging/bcm2835_codec: Add support for image_fx to
5 deinterlace
6
7 Adds another /dev/video node wrapping image_fx doing deinterlace.
8
9 Co-developed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
10 Signed-off-by: Dom Cobley <popcornmix@gmail.com>
11 ---
12 .../bcm2835-codec/bcm2835-v4l2-codec.c | 152 +++++++++++++++++-
13 1 file changed, 150 insertions(+), 2 deletions(-)
14
15 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
16 +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
17 @@ -58,6 +58,10 @@ static int isp_video_nr = 12;
18 module_param(isp_video_nr, int, 0644);
19 MODULE_PARM_DESC(isp_video_nr, "isp video device number");
20
21 +static int deinterlace_video_nr = 18;
22 +module_param(deinterlace_video_nr, int, 0644);
23 +MODULE_PARM_DESC(deinterlace_video_nr, "deinterlace video device number");
24 +
25 /*
26 * Workaround for GStreamer v4l2convert component not considering Bayer formats
27 * as raw, and therefore not considering a V4L2 device that supports them as
28 @@ -71,22 +75,33 @@ static unsigned int debug;
29 module_param(debug, uint, 0644);
30 MODULE_PARM_DESC(debug, "activates debug info (0-3)");
31
32 +static bool advanced_deinterlace = true;
33 +module_param(advanced_deinterlace, bool, 0644);
34 +MODULE_PARM_DESC(advanced_deinterlace, "Use advanced deinterlace");
35 +
36 +static int field_override;
37 +module_param(field_override, int, 0644);
38 +MODULE_PARM_DESC(field_override, "force TB(8)/BT(9) field");
39 +
40 enum bcm2835_codec_role {
41 DECODE,
42 ENCODE,
43 ISP,
44 + DEINTERLACE,
45 };
46
47 static const char * const roles[] = {
48 "decode",
49 "encode",
50 - "isp"
51 + "isp",
52 + "image_fx",
53 };
54
55 static const char * const components[] = {
56 "ril.video_decode",
57 "ril.video_encode",
58 "ril.isp",
59 + "ril.image_fx",
60 };
61
62 /* Timeout for stop_streaming to allow all buffers to return */
63 @@ -683,6 +698,7 @@ struct bcm2835_codec_driver {
64 struct bcm2835_codec_dev *encode;
65 struct bcm2835_codec_dev *decode;
66 struct bcm2835_codec_dev *isp;
67 + struct bcm2835_codec_dev *deinterlace;
68 };
69
70 enum {
71 @@ -1196,6 +1212,19 @@ static void vb2_to_mmal_buffer(struct m2
72 do_div(pts, 1000);
73 buf->mmal.pts = pts;
74 buf->mmal.dts = MMAL_TIME_UNKNOWN;
75 +
76 + switch (field_override ? field_override : vb2->field) {
77 + default:
78 + case V4L2_FIELD_NONE:
79 + break;
80 + case V4L2_FIELD_INTERLACED_BT:
81 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED;
82 + break;
83 + case V4L2_FIELD_INTERLACED_TB:
84 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
85 + MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST;
86 + break;
87 + }
88 }
89
90 /* device_run() - prepares and starts the device
91 @@ -1396,7 +1425,7 @@ static int vidioc_try_fmt(struct bcm2835
92 memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
93 sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
94
95 - if (ctx->dev->role == DECODE) {
96 + if (ctx->dev->role == DECODE || ctx->dev->role == DEINTERLACE) {
97 switch (f->fmt.pix_mp.field) {
98 /*
99 * All of this is pretty much guesswork as we'll set the
100 @@ -1686,6 +1715,46 @@ static int vidioc_g_selection(struct fil
101 break;
102 case ISP:
103 break;
104 + case DEINTERLACE:
105 + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
106 + switch (s->target) {
107 + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
108 + case V4L2_SEL_TGT_COMPOSE:
109 + s->r.left = 0;
110 + s->r.top = 0;
111 + s->r.width = q_data->crop_width;
112 + s->r.height = q_data->crop_height;
113 + break;
114 + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
115 + s->r.left = 0;
116 + s->r.top = 0;
117 + s->r.width = q_data->crop_width;
118 + s->r.height = q_data->crop_height;
119 + break;
120 + default:
121 + return -EINVAL;
122 + }
123 + } else {
124 + /* must be V4L2_BUF_TYPE_VIDEO_OUTPUT */
125 + switch (s->target) {
126 + case V4L2_SEL_TGT_CROP_DEFAULT:
127 + case V4L2_SEL_TGT_CROP_BOUNDS:
128 + s->r.top = 0;
129 + s->r.left = 0;
130 + s->r.width = q_data->bytesperline;
131 + s->r.height = q_data->height;
132 + break;
133 + case V4L2_SEL_TGT_CROP:
134 + s->r.top = 0;
135 + s->r.left = 0;
136 + s->r.width = q_data->crop_width;
137 + s->r.height = q_data->crop_height;
138 + break;
139 + default:
140 + return -EINVAL;
141 + }
142 + }
143 + break;
144 }
145
146 return 0;
147 @@ -1761,6 +1830,41 @@ static int vidioc_s_selection(struct fil
148 break;
149 case ISP:
150 break;
151 + case DEINTERLACE:
152 + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
153 + switch (s->target) {
154 + case V4L2_SEL_TGT_COMPOSE:
155 + /* Accept cropped image */
156 + s->r.left = 0;
157 + s->r.top = 0;
158 + s->r.width = min(s->r.width, q_data->crop_width);
159 + s->r.height = min(s->r.height, q_data->height);
160 + q_data->crop_width = s->r.width;
161 + q_data->crop_height = s->r.height;
162 + q_data->selection_set = true;
163 + break;
164 + default:
165 + return -EINVAL;
166 + }
167 + break;
168 + } else {
169 + /* must be V4L2_BUF_TYPE_VIDEO_OUTPUT */
170 + switch (s->target) {
171 + case V4L2_SEL_TGT_CROP:
172 + /* Only support crop from (0,0) */
173 + s->r.top = 0;
174 + s->r.left = 0;
175 + s->r.width = min(s->r.width, q_data->crop_width);
176 + s->r.height = min(s->r.height, q_data->height);
177 + q_data->crop_width = s->r.width;
178 + q_data->crop_height = s->r.height;
179 + q_data->selection_set = true;
180 + break;
181 + default:
182 + return -EINVAL;
183 + }
184 + break;
185 + }
186 }
187
188 return 0;
189 @@ -2335,6 +2439,30 @@ static int bcm2835_codec_create_componen
190 MMAL_PARAMETER_VIDEO_VALIDATE_TIMESTAMPS,
191 &enable,
192 sizeof(enable));
193 + } else if (dev->role == DEINTERLACE) {
194 + /* Select the default deinterlace algorithm. */
195 + int half_framerate = 0;
196 + int default_frame_interval = -1; /* don't interpolate */
197 + int frame_type = 5; /* 0=progressive, 3=TFF, 4=BFF, 5=see frame */
198 + int use_qpus = 0;
199 + enum mmal_parameter_imagefx effect =
200 + advanced_deinterlace && ctx->q_data[V4L2_M2M_SRC].crop_width <= 800 ?
201 + MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV :
202 + MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST;
203 + struct mmal_parameter_imagefx_parameters params = {
204 + .effect = effect,
205 + .num_effect_params = 4,
206 + .effect_parameter = { frame_type,
207 + default_frame_interval,
208 + half_framerate,
209 + use_qpus },
210 + };
211 +
212 + vchiq_mmal_port_parameter_set(dev->instance,
213 + &ctx->component->output[0],
214 + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
215 + &params,
216 + sizeof(params));
217 }
218
219 setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
220 @@ -3173,6 +3301,16 @@ static int bcm2835_codec_create(struct b
221 function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
222 video_nr = isp_video_nr;
223 break;
224 + case DEINTERLACE:
225 + v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
226 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
227 + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
228 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
229 + v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
230 + v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
231 + function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
232 + video_nr = deinterlace_video_nr;
233 + break;
234 default:
235 ret = -EINVAL;
236 goto unreg_dev;
237 @@ -3268,6 +3406,10 @@ static int bcm2835_codec_probe(struct pl
238 if (ret)
239 goto out;
240
241 + ret = bcm2835_codec_create(drv, &drv->deinterlace, DEINTERLACE);
242 + if (ret)
243 + goto out;
244 +
245 /* Register the media device node */
246 if (media_device_register(mdev) < 0)
247 goto out;
248 @@ -3277,6 +3419,10 @@ static int bcm2835_codec_probe(struct pl
249 return 0;
250
251 out:
252 + if (drv->deinterlace) {
253 + bcm2835_codec_destroy(drv->deinterlace);
254 + drv->deinterlace = NULL;
255 + }
256 if (drv->isp) {
257 bcm2835_codec_destroy(drv->isp);
258 drv->isp = NULL;
259 @@ -3298,6 +3444,8 @@ static int bcm2835_codec_remove(struct p
260
261 media_device_unregister(&drv->mdev);
262
263 + bcm2835_codec_destroy(drv->deinterlace);
264 +
265 bcm2835_codec_destroy(drv->isp);
266
267 bcm2835_codec_destroy(drv->encode);