Re: [RFC PATCH v3 07/11] [media] vimc: cap: Support several image formats

2017-06-12 Thread Hans Verkuil

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

2017-06-02 Thread Helen Koike
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: "
+