Re: [RFC PATCH v3 07/11] [media] vimc: cap: Support several image formats
On 06/03/2017 04:58 AM, Helen Koike wrote: Allow user space to change the image format as the frame size, the pixel format, colorspace, quantization, field YCbCr encoding and the transfer function Signed-off-by: Helen Koike --- Changes in v3: [media] vimc: cap: Support several image formats - use *_DEFAULT macros for colorimetry in the default format - clamp height and width of the image by an even value - is user try to set colorspace to an invalid format, set all colorimetry parameters to _DEFAULT - remove V4L2_FMT_FLAG_COMPRESSED from vimc_cap_enum_fmt_vid_cap - remove V4L2_BUF_TYPE_VIDEO_CAPTURE from vimc_cap_enum_fmt_vid_cap - increase step_width and step_height to 2 instead of 1 - remove link validate function, use the one in vimc-common.c Changes in v2: [media] vimc: cap: Support several image formats - this is a new commit in the serie (the old one was splitted in two) - allow user space to change all fields from struct v4l2_pix_format (e.g. colospace, quantization, field, xfer_func, ycbcr_enc) - link_validate and try_fmt: also checks colospace, quantization, field, xfer_func, ycbcr_enc - add struct v4l2_pix_format fmt_default - add enum_framesizes - enum_fmt_vid_cap: enumerate all formats from vimc_pix_map_table - add mode dev_dbg --- drivers/media/platform/vimc/vimc-capture.c | 131 + 1 file changed, 115 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 5bdecd1..e943267 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -40,6 +40,14 @@ struct vimc_cap_device { struct media_pipeline pipe; }; +static const struct v4l2_pix_format fmt_default = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_RGB24, + .field = V4L2_FIELD_NONE, + .colorspace = V4L2_COLORSPACE_SRGB, +}; + struct vimc_cap_buffer { /* * struct vb2_v4l2_buffer must be the first element @@ -73,7 +81,7 @@ static void vimc_cap_get_format(struct vimc_ent_device *ved, *fmt = vcap->format; } -static int vimc_cap_fmt_vid_cap(struct file *file, void *priv, +static int vimc_cap_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct vimc_cap_device *vcap = video_drvdata(file); @@ -83,16 +91,112 @@ static int vimc_cap_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct v4l2_pix_format *format = &f->fmt.pix; + const struct vimc_pix_map *vpix; + + format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH, + VIMC_FRAME_MAX_WIDTH) & ~1; + format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT, +VIMC_FRAME_MAX_HEIGHT) & ~1; + + /* Don't accept a pixelformat that is not on the table */ + vpix = vimc_pix_map_by_pixelformat(format->pixelformat); + if (!vpix) { + format->pixelformat = fmt_default.pixelformat; + vpix = vimc_pix_map_by_pixelformat(format->pixelformat); + } + /* TODO: Add support for custom bytesperline values */ + format->bytesperline = format->width * vpix->bpp; + format->sizeimage = format->bytesperline * format->height; + + if (format->field == V4L2_FIELD_ANY) + format->field = fmt_default.field; + + if (format->colorspace == V4L2_COLORSPACE_DEFAULT) + format->colorspace = fmt_default.colorspace; + + /* Check if values are out of range */ + if (format->colorspace > V4L2_COLORSPACE_DCI_P3) { + format->colorspace = fmt_default.colorspace; + format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + format->quantization = V4L2_QUANTIZATION_DEFAULT; + format->xfer_func = V4L2_XFER_FUNC_DEFAULT; + } + if (format->ycbcr_enc > V4L2_YCBCR_ENC_SMPTE240M) + format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + if (format->quantization > V4L2_QUANTIZATION_LIM_RANGE) + format->quantization = V4L2_QUANTIZATION_DEFAULT; + if (format->xfer_func > V4L2_XFER_FUNC_SMPTE2084) + format->xfer_func = V4L2_XFER_FUNC_DEFAULT; You might want to move this to common, since the sensor has the same code. + return 0; +} + +static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct vimc_cap_device *vcap = video_drvdata(file); + + /* Do not change the format while stream is on */ + if (vb2_is_busy(&vcap->queue)) +
[RFC PATCH v3 07/11] [media] vimc: cap: Support several image formats
Allow user space to change the image format as the frame size, the pixel format, colorspace, quantization, field YCbCr encoding and the transfer function Signed-off-by: Helen Koike --- Changes in v3: [media] vimc: cap: Support several image formats - use *_DEFAULT macros for colorimetry in the default format - clamp height and width of the image by an even value - is user try to set colorspace to an invalid format, set all colorimetry parameters to _DEFAULT - remove V4L2_FMT_FLAG_COMPRESSED from vimc_cap_enum_fmt_vid_cap - remove V4L2_BUF_TYPE_VIDEO_CAPTURE from vimc_cap_enum_fmt_vid_cap - increase step_width and step_height to 2 instead of 1 - remove link validate function, use the one in vimc-common.c Changes in v2: [media] vimc: cap: Support several image formats - this is a new commit in the serie (the old one was splitted in two) - allow user space to change all fields from struct v4l2_pix_format (e.g. colospace, quantization, field, xfer_func, ycbcr_enc) - link_validate and try_fmt: also checks colospace, quantization, field, xfer_func, ycbcr_enc - add struct v4l2_pix_format fmt_default - add enum_framesizes - enum_fmt_vid_cap: enumerate all formats from vimc_pix_map_table - add mode dev_dbg --- drivers/media/platform/vimc/vimc-capture.c | 131 + 1 file changed, 115 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 5bdecd1..e943267 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -40,6 +40,14 @@ struct vimc_cap_device { struct media_pipeline pipe; }; +static const struct v4l2_pix_format fmt_default = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_RGB24, + .field = V4L2_FIELD_NONE, + .colorspace = V4L2_COLORSPACE_SRGB, +}; + struct vimc_cap_buffer { /* * struct vb2_v4l2_buffer must be the first element @@ -73,7 +81,7 @@ static void vimc_cap_get_format(struct vimc_ent_device *ved, *fmt = vcap->format; } -static int vimc_cap_fmt_vid_cap(struct file *file, void *priv, +static int vimc_cap_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct vimc_cap_device *vcap = video_drvdata(file); @@ -83,16 +91,112 @@ static int vimc_cap_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct v4l2_pix_format *format = &f->fmt.pix; + const struct vimc_pix_map *vpix; + + format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH, + VIMC_FRAME_MAX_WIDTH) & ~1; + format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT, +VIMC_FRAME_MAX_HEIGHT) & ~1; + + /* Don't accept a pixelformat that is not on the table */ + vpix = vimc_pix_map_by_pixelformat(format->pixelformat); + if (!vpix) { + format->pixelformat = fmt_default.pixelformat; + vpix = vimc_pix_map_by_pixelformat(format->pixelformat); + } + /* TODO: Add support for custom bytesperline values */ + format->bytesperline = format->width * vpix->bpp; + format->sizeimage = format->bytesperline * format->height; + + if (format->field == V4L2_FIELD_ANY) + format->field = fmt_default.field; + + if (format->colorspace == V4L2_COLORSPACE_DEFAULT) + format->colorspace = fmt_default.colorspace; + + /* Check if values are out of range */ + if (format->colorspace > V4L2_COLORSPACE_DCI_P3) { + format->colorspace = fmt_default.colorspace; + format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + format->quantization = V4L2_QUANTIZATION_DEFAULT; + format->xfer_func = V4L2_XFER_FUNC_DEFAULT; + } + if (format->ycbcr_enc > V4L2_YCBCR_ENC_SMPTE240M) + format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + if (format->quantization > V4L2_QUANTIZATION_LIM_RANGE) + format->quantization = V4L2_QUANTIZATION_DEFAULT; + if (format->xfer_func > V4L2_XFER_FUNC_SMPTE2084) + format->xfer_func = V4L2_XFER_FUNC_DEFAULT; + return 0; +} + +static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct vimc_cap_device *vcap = video_drvdata(file); + + /* Do not change the format while stream is on */ + if (vb2_is_busy(&vcap->queue)) + return -EBUSY; + + vimc_cap_try_fmt_vid_cap(file, priv, f); + + dev_dbg(vcap->vdev.v4l2_dev->dev, "%s: format update: " +