RE: [PATCH 1/2] media: imx-jpeg: Implement g_selection and s_selection

From: Ming Qian
Date: Tue Sep 20 2022 - 20:26:28 EST


>Hi Ming,
>
>On 01.08.2022 13:29, Ming Qian wrote:
>> The codec can support any image size WxH, with arbitrary W (image
>> width) and H (image height) dimensions.
>>
>> But it requires buffer alignment,
>> so driver can report the aligned resolution through the g_fmt, and
>> report the actual resolution through the g_selection.
>>
>> For encoder, it even support to encode a smaller jpeg than the
>> original picture through s_selection api.
>
>Please add a mention here that "For the decoder, we do not support cropping
>a portion smaller than the original picture, due to hardware limitations
>(wrapper side)."
>

Hi Mirela,
OK, I'll add the message


>>
>> Signed-off-by: Ming Qian <ming.qian@xxxxxxx>
>> ---
>> .../media/platform/nxp/imx-jpeg/mxc-jpeg.c | 327 +++++++++++-------
>> .../media/platform/nxp/imx-jpeg/mxc-jpeg.h | 1 +
>> 2 files changed, 208 insertions(+), 120 deletions(-)
>>
>> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
>> b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
>> index ec13394bdddd..89f432b8c6df 100644
>> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
>> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
>> @@ -924,8 +924,8 @@ static void mxc_jpeg_config_enc_desc(struct
>vb2_buffer *out_buf,
>> jpeg->slot_data[slot].cfg_stream_size =
>> mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
>> q_data->fmt->fourcc,
>> - q_data->w,
>> - q_data->h);
>> + q_data->crop.width,
>> + q_data->crop.height);
>>
>> /* chain the config descriptor with the encoding descriptor */
>> cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
>@@
>> -942,11 +942,13 @@ static void mxc_jpeg_config_enc_desc(struct
>vb2_buffer *out_buf,
>> desc->next_descpt_ptr = 0; /* end of chain */
>>
>> /* use adjusted resolution for CAST IP job */
>> - w = q_data->w_adjusted;
>> - h = q_data->h_adjusted;
>> + w = q_data->crop.width;
>> + h = q_data->crop.height;
>> + v4l_bound_align_image(&w, w, MXC_JPEG_MAX_WIDTH, q_data-
>>fmt->h_align,
>> + &h, h, MXC_JPEG_MAX_HEIGHT, q_data->fmt-
>>v_align, 0);
>> mxc_jpeg_set_res(desc, w, h);
>> - mxc_jpeg_set_line_pitch(desc, w * (q_data->fmt->depth / 8));
>> - mxc_jpeg_set_bufsize(desc, desc->line_pitch * h);
>> + mxc_jpeg_set_line_pitch(desc, q_data->bytesperline[0]);
>> + mxc_jpeg_set_bufsize(desc, q_data->sizeimage[0]);
>> img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data->fmt->fourcc);
>> if (img_fmt == MXC_JPEG_INVALID)
>> dev_err(jpeg->dev, "No valid image format detected\n"); @@
>-995,6
>> +997,10 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
>> q_data_cap->fmt = jpeg_src_buf->fmt;
>> q_data_cap->w_adjusted = q_data_cap->w;
>> q_data_cap->h_adjusted = q_data_cap->h;
>> + q_data_cap->crop.left = 0;
>> + q_data_cap->crop.top = 0;
>> + q_data_cap->crop.width = jpeg_src_buf->w;
>> + q_data_cap->crop.height = jpeg_src_buf->h;
>>
>> /*
>> * align up the resolution for CAST IP, @@ -1007,7 +1013,7
>@@
>> static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
>> &q_data_cap->h_adjusted,
>> q_data_cap->h_adjusted, /* adjust up */
>> MXC_JPEG_MAX_HEIGHT,
>> - 0,
>> + q_data_cap->fmt->v_align,
>> 0);
>>
>> /* setup bytesperline/sizeimage for capture queue */ @@ -
>1016,6
>> +1022,7 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
>> notify_src_chg(ctx);
>> ctx->source_change = 1;
>> }
>> +
>> return ctx->source_change ? true : false;
>> }
>>
>> @@ -1201,30 +1208,18 @@ static int mxc_jpeg_queue_setup(struct
>vb2_queue *q,
>> {
>> struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
>> struct mxc_jpeg_q_data *q_data = NULL;
>> - struct mxc_jpeg_q_data tmp_q;
>> int i;
>>
>> q_data = mxc_jpeg_get_q_data(ctx, q->type);
>> if (!q_data)
>> return -EINVAL;
>>
>> - tmp_q.fmt = q_data->fmt;
>> - tmp_q.w = q_data->w_adjusted;
>> - tmp_q.h = q_data->h_adjusted;
>> - for (i = 0; i < MXC_JPEG_MAX_PLANES; i++) {
>> - tmp_q.bytesperline[i] = q_data->bytesperline[i];
>> - tmp_q.sizeimage[i] = q_data->sizeimage[i];
>> - }
>> - mxc_jpeg_sizeimage(&tmp_q);
>> - for (i = 0; i < MXC_JPEG_MAX_PLANES; i++)
>> - tmp_q.sizeimage[i] = max(tmp_q.sizeimage[i], q_data-
>>sizeimage[i]);
>> -
>
>This is an undo from patch "Align upwards buffer size", so please add a
>"Fixes:..." for it in the commit description.
>
>> /* Handle CREATE_BUFS situation - *nplanes != 0 */
>> if (*nplanes) {
>> if (*nplanes != q_data->fmt->colplanes)
>> return -EINVAL;
>> for (i = 0; i < *nplanes; i++) {
>> - if (sizes[i] < tmp_q.sizeimage[i])
>> + if (sizes[i] < q_data->sizeimage[i])
>> return -EINVAL;
>> }
>> return 0;
>> @@ -1233,7 +1228,7 @@ static int mxc_jpeg_queue_setup(struct
>vb2_queue *q,
>> /* Handle REQBUFS situation */
>> *nplanes = q_data->fmt->colplanes;
>> for (i = 0; i < *nplanes; i++)
>> - sizes[i] = tmp_q.sizeimage[i];
>> + sizes[i] = q_data->sizeimage[i];
>>
>> return 0;
>> }
>> @@ -1366,17 +1361,17 @@ static void mxc_jpeg_bytesperline(struct
>mxc_jpeg_q_data *q, u32 precision)
>> * applies to the first plane and is divided by the same factor
>> * as the width field for the other planes
>> */
>> - q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8);
>> + q->bytesperline[0] = q->w_adjusted *
>DIV_ROUND_UP(precision, 8);
>> q->bytesperline[1] = q->bytesperline[0];
>> } else if (q->fmt->subsampling ==
>V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
>> - q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8) * 2;
>> + q->bytesperline[0] = q->w_adjusted *
>DIV_ROUND_UP(precision, 8) *
>> +2;
>> q->bytesperline[1] = 0;
>> } else if (q->fmt->subsampling ==
>V4L2_JPEG_CHROMA_SUBSAMPLING_444) {
>> - q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8) * q-
>>fmt->nc;
>> + q->bytesperline[0] = q->w_adjusted *
>DIV_ROUND_UP(precision, 8) *
>> +q->fmt->nc;
>> q->bytesperline[1] = 0;
>> } else {
>> /* grayscale */
>> - q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8);
>> + q->bytesperline[0] = q->w_adjusted *
>DIV_ROUND_UP(precision, 8);
>> q->bytesperline[1] = 0;
>> }
>> }
>> @@ -1395,7 +1390,7 @@ static void mxc_jpeg_sizeimage(struct
>mxc_jpeg_q_data *q)
>> /* jpeg stream size must be multiple of 1K */
>> q->sizeimage[0] = ALIGN(q->sizeimage[0], 1024);
>> } else {
>> - q->sizeimage[0] = q->bytesperline[0] * q->h;
>> + q->sizeimage[0] = q->bytesperline[0] * q->h_adjusted;
>> q->sizeimage[1] = 0;
>> if (q->fmt->fourcc == V4L2_PIX_FMT_NV12M)
>> q->sizeimage[1] = q->sizeimage[0] / 2; @@ -1619,6
>+1614,10 @@
>> static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)
>> q[i]->h = MXC_JPEG_DEFAULT_HEIGHT;
>> q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH;
>> q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT;
>> + q[i]->crop.left = 0;
>> + q[i]->crop.top = 0;
>> + q[i]->crop.width = MXC_JPEG_DEFAULT_WIDTH;
>> + q[i]->crop.height = MXC_JPEG_DEFAULT_HEIGHT;
>> mxc_jpeg_bytesperline(q[i], q[i]->fmt->precision);
>> mxc_jpeg_sizeimage(q[i]);
>> }
>> @@ -1786,55 +1785,84 @@ static int mxc_jpeg_enum_fmt_vid_out(struct
>file *file, void *priv,
>> return 0;
>> }
>>
>> -static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct
>mxc_jpeg_fmt *fmt,
>> - struct mxc_jpeg_ctx *ctx, int q_type)
>> +static u32 mxc_jpeg_get_fmt_type(struct mxc_jpeg_ctx *ctx, u32 type)
>> +{
>> + if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
>> + return V4L2_TYPE_IS_OUTPUT(type) ?
>MXC_JPEG_FMT_TYPE_ENC : MXC_JPEG_FMT_TYPE_RAW;
>> + else
>> + return V4L2_TYPE_IS_CAPTURE(type) ?
>MXC_JPEG_FMT_TYPE_ENC :
>> +MXC_JPEG_FMT_TYPE_RAW; }
>> +
>> +static u32 mxc_jpeg_get_default_fourcc(struct mxc_jpeg_ctx *ctx, u32
>> +type)
>> {
>> + if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
>> + return V4L2_TYPE_IS_OUTPUT(type) ? V4L2_PIX_FMT_JPEG :
>MXC_JPEG_DEFAULT_PFMT;
>> + else
>> + return V4L2_TYPE_IS_CAPTURE(type) ? V4L2_PIX_FMT_JPEG :
>> +MXC_JPEG_DEFAULT_PFMT; }
>> +
>> +static int mxc_jpeg_try_fmt(struct v4l2_format *f,
>> + struct mxc_jpeg_ctx *ctx, struct mxc_jpeg_q_data
>*q_data) {
>> + const struct mxc_jpeg_fmt *fmt;
>> struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
>> struct v4l2_plane_pix_format *pfmt;
>> + u32 fourcc = f->fmt.pix_mp.pixelformat;
>> u32 w = (pix_mp->width < MXC_JPEG_MAX_WIDTH) ?
>> pix_mp->width : MXC_JPEG_MAX_WIDTH;
>> u32 h = (pix_mp->height < MXC_JPEG_MAX_HEIGHT) ?
>> pix_mp->height : MXC_JPEG_MAX_HEIGHT;
>> int i;
>> - struct mxc_jpeg_q_data tmp_q;
>> +
>> + fmt = mxc_jpeg_find_format(ctx, fourcc);
>> + if (!fmt || fmt->flags != mxc_jpeg_get_fmt_type(ctx, f->type)) {
>> + dev_warn(ctx->mxc_jpeg->dev, "Format not
>supported: %c%c%c%c, use the default.\n",
>> + (fourcc & 0xff),
>> + (fourcc >> 8) & 0xff,
>> + (fourcc >> 16) & 0xff,
>> + (fourcc >> 24) & 0xff);
>> + fourcc = mxc_jpeg_get_default_fourcc(ctx, f->type);
>> + fmt = mxc_jpeg_find_format(ctx, fourcc);
>> + if (!fmt)
>> + return -EINVAL;
>> + f->fmt.pix_mp.pixelformat = fourcc;
>> + }
>> + q_data->fmt = fmt;
>>
>> memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
>> pix_mp->field = V4L2_FIELD_NONE;
>> pix_mp->num_planes = fmt->colplanes;
>> pix_mp->pixelformat = fmt->fourcc;
>>
>> - pix_mp->width = w;
>> - pix_mp->height = h;
>> - v4l_bound_align_image(&w,
>> + q_data->w = w;
>> + q_data->h = h;
>> + q_data->w_adjusted = w;
>> + q_data->h_adjusted = h;
>> + v4l_bound_align_image(&q_data->w_adjusted,
>> w, /* adjust upwards*/
>> MXC_JPEG_MAX_WIDTH,
>> fmt->h_align,
>> - &h,
>> + &q_data->h_adjusted,
>> h, /* adjust upwards*/
>> MXC_JPEG_MAX_HEIGHT,
>> - 0,
>> + fmt->v_align,
>> 0);
>> -
>> - /* get user input into the tmp_q */
>> - tmp_q.w = w;
>> - tmp_q.h = h;
>> - tmp_q.fmt = fmt;
>> for (i = 0; i < pix_mp->num_planes; i++) {
>> pfmt = &pix_mp->plane_fmt[i];
>> - tmp_q.bytesperline[i] = pfmt->bytesperline;
>> - tmp_q.sizeimage[i] = pfmt->sizeimage;
>> + q_data->bytesperline[i] = pfmt->bytesperline;
>> + q_data->sizeimage[i] = pfmt->sizeimage;
>> }
>>
>> - /* calculate bytesperline & sizeimage into the tmp_q */
>> - mxc_jpeg_bytesperline(&tmp_q, fmt->precision);
>> - mxc_jpeg_sizeimage(&tmp_q);
>> + /* calculate bytesperline & sizeimage */
>> + mxc_jpeg_bytesperline(q_data, fmt->precision);
>> + mxc_jpeg_sizeimage(q_data);
>>
>> /* adjust user format according to our calculations */
>> for (i = 0; i < pix_mp->num_planes; i++) {
>> pfmt = &pix_mp->plane_fmt[i];
>> memset(pfmt->reserved, 0, sizeof(pfmt->reserved));
>> - pfmt->bytesperline = tmp_q.bytesperline[i];
>> - pfmt->sizeimage = tmp_q.sizeimage[i];
>> + pfmt->bytesperline = q_data->bytesperline[i];
>> + pfmt->sizeimage = q_data->sizeimage[i];
>> }
>>
>> /* fix colorspace information to sRGB for both output & capture */
>> @@ -1848,6 +1876,16 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f,
>const struct mxc_jpeg_fmt *fm
>> */
>> pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;
>>
>> + if (fmt->flags == MXC_JPEG_FMT_TYPE_RAW) {
>> + q_data->crop.left = 0;
>> + q_data->crop.top = 0;
>> + q_data->crop.width = q_data->w;
>> + q_data->crop.height = q_data->h;
>> + }
>> +
>> + pix_mp->width = q_data->w_adjusted;
>> + pix_mp->height = q_data->h_adjusted;
>> +
>> return 0;
>> }
>>
>> @@ -1857,29 +1895,14 @@ static int mxc_jpeg_try_fmt_vid_cap(struct file
>*file, void *priv,
>> struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
>> struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
>> struct device *dev = jpeg->dev;
>> - const struct mxc_jpeg_fmt *fmt;
>> - u32 fourcc = f->fmt.pix_mp.pixelformat;
>> -
>> - int q_type = (jpeg->mode == MXC_JPEG_DECODE) ?
>> - MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
>> + struct mxc_jpeg_q_data tmp_q;
>>
>> if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
>> dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
>> return -EINVAL;
>> }
>>
>> - fmt = mxc_jpeg_find_format(ctx, fourcc);
>> - if (!fmt || fmt->flags != q_type) {
>> - dev_warn(dev, "Format not supported: %c%c%c%c, use the
>default.\n",
>> - (fourcc & 0xff),
>> - (fourcc >> 8) & 0xff,
>> - (fourcc >> 16) & 0xff,
>> - (fourcc >> 24) & 0xff);
>> - f->fmt.pix_mp.pixelformat = (jpeg->mode ==
>MXC_JPEG_DECODE) ?
>> - MXC_JPEG_DEFAULT_PFMT :
>V4L2_PIX_FMT_JPEG;
>> - fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
>> - }
>> - return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
>> + return mxc_jpeg_try_fmt(f, ctx, &tmp_q);
>> }
>>
>> static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv,
>> @@ -1888,88 +1911,55 @@ static int mxc_jpeg_try_fmt_vid_out(struct file
>*file, void *priv,
>> struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
>> struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
>> struct device *dev = jpeg->dev;
>> - const struct mxc_jpeg_fmt *fmt;
>> - u32 fourcc = f->fmt.pix_mp.pixelformat;
>> -
>> - int q_type = (jpeg->mode == MXC_JPEG_ENCODE) ?
>> - MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
>> + struct mxc_jpeg_q_data tmp_q;
>>
>> if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
>> dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
>> return -EINVAL;
>> }
>>
>> - fmt = mxc_jpeg_find_format(ctx, fourcc);
>> - if (!fmt || fmt->flags != q_type) {
>> - dev_warn(dev, "Format not supported: %c%c%c%c, use the
>default.\n",
>> - (fourcc & 0xff),
>> - (fourcc >> 8) & 0xff,
>> - (fourcc >> 16) & 0xff,
>> - (fourcc >> 24) & 0xff);
>> - f->fmt.pix_mp.pixelformat = (jpeg->mode ==
>MXC_JPEG_ENCODE) ?
>> - MXC_JPEG_DEFAULT_PFMT :
>V4L2_PIX_FMT_JPEG;
>> - fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
>> - }
>> - return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
>> + return mxc_jpeg_try_fmt(f, ctx, &tmp_q); }
>
>Lots of changes here, looks cleaner like this, less code duplication.
>Regression tests look ok, hope we did not miss anything.
>
>> +
>> +static void mxc_jpeg_s_parsed_fmt(struct mxc_jpeg_ctx *ctx, struct
>> +v4l2_format *f) {
>> + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
>> + struct mxc_jpeg_q_data *q_data_cap;
>> +
>> + if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE
>|| !V4L2_TYPE_IS_CAPTURE(f->type))
>> + return;
>> + if (!ctx->header_parsed)
>> + return;
>> +
>> + q_data_cap = mxc_jpeg_get_q_data(ctx, f->type);
>> + pix_mp->pixelformat = pix_mp->pixelformat;
>
>What's the purpose of the above line? Was it meant to be q_data_cap->fmt-
>>fourcc?
>
>> + pix_mp->width = q_data_cap->w;
>> + pix_mp->height = q_data_cap->h;
>> }
>>
>> static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx,
>> struct v4l2_format *f)
>> {
>> struct vb2_queue *vq;
>> - struct mxc_jpeg_q_data *q_data = NULL;
>> - struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
>> struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
>> - int i;
>>
>> vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
>> if (!vq)
>> return -EINVAL;
>>
>> - q_data = mxc_jpeg_get_q_data(ctx, f->type);
>> -
>> if (vb2_is_busy(vq)) {
>> v4l2_err(&jpeg->v4l2_dev, "queue busy\n");
>> return -EBUSY;
>> }
>>
>> - q_data->fmt = mxc_jpeg_find_format(ctx, pix_mp->pixelformat);
>> - q_data->w = pix_mp->width;
>> - q_data->h = pix_mp->height;
>> -
>> - q_data->w_adjusted = q_data->w;
>> - q_data->h_adjusted = q_data->h;
>> - /*
>> - * align up the resolution for CAST IP,
>> - * but leave the buffer resolution unchanged
>> - */
>> - v4l_bound_align_image(&q_data->w_adjusted,
>> - q_data->w_adjusted, /* adjust upwards */
>> - MXC_JPEG_MAX_WIDTH,
>> - q_data->fmt->h_align,
>> - &q_data->h_adjusted,
>> - q_data->h_adjusted, /* adjust upwards */
>> - MXC_JPEG_MAX_HEIGHT,
>> - q_data->fmt->v_align,
>> - 0);
>> -
>> - for (i = 0; i < pix_mp->num_planes; i++) {
>> - q_data->bytesperline[i] = pix_mp->plane_fmt[i].bytesperline;
>> - q_data->sizeimage[i] = pix_mp->plane_fmt[i].sizeimage;
>> - }
>> + mxc_jpeg_s_parsed_fmt(ctx, f);
>>
>> - return 0;
>> + return mxc_jpeg_try_fmt(f, ctx, mxc_jpeg_get_q_data(ctx, f->type));
>> }
>>
>> static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
>> struct v4l2_format *f)
>> {
>> - int ret;
>> -
>> - ret = mxc_jpeg_try_fmt_vid_cap(file, priv, f);
>> - if (ret)
>> - return ret;
>> -
>> return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
>> }
>>
>> @@ -1983,10 +1973,6 @@ static int mxc_jpeg_s_fmt_vid_out(struct file *file,
>void *priv,
>> enum v4l2_buf_type cap_type =
>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>> struct v4l2_format fc;
>>
>> - ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
>> - if (ret)
>> - return ret;
>> -
>> ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
>> if (ret)
>> return ret;
>> @@ -2032,6 +2018,10 @@ static int mxc_jpeg_g_fmt_vid(struct file *file,
>void *priv,
>> pix_mp->width = q_data->w;
>> pix_mp->height = q_data->h;
>> pix_mp->field = V4L2_FIELD_NONE;
>> + if (q_data->fmt->flags == MXC_JPEG_FMT_TYPE_RAW) {
>> + pix_mp->width = q_data->w_adjusted;
>> + pix_mp->height = q_data->h_adjusted;
>> + }
>>
>> /* fix colorspace information to sRGB for both output & capture */
>> pix_mp->colorspace = V4L2_COLORSPACE_SRGB; @@ -2048,6
>+2038,100 @@
>> static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,
>> return 0;
>> }
>>
>> +static int mxc_jpeg_dec_g_selection(struct file *file, void *fh,
>> +struct v4l2_selection *s) {
>> + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
>> + struct mxc_jpeg_q_data *q_data_cap;
>> +
>> + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type !=
>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
>> + return -EINVAL;
>> +
>> + q_data_cap = mxc_jpeg_get_q_data(ctx, s->type);
>> +
>> + switch (s->target) {
>
>Acording to:
>https://linuxtv.org/downloads/v4l-dvb-apis/userspace-api/v4l/dev-
>decoder.html?highlight=v4l2_sel_tgt_compose_padded
>
>The following selection targets are supported on CAPTURE:
>
>V4L2_SEL_TGT_CROP_BOUNDS - corresponds to the coded resolution of the
>stream.
>
>V4L2_SEL_TGT_CROP_DEFAULT - the rectangle covering the part of the
>CAPTURE buffer that contains meaningful picture data (visible area); width
>and height will be equal to the visible resolution of the stream.
>
>V4L2_SEL_TGT_CROP - the rectangle within the coded resolution to be output
>to CAPTURE; defaults to V4L2_SEL_TGT_CROP_DEFAULT; read-only on
>hardware without additional compose/scaling capabilities.
>
>> + case V4L2_SEL_TGT_COMPOSE:
>> + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
>> + case V4L2_SEL_TGT_COMPOSE_PADDED:
>
>V4L2_SEL_TGT_COMPOSE_PADDED should also contain paddings, so move it
>below, as discussed internally.
>
>Regards,
>Mirela
>
>> + s->r = q_data_cap->crop;
>> + break;
>> + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
>> + s->r.left = 0;
>> + s->r.top = 0;
>> + s->r.width = q_data_cap->w_adjusted;
>> + s->r.height = q_data_cap->h_adjusted;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int mxc_jpeg_enc_g_selection(struct file *file, void *fh,
>> +struct v4l2_selection *s) {
>> + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
>> + struct mxc_jpeg_q_data *q_data_out;
>> +
>> + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type !=
>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
>> + return -EINVAL;
>> +
>> + q_data_out = mxc_jpeg_get_q_data(ctx, s->type);
>> +
>> + switch (s->target) {
>> + case V4L2_SEL_TGT_CROP_DEFAULT:
>> + case V4L2_SEL_TGT_CROP_BOUNDS:
>> + s->r.left = 0;
>> + s->r.top = 0;
>> + s->r.width = q_data_out->w;
>> + s->r.height = q_data_out->h;
>> + break;
>> + case V4L2_SEL_TGT_CROP:
>> + s->r = q_data_out->crop;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int mxc_jpeg_g_selection(struct file *file, void *fh, struct
>> +v4l2_selection *s) {
>> + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
>> +
>> + if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
>> + return mxc_jpeg_dec_g_selection(file, fh, s);
>> + else
>> + return mxc_jpeg_enc_g_selection(file, fh, s); }
>> +
>> +static int mxc_jpeg_s_selection(struct file *file, void *fh, struct
>> +v4l2_selection *s) {
>> + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
>> + struct mxc_jpeg_q_data *q_data_out;
>> +
>> + if (ctx->mxc_jpeg->mode != MXC_JPEG_ENCODE)
>> + return -ENOTTY;
>> +
>> + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type !=
>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
>> + return -EINVAL;
>> + if (s->target != V4L2_SEL_TGT_CROP)
>> + return -EINVAL;
>> +
>> + q_data_out = mxc_jpeg_get_q_data(ctx, s->type);
>> + if (s->r.left || s->r.top)
>> + return -EINVAL;
>> + if (s->r.width > q_data_out->w || s->r.height > q_data_out->h)
>> + return -EINVAL;
>> +
>> + q_data_out->crop.left = 0;
>> + q_data_out->crop.top = 0;
>> + q_data_out->crop.width = s->r.width;
>> + q_data_out->crop.height = s->r.height;
>> +
>> + return 0;
>> +}
>> +
>> static int mxc_jpeg_subscribe_event(struct v4l2_fh *fh,
>> const struct v4l2_event_subscription *sub)
>> {
>> @@ -2077,6 +2161,9 @@ static const struct v4l2_ioctl_ops
>mxc_jpeg_ioctl_ops = {
>> .vidioc_g_fmt_vid_cap_mplane = mxc_jpeg_g_fmt_vid,
>> .vidioc_g_fmt_vid_out_mplane = mxc_jpeg_g_fmt_vid,
>>
>> + .vidioc_g_selection = mxc_jpeg_g_selection,
>> + .vidioc_s_selection = mxc_jpeg_s_selection,
>> +
>> .vidioc_subscribe_event = mxc_jpeg_subscribe_event,
>> .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>>
>> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
>> b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
>> index 8104ee4a3b7a..f75dfc89ff6d 100644
>> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
>> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
>> @@ -84,6 +84,7 @@ struct mxc_jpeg_q_data {
>> int h;
>> int h_adjusted;
>> unsigned int sequence;
>> + struct v4l2_rect crop;
>> };
>>
>> struct mxc_jpeg_ctx {