Skip to content

Commit bf0bb5a

Browse files
committed
bcm2835-codec: /dev/video21 as interface to image_encode JPEG encoder
1 parent e8e74cc commit bf0bb5a

File tree

1 file changed

+100
-26
lines changed

1 file changed

+100
-26
lines changed

drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ static int deinterlace_video_nr = 18;
6262
module_param(deinterlace_video_nr, int, 0644);
6363
MODULE_PARM_DESC(deinterlace_video_nr, "deinterlace video device number");
6464

65+
static int encode_image_nr = 21;
66+
module_param(encode_image_nr, int, 0644);
67+
MODULE_PARM_DESC(encode_image_nr, "encoder image device number");
68+
6569
/*
6670
* Workaround for GStreamer v4l2convert component not considering Bayer formats
6771
* as raw, and therefore not considering a V4L2 device that supports them as
@@ -88,20 +92,23 @@ enum bcm2835_codec_role {
8892
ENCODE,
8993
ISP,
9094
DEINTERLACE,
95+
ENCODE_IMAGE,
9196
};
9297

9398
static const char * const roles[] = {
9499
"decode",
95100
"encode",
96101
"isp",
97102
"image_fx",
103+
"encode_image",
98104
};
99105

100106
static const char * const components[] = {
101107
"ril.video_decode",
102108
"ril.video_encode",
103109
"ril.isp",
104110
"ril.image_fx",
111+
"ril.image_encode",
105112
};
106113

107114
/* Timeout for stop_streaming to allow all buffers to return */
@@ -577,6 +584,12 @@ static const struct bcm2835_codec_fmt supported_formats[] = {
577584
.depth = 0,
578585
.flags = V4L2_FMT_FLAG_COMPRESSED,
579586
.mmal_fmt = MMAL_ENCODING_H264,
587+
}, {
588+
.fourcc = V4L2_PIX_FMT_JPEG,
589+
.depth = 0,
590+
.flags = V4L2_FMT_FLAG_COMPRESSED,
591+
.mmal_fmt = MMAL_ENCODING_JPEG,
592+
.size_multiplier_x2 = 3,
580593
}, {
581594
.fourcc = V4L2_PIX_FMT_MJPEG,
582595
.depth = 0,
@@ -697,6 +710,7 @@ struct bcm2835_codec_driver {
697710
struct bcm2835_codec_dev *decode;
698711
struct bcm2835_codec_dev *isp;
699712
struct bcm2835_codec_dev *deinterlace;
713+
struct bcm2835_codec_dev *encode_image;
700714
};
701715

702716
enum {
@@ -829,13 +843,15 @@ static void job_abort(void *priv)
829843
static inline unsigned int get_sizeimage(int bpl, int width, int height,
830844
struct bcm2835_codec_fmt *fmt)
831845
{
846+
unsigned int multiplier = max(fmt->size_multiplier_x2, 1);
847+
832848
if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
833849
if (width * height > 1280 * 720)
834-
return DEF_COMP_BUF_SIZE_GREATER_720P;
850+
return DEF_COMP_BUF_SIZE_GREATER_720P * multiplier;
835851
else
836-
return DEF_COMP_BUF_SIZE_720P_OR_LESS;
852+
return DEF_COMP_BUF_SIZE_720P_OR_LESS * multiplier;
837853
} else {
838-
return (bpl * height * fmt->size_multiplier_x2) >> 1;
854+
return (bpl * height * multiplier) >> 1;
839855
}
840856
}
841857

@@ -1413,12 +1429,12 @@ static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
14131429
f->fmt.pix_mp.height = MIN_H;
14141430

14151431
/*
1416-
* For decoders the buffer must have a vertical alignment of 16
1417-
* lines.
1432+
* For decoders and image encoders the buffer must have
1433+
* a vertical alignment of 16 lines.
14181434
* The selection will reflect any cropping rectangle when only
14191435
* some of the pixels are active.
14201436
*/
1421-
if (ctx->dev->role == DECODE)
1437+
if (ctx->dev->role == DECODE || ctx->dev->role == ENCODE_IMAGE)
14221438
f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
14231439
}
14241440
f->fmt.pix_mp.num_planes = 1;
@@ -1562,12 +1578,13 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
15621578
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
15631579
q_data->bytesperline, q_data->sizeimage);
15641580

