> From: Mirela Rabulea (OSS) <mirela.rabulea@xxxxxxxxxxx> > Sent: 2022年6月16日 15:31 > To: Ming Qian <ming.qian@xxxxxxx>; mchehab@xxxxxxxxxx; > hverkuil-cisco@xxxxxxxxx > Cc: shawnguo@xxxxxxxxxx; s.hauer@xxxxxxxxxxxxxx; kernel@xxxxxxxxxxxxxx; > festevam@xxxxxxxxx; dl-linux-imx <linux-imx@xxxxxxx>; > linux-media@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; > devicetree@xxxxxxxxxxxxxxx; linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > Subject: Re: [PATCH v2] media: imx-jpeg: Align upwards buffer size > > Hi Ming, > > On 13.06.2022 08:25, Ming Qian wrote: > >> From: Mirela Rabulea (OSS) <mirela.rabulea@xxxxxxxxxxx> > >> Sent: 2022年6月13日 6:56 > >> To: Ming Qian <ming.qian@xxxxxxx>; mchehab@xxxxxxxxxx; > >> hverkuil-cisco@xxxxxxxxx > >> Cc: shawnguo@xxxxxxxxxx; s.hauer@xxxxxxxxxxxxxx; > >> kernel@xxxxxxxxxxxxxx; festevam@xxxxxxxxx; dl-linux-imx > >> <linux-imx@xxxxxxx>; linux-media@xxxxxxxxxxxxxxx; > >> linux-kernel@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx; > >> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > >> Subject: Re: [PATCH v2] media: imx-jpeg: Align upwards buffer size > >> > >> Hi Ming, > >> > >> On 30.05.2022 10:49, Ming Qian wrote: > >>> The hardware can support any image size WxH, with arbitrary W (image > >>> width) and H (image height) dimensions. > >>> > >>> Align upwards buffer size for both encoder and decoder. > >>> and leave the picture resolution unchanged. > >>> > >>> For decoder, the risk of memory out of bounds can be avoided. > >>> For both encoder and decoder, the driver will lift the limitation of > >>> resolution alignment. > >>> > >>> For example, the decoder can support jpeg whose resolution is > >>> 227x149 > >> > >> I doubt 227x149 is working. I have tried 127x127, with your patch > >> applied, both on encoder and decoder, the image does not look ok. The > >> 126x127 seems to work. Having an odd resolution seems strange, I see > >> not even gstreamer supports it (tried videotestsrc & filesink with > >> BGR, > >> 127x128 produces a 128x128 size). > >> > >> We need to gain more clarity on this one. > >> And when we do, if we really can support any arbitrary resolution, > >> from both the jpeg core and wrapper point of view, we have stuff to clean > up. > >> The assumption that I started with was, as stated in the comments: > >> * The alignment requirements for the resolution depend on the format, > >> * multiple of 16 resolutions should work for all formats. > >> * Special workarounds are made in the driver to support NV12 1080p. > >> With h_align/v_align defined in mxc_formats[]. > >> > >> Regards, > >> Mirela > > > > Hi Mirela, > > I think you are confusing picture size and buffer size. > > In this patch, driver will enlarge the buffer size to align 16x16. But let > the picture size unchanged. > > And if you display the decoded 227x149 picture directly on imx8q, > > you may meet some drm error, and the display looks abnormal, The error > message like below: > > [ 36.381015] [drm] [CRTC:38:crtc-0] dpu_crtc_atomic_flush: wait for > content shdld done timeout > > [ 36.389630] [drm] [CRTC:38:crtc-0] dpu_crtc_atomic_flush: FrameGen > requests to read empty FIFO > > [ 49.469022] [drm] [CRTC:38:crtc-0] dpu_crtc_atomic_flush: wait for > content shdld done timeout > > > > But if you save the decoded picture data in to a file, then check the data, you > will find it's correct. > > And if you treat the decoded buffer as a picture with resolution 240x160, and > with some padding content, it's also correct. > > > > So in my first patch, I let the driver report the aligned resolution > > in g_fmt, and implement a g_selection to report the actual resolution > through the crop info. > > but this solution will fail your labgrid jpeg test. > > > > So I choose the current solution that keep the actual picture size, and align > upwards the buffer size. > > > > The display of 227x149 is abnormal, I think it's not the jpeg codec's > limitation, but the imx8q drm's limitation. > > I did not try to display with gstreamer. I just tried to generate some test files. > For example, this one: > gst-launch-1.0 videotestsrc pattern=smpte75 num-buffers=1 ! > video/x-raw,width=227,height=149,format=BGR ! filesink > location=bgr_227x149.raw generates a 228x149 file, not 227x149, with the > 228 column black (padding?). For visualizing, I used vooya, on host machine. > > I then tried the pattern generator: https://github.com/NXPmicro/nxp-patgen > ./patgen.exe -pix_fmt yuv444 -p colorbar -vsize 227x149 > > This generates a raw yuv444 227x149, without padding. > I used the unit test application to encode it. > The resulting jpeg is reported by JPEGSnoop to have Image Size = 227x149, > and it looks bad, every line is shifted, as if it would have > 228 width. > I did not check yet to see if any adjustments are needed in the unit test. > > I'll send you my test files. > > Regards, > Mirela > Hi Mirela, I tested your test file patgen-colorbar-227x149-yuv444.yuv, and encode it to jpeg. The encoded jpeg has image size 227x149, and it looks good. I have sent it to you, you can double check. Note when encoding the 227x149 yuv444 image, the buffer size is aligned upwards to 696 x 152. So when you write the yuv date into the buffer, you should write line by line. The bytesperline of the buffer is not 681(227x3), but 696. Ming > > > > And in my opinion, I prefer the first solution that implementing a g_selection > to report the actual picture size. > > If you can accept that changing your labgrid jpeg testcase, I can prepare a v3 > patch to switch to this solution. > > > > Ming > > > >> > >>> the encoder can support nv12 1080P, won't change it to 1920x1072. > >>> > >>> Fixes: 2db16c6ed72ce ("media: imx-jpeg: Add V4L2 driver for i.MX8 > >>> JPEG > >>> Encoder/Decoder") > >>> Signed-off-by: Ming Qian <ming.qian@xxxxxxx> > >>> --- > >>> v2 > >>> - add Fixes tag > >>> .../media/platform/nxp/imx-jpeg/mxc-jpeg.c | 88 > ++++++++----------- > >>> 1 file changed, 37 insertions(+), 51 deletions(-) > >>> > >>> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c > >>> b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c > >>> index c0fd030d0f19..9a1c8df522ed 100644 > >>> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c > >>> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c > >>> @@ -894,8 +894,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_adjusted, > >>> - q_data->h_adjusted); > >>> + q_data->w, > >>> + q_data->h); > >>> > >>> /* chain the config descriptor with the encoding descriptor */ > >>> cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN; > @@ > >>> -977,7 +977,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, > >>> - q_data_cap->fmt->v_align, > >>> + 0, > >>> 0); > >>> > >>> /* setup bytesperline/sizeimage for capture queue */ @@ > >>> -1161,18 > >>> +1161,30 @@ 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]); > >>> + > >>> /* 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] < q_data->sizeimage[i]) > >>> + if (sizes[i] < tmp_q.sizeimage[i]) > >>> return -EINVAL; > >>> } > >>> return 0; > >>> @@ -1181,7 +1193,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] = q_data->sizeimage[i]; > >>> + sizes[i] = tmp_q.sizeimage[i]; > >>> > >>> return 0; > >>> } > >>> @@ -1381,11 +1393,6 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx > >> *ctx, struct vb2_buffer *vb) > >>> } > >>> q_data_out->w = header.frame.width; > >>> q_data_out->h = header.frame.height; > >>> - if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) { > >>> - dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n", > >>> - header.frame.width, header.frame.height); > >>> - return -EINVAL; > >>> - } > >>> if (header.frame.width > MXC_JPEG_MAX_WIDTH || > >>> header.frame.height > MXC_JPEG_MAX_HEIGHT) { > >>> dev_err(dev, "JPEG width or height should be <= > 8192: %dx%d\n", > >> @@ > >>> -1748,22 +1755,17 @@ static int mxc_jpeg_try_fmt(struct v4l2_format > >>> *f, > >> const struct mxc_jpeg_fmt *fm > >>> pix_mp->num_planes = fmt->colplanes; > >>> pix_mp->pixelformat = fmt->fourcc; > >>> > >>> - /* > >>> - * use MXC_JPEG_H_ALIGN instead of fmt->v_align, for vertical > >>> - * alignment, to loosen up the alignment to multiple of 8, > >>> - * otherwise NV12-1080p fails as 1080 is not a multiple of 16 > >>> - */ > >>> + pix_mp->width = w; > >>> + pix_mp->height = h; > >>> v4l_bound_align_image(&w, > >>> - MXC_JPEG_MIN_WIDTH, > >>> - w, /* adjust downwards*/ > >>> + w, /* adjust upwards*/ > >>> + MXC_JPEG_MAX_WIDTH, > >>> fmt->h_align, > >>> &h, > >>> - MXC_JPEG_MIN_HEIGHT, > >>> - h, /* adjust downwards*/ > >>> - MXC_JPEG_H_ALIGN, > >>> + h, /* adjust upwards*/ > >>> + MXC_JPEG_MAX_HEIGHT, > >>> + 0, > >>> 0); > >>> - pix_mp->width = w; /* negotiate the width */ > >>> - pix_mp->height = h; /* negotiate the height */ > >>> > >>> /* get user input into the tmp_q */ > >>> tmp_q.w = w; > >>> @@ -1889,35 +1891,19 @@ static int mxc_jpeg_s_fmt(struct > >>> mxc_jpeg_ctx *ctx, > >>> > >>> q_data->w_adjusted = q_data->w; > >>> q_data->h_adjusted = q_data->h; > >>> - if (jpeg->mode == MXC_JPEG_DECODE) { > >>> - /* > >>> - * 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); > >>> - } else { > >>> - /* > >>> - * align down the resolution for CAST IP, > >>> - * but leave the buffer resolution unchanged > >>> - */ > >>> - v4l_bound_align_image(&q_data->w_adjusted, > >>> - MXC_JPEG_MIN_WIDTH, > >>> - q_data->w_adjusted, /* adjust downwards*/ > >>> - q_data->fmt->h_align, > >>> - &q_data->h_adjusted, > >>> - MXC_JPEG_MIN_HEIGHT, > >>> - q_data->h_adjusted, /* adjust downwards*/ > >>> - q_data->fmt->v_align, > >>> - 0); > >>> - } > >>> + /* > >>> + * 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;