diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c index af347cd80964b7..48915fdeb01a9a 100644 --- a/drivers/media/platform/bcm2835/bcm2835-camera.c +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c @@ -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 @@ -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) @@ -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, @@ -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; @@ -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]; @@ -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); @@ -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 { @@ -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) { @@ -1122,6 +1151,7 @@ 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; @@ -1129,10 +1159,10 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev, 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); } } @@ -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, @@ -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) @@ -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; @@ -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", @@ -1569,8 +1612,9 @@ 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; } @@ -1578,9 +1622,9 @@ static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev, 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) @@ -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, diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h index 4ddd687b12565f..7fe9f658a92704 100644 --- a/drivers/media/platform/bcm2835/bcm2835-camera.h +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h @@ -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, @@ -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; diff --git a/drivers/media/platform/bcm2835/controls.c b/drivers/media/platform/bcm2835/controls.c index 9a40bd01a8f86d..dd1186b5d4596d 100644 --- a/drivers/media/platform/bcm2835/controls.c +++ b/drivers/media/platform/bcm2835/controls.c @@ -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, @@ -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) diff --git a/drivers/media/platform/bcm2835/mmal-encodings.h b/drivers/media/platform/bcm2835/mmal-encodings.h index 764bb12fb53f98..024d620dc1dfda 100644 --- a/drivers/media/platform/bcm2835/mmal-encodings.h +++ b/drivers/media/platform/bcm2835/mmal-encodings.h @@ -12,6 +12,8 @@ * Simon Mellor * Luke Diamand */ +#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') @@ -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 */ diff --git a/drivers/media/platform/bcm2835/mmal-parameters.h b/drivers/media/platform/bcm2835/mmal-parameters.h index 089f949b00b0f7..aa0fd180271b1b 100644 --- a/drivers/media/platform/bcm2835/mmal-parameters.h +++ b/drivers/media/platform/bcm2835/mmal-parameters.h @@ -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 */