Skip to content

V4L2 padding removal, and support for H264_I_PERIOD #598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 21, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 82 additions & 35 deletions drivers/media/platform/bcm2835/bcm2835-camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ int bcm2835_v4l2_debug;
module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");

int max_video_width = MAX_VIDEO_MODE_WIDTH;
int max_video_height = MAX_VIDEO_MODE_HEIGHT;
module_param(max_video_width, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(max_video_width, "Threshold for video mode");
module_param(max_video_height, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(max_video_height, "Threshold for video mode");

static struct bm2835_mmal_dev *gdev; /* global device data */

#define FPS_MIN 1
Expand Down Expand Up @@ -171,6 +178,14 @@ static struct mmal_fmt formats[] = {
.depth = 12,
.mmal_component = MMAL_COMPONENT_CAMERA,
},
{
.name = "RGB32 (BE)",
.fourcc = V4L2_PIX_FMT_BGR32,
.flags = 0,
.mmal = MMAL_ENCODING_BGRA,
.depth = 32,
.mmal_component = MMAL_COMPONENT_CAMERA,
},
};

static struct mmal_fmt *get_format(struct v4l2_format *f)
Expand Down Expand Up @@ -828,20 +843,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.height = dev->capture.height;
f->fmt.pix.field = V4L2_FIELD_NONE;
f->fmt.pix.pixelformat = dev->capture.fmt->fourcc;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * dev->capture.fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG
&& f->fmt.pix.sizeimage < (100 << 10)) {
/* Need a minimum size for JPEG to account for EXIF. */
f->fmt.pix.sizeimage = (100 << 10);
}
f->fmt.pix.bytesperline = dev->capture.stride;
f->fmt.pix.sizeimage = dev->capture.buffersize;

if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_YUYV ||
dev->capture.fmt->fourcc == V4L2_PIX_FMT_UYVY)
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
else
if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24)
f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
else
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
f->fmt.pix.priv = 0;

v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
Expand All @@ -865,21 +873,35 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
}

f->fmt.pix.field = V4L2_FIELD_NONE;
/* image must be a multiple of 32 pixels wide and 16 lines high */
v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 5,
&f->fmt.pix.height, 32, MAX_HEIGHT, 4, 0);
f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
if (f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)

v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Clipping/aligning %dx%d format %08X\n",
f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat);

v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 1,
&f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 1, 0);
f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth)>>3;

/* Image buffer has to be padded to allow for alignment, even though
* we then remove that padding before delivering the buffer.
*/
f->fmt.pix.sizeimage = ((f->fmt.pix.height+15)&~15) *
(((f->fmt.pix.width+31)&~31) * mfmt->depth) >> 3;

if ((mfmt->flags & V4L2_FMT_FLAG_COMPRESSED) &&
f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
f->fmt.pix.sizeimage = MIN_BUFFER_SIZE;

if (mfmt->fourcc == V4L2_PIX_FMT_YUYV ||
mfmt->fourcc == V4L2_PIX_FMT_UYVY)
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
else
if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24)
f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
else
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
f->fmt.pix.priv = 0;

v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Now %dx%d format %08X\n",
f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat);

v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
__func__);
return 0;
Expand Down Expand Up @@ -917,8 +939,8 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
switch (mfmt->mmal_component) {
case MMAL_COMPONENT_CAMERA:
/* Make a further decision on port based on resolution */
if (f->fmt.pix.width <= MAX_VIDEO_MODE_WIDTH
&& f->fmt.pix.height <= MAX_VIDEO_MODE_HEIGHT)
if (f->fmt.pix.width <= max_video_width
&& f->fmt.pix.height <= max_video_height)
camera_port = port =
&dev->component[MMAL_COMPONENT_CAMERA]->
output[MMAL_CAMERA_PORT_VIDEO];
Expand Down Expand Up @@ -962,6 +984,7 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
camera_port->es.video.crop.height = f->fmt.pix.height;
camera_port->es.video.frame_rate.num = 0;
camera_port->es.video.frame_rate.den = 1;
camera_port->es.video.color_space = MMAL_COLOR_SPACE_JPEG_JFIF;

ret = vchiq_mmal_port_set_format(dev->instance, camera_port);

Expand Down Expand Up @@ -1014,7 +1037,9 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,

if (ret) {
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"%s failed to set format\n", __func__);
"%s failed to set format %dx%d %08X\n", __func__,
f->fmt.pix.width, f->fmt.pix.height,
f->fmt.pix.pixelformat);
/* ensure capture is not going to be tried */
dev->capture.port = NULL;
} else {
Expand Down Expand Up @@ -1071,8 +1096,12 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
if (ret)
v4l2_dbg(1, bcm2835_v4l2_debug,
&dev->v4l2_dev,
"%s failed to set format\n",
__func__);
"%s failed to set format %dx%d fmt %08X\n",
__func__,
f->fmt.pix.width,
f->fmt.pix.height,
f->fmt.pix.pixelformat
);
}

