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
7 Adds another /dev/video node wrapping image_fx doing deinterlace.
9 Co-developed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
10 Signed-off-by: Dom Cobley <popcornmix@gmail.com>
12 .../bcm2835-codec/bcm2835-v4l2-codec.c | 152 +++++++++++++++++-
13 1 file changed, 150 insertions(+), 2 deletions(-)
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");
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");
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)");
32 +static bool advanced_deinterlace = true;
33 +module_param(advanced_deinterlace, bool, 0644);
34 +MODULE_PARM_DESC(advanced_deinterlace, "Use advanced deinterlace");
36 +static int field_override;
37 +module_param(field_override, int, 0644);
38 +MODULE_PARM_DESC(field_override, "force TB(8)/BT(9) field");
40 enum bcm2835_codec_role {
47 static const char * const roles[] = {
55 static const char * const components[] = {
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;
71 @@ -1196,6 +1212,19 @@ static void vb2_to_mmal_buffer(struct m2
74 buf->mmal.dts = MMAL_TIME_UNKNOWN;
76 + switch (field_override ? field_override : vb2->field) {
78 + case V4L2_FIELD_NONE:
80 + case V4L2_FIELD_INTERLACED_BT:
81 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED;
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;
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));
95 - if (ctx->dev->role == DECODE) {
96 + if (ctx->dev->role == DECODE || ctx->dev->role == DEINTERLACE) {
97 switch (f->fmt.pix_mp.field) {
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
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:
111 + s->r.width = q_data->crop_width;
112 + s->r.height = q_data->crop_height;
114 + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
117 + s->r.width = q_data->crop_width;
118 + s->r.height = q_data->crop_height;
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:
130 + s->r.width = q_data->bytesperline;
131 + s->r.height = q_data->height;
133 + case V4L2_SEL_TGT_CROP:
136 + s->r.width = q_data->crop_width;
137 + s->r.height = q_data->crop_height;
147 @@ -1761,6 +1830,41 @@ static int vidioc_s_selection(struct fil
152 + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
153 + switch (s->target) {
154 + case V4L2_SEL_TGT_COMPOSE:
155 + /* Accept cropped image */
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;
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) */
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;
189 @@ -2335,6 +2439,30 @@ static int bcm2835_codec_create_componen
190 MMAL_PARAMETER_VIDEO_VALIDATE_TIMESTAMPS,
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 */
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 = {
205 + .num_effect_params = 4,
206 + .effect_parameter = { frame_type,
207 + default_frame_interval,
212 + vchiq_mmal_port_parameter_set(dev->instance,
213 + &ctx->component->output[0],
214 + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
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;
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;
237 @@ -3268,6 +3406,10 @@ static int bcm2835_codec_probe(struct pl
241 + ret = bcm2835_codec_create(drv, &drv->deinterlace, DEINTERLACE);
245 /* Register the media device node */
246 if (media_device_register(mdev) < 0)
248 @@ -3277,6 +3419,10 @@ static int bcm2835_codec_probe(struct pl
252 + if (drv->deinterlace) {
253 + bcm2835_codec_destroy(drv->deinterlace);
254 + drv->deinterlace = NULL;
257 bcm2835_codec_destroy(drv->isp);
259 @@ -3298,6 +3444,8 @@ static int bcm2835_codec_remove(struct p
261 media_device_unregister(&drv->mdev);
263 + bcm2835_codec_destroy(drv->deinterlace);
265 bcm2835_codec_destroy(drv->isp);
267 bcm2835_codec_destroy(drv->encode);