@@ -62,6 +62,10 @@ static int deinterlace_video_nr = 18;
62
62
module_param (deinterlace_video_nr , int , 0644 );
63
63
MODULE_PARM_DESC (deinterlace_video_nr , "deinterlace video device number" );
64
64
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
+
65
69
/*
66
70
* Workaround for GStreamer v4l2convert component not considering Bayer formats
67
71
* as raw, and therefore not considering a V4L2 device that supports them as
@@ -88,20 +92,23 @@ enum bcm2835_codec_role {
88
92
ENCODE ,
89
93
ISP ,
90
94
DEINTERLACE ,
95
+ ENCODE_IMAGE ,
91
96
};
92
97
93
98
static const char * const roles [] = {
94
99
"decode" ,
95
100
"encode" ,
96
101
"isp" ,
97
102
"image_fx" ,
103
+ "encode_image" ,
98
104
};
99
105
100
106
static const char * const components [] = {
101
107
"ril.video_decode" ,
102
108
"ril.video_encode" ,
103
109
"ril.isp" ,
104
110
"ril.image_fx" ,
111
+ "ril.image_encode" ,
105
112
};
106
113
107
114
/* Timeout for stop_streaming to allow all buffers to return */
@@ -577,6 +584,12 @@ static const struct bcm2835_codec_fmt supported_formats[] = {
577
584
.depth = 0 ,
578
585
.flags = V4L2_FMT_FLAG_COMPRESSED ,
579
586
.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 ,
580
593
}, {
581
594
.fourcc = V4L2_PIX_FMT_MJPEG ,
582
595
.depth = 0 ,
@@ -697,6 +710,7 @@ struct bcm2835_codec_driver {
697
710
struct bcm2835_codec_dev * decode ;
698
711
struct bcm2835_codec_dev * isp ;
699
712
struct bcm2835_codec_dev * deinterlace ;
713
+ struct bcm2835_codec_dev * encode_image ;
700
714
};
701
715
702
716
enum {
@@ -829,13 +843,15 @@ static void job_abort(void *priv)
829
843
static inline unsigned int get_sizeimage (int bpl , int width , int height ,
830
844
struct bcm2835_codec_fmt * fmt )
831
845
{
846
+ unsigned int multiplier = max (fmt -> size_multiplier_x2 , 1 );
847
+
832
848
if (fmt -> flags & V4L2_FMT_FLAG_COMPRESSED ) {
833
849
if (width * height > 1280 * 720 )
834
- return DEF_COMP_BUF_SIZE_GREATER_720P ;
850
+ return DEF_COMP_BUF_SIZE_GREATER_720P * multiplier ;
835
851
else
836
- return DEF_COMP_BUF_SIZE_720P_OR_LESS ;
852
+ return DEF_COMP_BUF_SIZE_720P_OR_LESS * multiplier ;
837
853
} else {
838
- return (bpl * height * fmt -> size_multiplier_x2 ) >> 1 ;
854
+ return (bpl * height * multiplier ) >> 1 ;
839
855
}
840
856
}
841
857
@@ -1413,12 +1429,12 @@ static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
1413
1429
f -> fmt .pix_mp .height = MIN_H ;
1414
1430
1415
1431
/*
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.
1418
1434
* The selection will reflect any cropping rectangle when only
1419
1435
* some of the pixels are active.
1420
1436
*/
1421
- if (ctx -> dev -> role == DECODE )
1437
+ if (ctx -> dev -> role == DECODE || ctx -> dev -> role == ENCODE_IMAGE )
1422
1438
f -> fmt .pix_mp .height = ALIGN (f -> fmt .pix_mp .height , 16 );
1423
1439
}
1424
1440
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,
1562
1578
v4l2_dbg (1 , debug , & ctx -> dev -> v4l2_dev , "Calulated bpl as %u, size %u\n" ,
1563
1579
q_data -> bytesperline , q_data -> sizeimage );
1564
1580
1565
- if (ctx -> dev -> role == DECODE &&
1581
+ if (( ctx -> dev -> role == DECODE || ctx -> dev -> role == ENCODE_IMAGE ) &&
1566
1582
q_data -> fmt -> flags & V4L2_FMT_FLAG_COMPRESSED &&
1567
1583
q_data -> crop_width && q_data -> height ) {
1568
1584
/*
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.
1571
1588
* GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
1572
1589
* nor set up a resolution on the output side, therefore
1573
1590
* 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,
1707
1724
switch (s -> type ) {
1708
1725
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
1709
1726
/* CAPTURE on encoder is not valid. */
1710
- if (ctx -> dev -> role == ENCODE )
1727
+ if (ctx -> dev -> role == ENCODE || ctx -> dev -> role == ENCODE_IMAGE )
1711
1728
return - EINVAL ;
1712
1729
q_data = & ctx -> q_data [V4L2_M2M_DST ];
1713
1730
break ;
@@ -1750,6 +1767,7 @@ static int vidioc_g_selection(struct file *file, void *priv,
1750
1767
}
1751
1768
break ;
1752
1769
case ENCODE :
1770
+ case ENCODE_IMAGE :
1753
1771
switch (s -> target ) {
1754
1772
case V4L2_SEL_TGT_CROP_DEFAULT :
1755
1773
case V4L2_SEL_TGT_CROP_BOUNDS :
@@ -1832,7 +1850,7 @@ static int vidioc_s_selection(struct file *file, void *priv,
1832
1850
switch (s -> type ) {
1833
1851
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
1834
1852
/* CAPTURE on encoder is not valid. */
1835
- if (ctx -> dev -> role == ENCODE )
1853
+ if (ctx -> dev -> role == ENCODE || ctx -> dev -> role == ENCODE_IMAGE )
1836
1854
return - EINVAL ;
1837
1855
q_data = & ctx -> q_data [V4L2_M2M_DST ];
1838
1856
break ;
@@ -1868,6 +1886,7 @@ static int vidioc_s_selection(struct file *file, void *priv,
1868
1886
}
1869
1887
break ;
1870
1888
case ENCODE :
1889
+ case ENCODE_IMAGE :
1871
1890
switch (s -> target ) {
1872
1891
case V4L2_SEL_TGT_CROP :
1873
1892
/* Only support crop from (0,0) */
@@ -2250,6 +2269,18 @@ static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
2250
2269
sizeof (u32_value ));
2251
2270
break ;
2252
2271
}
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
+
2253
2284
2254
2285
default :
2255
2286
v4l2_err (& ctx -> dev -> v4l2_dev , "Invalid control\n" );
@@ -2348,7 +2379,7 @@ static int vidioc_try_encoder_cmd(struct file *file, void *priv,
2348
2379
{
2349
2380
struct bcm2835_codec_ctx * ctx = file2ctx (file );
2350
2381
2351
- if (ctx -> dev -> role != ENCODE )
2382
+ if (ctx -> dev -> role != ENCODE && ctx -> dev -> role != ENCODE_IMAGE )
2352
2383
return - EINVAL ;
2353
2384
2354
2385
switch (cmd -> cmd ) {
@@ -2559,6 +2590,14 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
2559
2590
MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS ,
2560
2591
& params ,
2561
2592
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 ));
2562
2601
}
2563
2602
2564
2603
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)
2587
2626
goto destroy_component ;
2588
2627
}
2589
2628
2590
- if (dev -> role == ENCODE ) {
2629
+ if (dev -> role == ENCODE || dev -> role == ENCODE_IMAGE ) {
2591
2630
u32 param = 1 ;
2592
2631
2593
2632
if (ctx -> q_data [V4L2_M2M_SRC ].sizeimage <
@@ -2596,19 +2635,21 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
2596
2635
ctx -> q_data [V4L2_M2M_SRC ].sizeimage ,
2597
2636
ctx -> component -> output [0 ].minimum_buffer .size );
2598
2637
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
+ }
2612
2653
/*
2613
2654
* Avoid fragmenting the buffers over multiple frames (unless
2614
2655
* the frame is bigger than the whole buffer)
@@ -3238,6 +3279,23 @@ static int bcm2835_codec_open(struct file *file)
3238
3279
v4l2_ctrl_handler_init (hdl , 0 );
3239
3280
}
3240
3281
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 ;
3241
3299
}
3242
3300
3243
3301
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,
3515
3573
function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER ;
3516
3574
video_nr = deinterlace_video_nr ;
3517
3575
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 ;
3518
3582
default :
3519
3583
ret = - EINVAL ;
3520
3584
goto unreg_dev ;
@@ -3614,6 +3678,10 @@ static int bcm2835_codec_probe(struct platform_device *pdev)
3614
3678
if (ret )
3615
3679
goto out ;
3616
3680
3681
+ ret = bcm2835_codec_create (drv , & drv -> encode_image , ENCODE_IMAGE );
3682
+ if (ret )
3683
+ goto out ;
3684
+
3617
3685
/* Register the media device node */
3618
3686
if (media_device_register (mdev ) < 0 )
3619
3687
goto out ;
@@ -3623,6 +3691,10 @@ static int bcm2835_codec_probe(struct platform_device *pdev)
3623
3691
return 0 ;
3624
3692
3625
3693
out :
3694
+ if (drv -> encode_image ) {
3695
+ bcm2835_codec_destroy (drv -> encode_image );
3696
+ drv -> encode_image = NULL ;
3697
+ }
3626
3698
if (drv -> deinterlace ) {
3627
3699
bcm2835_codec_destroy (drv -> deinterlace );
3628
3700
drv -> deinterlace = NULL ;
@@ -3648,6 +3720,8 @@ static int bcm2835_codec_remove(struct platform_device *pdev)
3648
3720
3649
3721
media_device_unregister (& drv -> mdev );
3650
3722
3723
+ bcm2835_codec_destroy (drv -> encode_image );
3724
+
3651
3725
bcm2835_codec_destroy (drv -> deinterlace );
3652
3726
3653
3727
bcm2835_codec_destroy (drv -> isp );
0 commit comments