Hi Team, I hope this message finds you well. I wanted to drop a gentle reminder regarding the patch I submitted recently. When you have a moment, could you please review it? Your feedback is invaluable, and I look forward to any insights or suggestions you might have.
Thank you so much for your time and assistance! Best regards, Wenjie Yin -----Original Message----- From: Wenjie.Yin On Behalf Of Wenjie Yin Sent: Wednesday, October 29, 2025 5:20 PM To: '[email protected]' <[email protected]>; Wenjie Yin <[email protected]> Cc: '[email protected]' <[email protected]>; Qiwei Liu (QUIC) <[email protected]>; '[email protected]' <[email protected]> Subject: [PATCH] libavcodec/v4l2_buffers: fixing buffer alignment issue V4l2 drivers may return buffer width & height with aligned values, which may be different from frame width & height. Bytesperlines and strides should be check for aligned buffers when copying pixel data. When width aligned, copy with planar; otherwise, copy line-by-line to dest buffer. Co-authored-by: Renjiang Han <[email protected]> Signed-off-by: Wenjie.Yin <[email protected]> Signed-off-by: Wenjie Yin <[email protected]> --- libavcodec/v4l2_buffers.c | 68 +++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index d869ce9e77..5f5a8aefd5 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -356,6 +356,33 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) return 0; } +static int v4l2_plane_to_plane_align(V4L2Buffer *out, int plane, const +uint8_t* data, int size, int offset, int width, int height, int stride) { + unsigned int bytesused, length; + + if (plane >= out->num_planes) + return AVERROR(EINVAL); + + length = out->plane_info[plane].length; + bytesused = FFMIN(size+offset, length); + + for (int i = 0; i < height; i++) { + memcpy((uint8_t*)out->plane_info[plane].mm_addr + offset, data, width); + offset += stride; + data += width; + } + + if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) { + out->planes[plane].bytesused = bytesused; + out->planes[plane].length = length; + } else { + out->buf.bytesused = bytesused; + out->buf.length = length; + } + + return 0; +} + static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) { int i, ret; @@ -364,7 +391,11 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) fmt.fmt.pix_mp.pixelformat : fmt.fmt.pix.pixelformat; int height = V4L2_TYPE_IS_MULTIPLANAR(fmt.type) ? fmt.fmt.pix_mp.height : fmt.fmt.pix.height; - int is_planar_format = 0; + int bytesperline = V4L2_TYPE_IS_MULTIPLANAR(fmt.type) ? + (fmt.fmt.pix_mp.num_planes ? fmt.fmt.pix_mp.plane_fmt[0].bytesperline: 0) : fmt.fmt.pix.bytesperline; + int sizeimage = V4L2_TYPE_IS_MULTIPLANAR(fmt.type) ? + (fmt.fmt.pix_mp.num_planes ? fmt.fmt.pix_mp.plane_fmt[0].sizeimage: 0) : fmt.fmt.pix.sizeimage; + int is_planar_format = 0, scanline_y = 0, scanline_uv = 0; switch (pixel_format) { case V4L2_PIX_FMT_YUV420M: @@ -398,16 +429,41 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) for (i = 0; i < desc->nb_components; i++) planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); + switch (pixel_format) + { + /* Currently only NV12 & NV21 are addressed for buffer alignment issue */ + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + scanline_y = sizeimage / bytesperline * 2 / 3; + scanline_uv = scanline_y / 2; + break; + default: + /* By default, no buffer alignment issues are expected */ + scanline_y = height; + scanline_uv = AV_CEIL_RSHIFT(height, desc->log2_chroma_h); + bytesperline = frame->linesize[0]; + break; + } + for (i = 0; i < planes_nb; i++) { int size, h = height; if (i == 1 || i == 2) { h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); } - size = frame->linesize[i] * h; - ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset); - if (ret) - return ret; - offset += size; + + if (bytesperline == frame->linesize[0]) { + size = frame->linesize[i] * h; + ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset); + if (ret) + return ret; + offset += frame->linesize[i] * (i ? scanline_uv : scanline_y); + } else { + size = bytesperline * (i ? scanline_uv : scanline_y); + ret = v4l2_plane_to_plane_align(out, 0, frame->data[i], size, offset, frame->linesize[i], h, bytesperline); + if (ret) + return ret; + offset += size; + } } return 0; } -- 2.34.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