1565-
if (ctx->dev->role == DECODE &&
1581+
if ((ctx->dev->role == DECODE || ctx->dev->role == ENCODE_IMAGE) &&
15661582
q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
15671583
q_data->crop_width && q_data->height) {
15681584
/*
1569-
* On the decoder, if provided with a resolution on the input
1570-
* side, then replicate that to the output side.
1585+
* On the decoder or image encoder, if provided with
1586+
* a resolution on the input side, then replicate that
1587+
* to the output side.
15711588
* GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
15721589
* nor set up a resolution on the output side, therefore
15731590
* we can't decode anything at a resolution other than the
@@ -1707,7 +1724,7 @@ static int vidioc_g_selection(struct file *file, void *priv,
17071724
switch (s->type) {
17081725
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
17091726
/* CAPTURE on encoder is not valid. */
1710-
if (ctx->dev->role == ENCODE)
1727+
if (ctx->dev->role == ENCODE || ctx->dev->role == ENCODE_IMAGE)
17111728
return -EINVAL;
17121729
q_data = &ctx->q_data[V4L2_M2M_DST];
17131730
break;
@@ -1750,6 +1767,7 @@ static int vidioc_g_selection(struct file *file, void *priv,
17501767
}
17511768
break;
17521769
case ENCODE:
1770+
case ENCODE_IMAGE:
17531771
switch (s->target) {
17541772
case V4L2_SEL_TGT_CROP_DEFAULT:
17551773
case V4L2_SEL_TGT_CROP_BOUNDS:
@@ -1832,7 +1850,7 @@ static int vidioc_s_selection(struct file *file, void *priv,
18321850
switch (s->type) {
18331851
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
18341852
/* CAPTURE on encoder is not valid. */
1835-
if (ctx->dev->role == ENCODE)
1853+
if (ctx->dev->role == ENCODE || ctx->dev->role == ENCODE_IMAGE)
18361854
return -EINVAL;
18371855
q_data = &ctx->q_data[V4L2_M2M_DST];
18381856
break;
@@ -1868,6 +1886,7 @@ static int vidioc_s_selection(struct file *file, void *priv,
18681886
}
18691887
break;
18701888
case ENCODE:
1889+
case ENCODE_IMAGE:
18711890
switch (s->target) {
18721891
case V4L2_SEL_TGT_CROP:
18731892
/* Only support crop from (0,0) */
@@ -2250,6 +2269,18 @@ static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
22502269
sizeof(u32_value));
22512270
break;
22522271
}
2272+
case V4L2_CID_JPEG_COMPRESSION_QUALITY:
2273+
if (!ctx->component)
2274+
break;
2275+
2276+
ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2277+
&ctx->component->output[0],
2278+
MMAL_PARAMETER_JPEG_Q_FACTOR,
2279+
&ctrl->val,
2280+
sizeof(ctrl->val));
2281+
break;
2282+
2283+
22532284

22542285
default:
22552286
v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
@@ -2348,7 +2379,7 @@ static int vidioc_try_encoder_cmd(struct file *file, void *priv,
23482379
{
23492380
struct bcm2835_codec_ctx *ctx = file2ctx(file);
23502381

2351-
if (ctx->dev->role != ENCODE)
2382+
if (ctx->dev->role != ENCODE && ctx->dev->role != ENCODE_IMAGE)
23522383
return -EINVAL;
23532384

23542385
switch (cmd->cmd) {
@@ -2559,6 +2590,14 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
25592590
MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
25602591
&params,
25612592
sizeof(params));
2593+
2594+
} else if (dev->role == ENCODE_IMAGE) {
2595+
enable = 0;
2596+
vchiq_mmal_port_parameter_set(dev->instance,
2597+
&ctx->component->control,
2598+
MMAL_PARAMETER_EXIF_DISABLE,
2599+
&enable,
2600+
sizeof(enable));
25622601
}
25632602

25642603
setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
@@ -2587,7 +2626,7 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
25872626
goto destroy_component;
25882627
}
25892628

2590-
if (dev->role == ENCODE) {
2629+
if (dev->role == ENCODE || dev->role == ENCODE_IMAGE) {
25912630
u32 param = 1;
25922631

25932632
if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
@@ -2596,19 +2635,21 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
25962635
ctx->q_data[V4L2_M2M_SRC].sizeimage,
25972636
ctx->component->output[0].minimum_buffer.size);
25982637

2599-
/* Enable SPS Timing header so framerate information is encoded
2600-
* in the H264 header.
2601-
*/
2602-
vchiq_mmal_port_parameter_set(ctx->dev->instance,
2603-
&ctx->component->output[0],
2604-
MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
2605-
&param, sizeof(param));
2606-
2607-
/* Enable inserting headers into the first frame */
2608-
vchiq_mmal_port_parameter_set(ctx->dev->instance,
2609-
&ctx->component->control,
2610-
MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
2611-
&param, sizeof(param));
2638+
if (dev->role == ENCODE) {
2639+
/* Enable SPS Timing header so framerate information is encoded
2640+
* in the H264 header.
2641+
*/
2642+
vchiq_mmal_port_parameter_set(ctx->dev->instance,
2643+
&ctx->component->output[0],
2644+
MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
2645+
&param, sizeof(param));
2646+
2647+
/* Enable inserting headers into the first frame */
2648+
vchiq_mmal_port_parameter_set(ctx->dev->instance,
2649+
&ctx->component->control,
2650+
MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
2651+
&param, sizeof(param));
2652+
}
26122653
/*
26132654
* Avoid fragmenting the buffers over multiple frames (unless
26142655
* the frame is bigger than the whole buffer)
@@ -3238,6 +3279,23 @@ static int bcm2835_codec_open(struct file *file)
32383279
v4l2_ctrl_handler_init(hdl, 0);
32393280
}
32403281
break;
3282+
case ENCODE_IMAGE:
3283+
{
3284+
/* Encode image controls */
3285+
v4l2_ctrl_handler_init(hdl, 1);
3286+
3287+
v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3288+
V4L2_CID_JPEG_COMPRESSION_QUALITY,
3289+
1, 100,
3290+
1, 80);
3291+
if (hdl->error) {
3292+
rc = hdl->error;
3293+
goto free_ctrl_handler;
3294+
}
3295+
ctx->fh.ctrl_handler = hdl;
3296+
v4l2_ctrl_handler_setup(hdl);
3297+
}
3298+
break;
32413299
}
32423300

32433301
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
@@ -3515,6 +3573,12 @@ static int bcm2835_codec_create(struct bcm2835_codec_driver *drv,
35153573
function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
35163574
video_nr = deinterlace_video_nr;
35173575
break;
3576+
case ENCODE_IMAGE:
3577+
v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
3578+
v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
3579+
function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
3580+
video_nr = encode_image_nr;
3581+
break;
35183582
default:
35193583
ret = -EINVAL;
35203584
goto unreg_dev;
@@ -3614,6 +3678,10 @@ static int bcm2835_codec_probe(struct platform_device *pdev)
36143678
if (ret)
36153679
goto out;
36163680

3681+
ret = bcm2835_codec_create(drv, &drv->encode_image, ENCODE_IMAGE);
3682+
if (ret)
3683+
goto out;
3684+
36173685
/* Register the media device node */
36183686
if (media_device_register(mdev) < 0)
36193687
goto out;
@@ -3623,6 +3691,10 @@ static int bcm2835_codec_probe(struct platform_device *pdev)
36233691
return 0;
36243692

36253693
out:
3694+
if (drv->encode_image) {
3695+
bcm2835_codec_destroy(drv->encode_image);
3696+
drv->encode_image = NULL;
3697+
}
36263698
if (drv->deinterlace) {
36273699
bcm2835_codec_destroy(drv->deinterlace);
36283700
drv->deinterlace = NULL;
@@ -3648,6 +3720,8 @@ static int bcm2835_codec_remove(struct platform_device *pdev)
36483720

36493721
media_device_unregister(&drv->mdev);
36503722

3723+
bcm2835_codec_destroy(drv->encode_image);
3724+
36513725
bcm2835_codec_destroy(drv->deinterlace);
36523726

36533727
bcm2835_codec_destroy(drv->isp);

0 commit comments

Comments
 (0)