if (!ret) {
Expand Down Expand Up @@ -1122,17 +1151,18 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
dev->capture.stride = f->fmt.pix.bytesperline;
dev->capture.width = camera_port->es.video.crop.width;
dev->capture.height = camera_port->es.video.crop.height;
dev->capture.buffersize = port->current_buffer.size;

/* select port for capture */
dev->capture.port = port;
dev->capture.camera_port = camera_port;
dev->capture.encode_component = encode_component;
v4l2_dbg(1, bcm2835_v4l2_debug,
&dev->v4l2_dev,
"Set dev->capture.fmt %08X, %dx%d, stride %d",
"Set dev->capture.fmt %08X, %dx%d, stride %d, size %d",
port->format.encoding,
dev->capture.width, dev->capture.height,
dev->capture.stride);
dev->capture.stride, dev->capture.buffersize);
}
}

Expand Down Expand Up @@ -1352,8 +1382,8 @@ static int set_camera_parameters(struct vchiq_mmal_instance *instance,
.max_stills_h = MAX_HEIGHT,
.stills_yuv422 = 1,
.one_shot_stills = 1,
.max_preview_video_w = 1920,
.max_preview_video_h = 1088,
.max_preview_video_w = max_video_width,
.max_preview_video_h = max_video_height,
.num_preview_video_frames = 3,
.stills_capture_circular_buffer_height = 0,
.fast_preview_resume = 0,
Expand All @@ -1371,6 +1401,7 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
{
int ret;
struct mmal_es_format *format;
u32 bool_true = 1;

ret = vchiq_mmal_init(&dev->instance);
if (ret < 0)
Expand Down Expand Up @@ -1425,6 +1456,12 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
format->es->video.frame_rate.num = 0; /* Rely on fps_range */
format->es->video.frame_rate.den = 1;

vchiq_mmal_port_parameter_set(dev->instance,
&dev->component[MMAL_COMPONENT_CAMERA]->
output[MMAL_CAMERA_PORT_VIDEO],
MMAL_PARAMETER_NO_IMAGE_PADDING,
&bool_true, sizeof(bool_true));

format =
&dev->component[MMAL_COMPONENT_CAMERA]->
output[MMAL_CAMERA_PORT_CAPTURE].format;
Expand All @@ -1448,6 +1485,12 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;

vchiq_mmal_port_parameter_set(dev->instance,
&dev->component[MMAL_COMPONENT_CAMERA]->
output[MMAL_CAMERA_PORT_CAPTURE],
MMAL_PARAMETER_NO_IMAGE_PADDING,
&bool_true, sizeof(bool_true));

/* get the preview component ready */
ret = vchiq_mmal_component_init(
dev->instance, "ril.video_render",
Expand Down Expand Up @@ -1569,18 +1612,19 @@ static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
if (ret < 0)
return ret;

v4l2_info(vfd->v4l2_dev, "V4L2 device registered as %s\n",
video_device_node_name(vfd));
v4l2_info(vfd->v4l2_dev,
"V4L2 device registered as %s - stills mode > %dx%d\n",
video_device_node_name(vfd), max_video_width, max_video_height);

return 0;
}

static struct v4l2_format default_v4l2_format = {
.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG,
.fmt.pix.width = 1024,
.fmt.pix.bytesperline = 1024 * 3 / 2,
.fmt.pix.bytesperline = 1024,
.fmt.pix.height = 768,
.fmt.pix.sizeimage = 1<<18,
.fmt.pix.sizeimage = 1024*768,
};

static int __init bm2835_mmal_init(void)
Expand Down Expand Up @@ -1643,6 +1687,9 @@ static int __init bm2835_mmal_init(void)
if (ret < 0)
goto unreg_dev;

/* Really want to call vidioc_s_fmt_vid_cap with the default
* format, but currently the APIs don't join up.
*/
ret = mmal_setup_components(dev, &default_v4l2_format);
if (ret < 0) {
v4l2_err(&dev->v4l2_dev,
Expand Down
3 changes: 2 additions & 1 deletion drivers/media/platform/bcm2835/bcm2835-camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* core driver device
*/

#define V4L2_CTRL_COUNT 27 /* number of v4l controls */
#define V4L2_CTRL_COUNT 28 /* number of v4l controls */

enum {
MMAL_COMPONENT_CAMERA = 0,
Expand Down Expand Up @@ -70,6 +70,7 @@ struct bm2835_mmal_dev {
unsigned int width; /* width */
unsigned int height; /* height */
unsigned int stride; /* stride */
unsigned int buffersize; /* buffer size with padding */
struct mmal_fmt *fmt;
struct v4l2_fract timeperframe;

Expand Down
11 changes: 9 additions & 2 deletions drivers/media/platform/bcm2835/controls.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,8 +966,8 @@ static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
},
/* {
0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
},
*/ {
}, */
{
V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
MMAL_PARAMETER_EXPOSURE_MODE,
Expand Down Expand Up @@ -1149,6 +1149,13 @@ static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
&ctrl_set_scene_mode,
false
},
{
V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, MMAL_CONTROL_TYPE_STD,
1, 1000, 60, 1, NULL,
MMAL_PARAMETER_INTRAPERIOD,
&ctrl_set_video_encode_param_output,
false
},
};

int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
Expand Down
33 changes: 33 additions & 0 deletions drivers/media/platform/bcm2835/mmal-encodings.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* Simon Mellor <[email protected]>
* Luke Diamand <[email protected]>
*/
#ifndef MMAL_ENCODINGS_H
#define MMAL_ENCODINGS_H

#define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4')
#define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3')
Expand Down Expand Up @@ -92,3 +94,34 @@
#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1')
/** Implicitly delineated NAL units without emulation prevention */
#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ')


/** \defgroup MmalColorSpace List of pre-defined video color spaces
* This defines a list of common color spaces. This list isn't exhaustive and
* is only provided as a convenience to avoid clients having to use FourCC
* codes directly. However components are allowed to define and use their own
* FourCC codes.
*/
/* @{ */

/** Unknown color space */
#define MMAL_COLOR_SPACE_UNKNOWN 0
/** ITU-R BT.601-5 [SDTV] */
#define MMAL_COLOR_SPACE_ITUR_BT601 MMAL_FOURCC('Y', '6', '0', '1')
/** ITU-R BT.709-3 [HDTV] */
#define MMAL_COLOR_SPACE_ITUR_BT709 MMAL_FOURCC('Y', '7', '0', '9')
/** JPEG JFIF */
#define MMAL_COLOR_SPACE_JPEG_JFIF MMAL_FOURCC('Y', 'J', 'F', 'I')
/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
#define MMAL_COLOR_SPACE_FCC MMAL_FOURCC('Y', 'F', 'C', 'C')
/** Society of Motion Picture and Television Engineers 240M (1999) */
#define MMAL_COLOR_SPACE_SMPTE240M MMAL_FOURCC('Y', '2', '4', '0')
/** ITU-R BT.470-2 System M */
#define MMAL_COLOR_SPACE_BT470_2_M MMAL_FOURCC('Y', '_', '_', 'M')
/** ITU-R BT.470-2 System BG */
#define MMAL_COLOR_SPACE_BT470_2_BG MMAL_FOURCC('Y', '_', 'B', 'G')
/** JPEG JFIF, but with 16..255 luma */
#define MMAL_COLOR_SPACE_JFIF_Y16_255 MMAL_FOURCC('Y', 'Y', '1', '6')
/* @} MmalColorSpace List */

#endif /* MMAL_ENCODINGS_H */
3 changes: 2 additions & 1 deletion drivers/media/platform/bcm2835/mmal-parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ enum mmal_parameter_common_type {
MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */
MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */
MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */
MMAL_PARAMETER_SYSTEM_TIME /**< MMAL_PARAMETER_UINT64_T */
MMAL_PARAMETER_SYSTEM_TIME, /**< MMAL_PARAMETER_UINT64_T */
MMAL_PARAMETER_NO_IMAGE_PADDING /**< MMAL_PARAMETER_BOOLEAN_T */
};

/* camera parameters */
Expand Down