[libcamera-devel] [PATCH v2 4/5] qcam: format_converter: Add fully-planar YUV formats support

Kieran Bingham kieran.bingham at ideasonboard.com
Tue Sep 21 17:35:32 CEST 2021


On 07/09/2021 01:20, Laurent Pinchart wrote:
> Add support for the YUV420, YVU420 and YUV420 formats supported by
> libcamera. YUV420 can be produced by the Raspberry Pi pipeline handler,
> being able to display it is useful for testing.
> 

These need adding to the gstlibcamera-utils.cpp format_map too.
I've done that while working through to verify the formats here.

Patch incoming separately.

Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>


> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
>  src/qcam/format_converter.cpp | 66 +++++++++++++++++++++++++++++++++++
>  src/qcam/format_converter.h   |  2 ++
>  2 files changed, 68 insertions(+)
> 
> diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp
> index 7979ea8a77ff..d4d3223bc698 100644
> --- a/src/qcam/format_converter.cpp
> +++ b/src/qcam/format_converter.cpp
> @@ -8,6 +8,7 @@
>  #include "format_converter.h"
>  
>  #include <errno.h>
> +#include <utility>
>  
>  #include <QImage>
>  
> @@ -141,6 +142,25 @@ int FormatConverter::configure(const libcamera::PixelFormat &format,
>  		cb_pos_ = 1;
>  		break;
>  
> +	case libcamera::formats::YUV420:
> +		formatFamily_ = YUVPlanar;
> +		horzSubSample_ = 2;
> +		vertSubSample_ = 2;
> +		nvSwap_ = false;
> +		break;
> +	case libcamera::formats::YVU420:
> +		formatFamily_ = YUVPlanar;
> +		horzSubSample_ = 2;
> +		vertSubSample_ = 2;
> +		nvSwap_ = true;
> +		break;
> +	case libcamera::formats::YUV422:
> +		formatFamily_ = YUVPlanar;
> +		horzSubSample_ = 2;
> +		vertSubSample_ = 1;
> +		nvSwap_ = false;
> +		break;
> +
>  	case libcamera::formats::MJPEG:
>  		formatFamily_ = MJPEG;
>  		break;
> @@ -172,6 +192,9 @@ void FormatConverter::convert(const Image *src, size_t size, QImage *dst)
>  	case YUVSemiPlanar:
>  		convertYUVSemiPlanar(src, dst->bits());
>  		break;
> +	case YUVPlanar:
> +		convertYUVPlanar(src, dst->bits());
> +		break;
>  	};
>  }
>  
> @@ -247,6 +270,49 @@ void FormatConverter::convertYUVPacked(const Image *srcImage, unsigned char *dst
>  	}
>  }
>  
> +void FormatConverter::convertYUVPlanar(const Image *srcImage, unsigned char *dst)
> +{
> +	unsigned int c_stride = stride_ / horzSubSample_;
> +	unsigned int c_inc = horzSubSample_ == 1 ? 1 : 0;
> +	const unsigned char *src_y = srcImage->data(0).data();
> +	const unsigned char *src_cb = srcImage->data(1).data();
> +	const unsigned char *src_cr = srcImage->data(2).data();
> +	int r, g, b;
> +
> +	if (nvSwap_)
> +		std::swap(src_cb, src_cr);
> +
> +	for (unsigned int y = 0; y < height_; y++) {
> +		const unsigned char *line_y = src_y + y * stride_;
> +		const unsigned char *line_cb = src_cb + (y / vertSubSample_) *
> +					       c_stride;
> +		const unsigned char *line_cr = src_cr + (y / vertSubSample_) *
> +					       c_stride;
> +
> +		for (unsigned int x = 0; x < width_; x += 2) {
> +			yuv_to_rgb(*line_y, *line_cb, *line_cr, &r, &g, &b);
> +			dst[0] = b;
> +			dst[1] = g;
> +			dst[2] = r;
> +			dst[3] = 0xff;
> +			line_y++;
> +			line_cb += c_inc;
> +			line_cr += c_inc;
> +			dst += 4;
> +
> +			yuv_to_rgb(*line_y, *line_cb, *line_cr, &r, &g, &b);
> +			dst[0] = b;
> +			dst[1] = g;
> +			dst[2] = r;
> +			dst[3] = 0xff;
> +			line_y++;
> +			line_cb += 1;
> +			line_cr += 1;
> +			dst += 4;
> +		}
> +	}
> +}
> +
>  void FormatConverter::convertYUVSemiPlanar(const Image *srcImage, unsigned char *dst)
>  {
>  	unsigned int c_stride = stride_ * (2 / horzSubSample_);
> diff --git a/src/qcam/format_converter.h b/src/qcam/format_converter.h
> index 9ce2cc6da7f2..9da2df5d294b 100644
> --- a/src/qcam/format_converter.h
> +++ b/src/qcam/format_converter.h
> @@ -29,11 +29,13 @@ private:
>  		MJPEG,
>  		RGB,
>  		YUVPacked,
> +		YUVPlanar,
>  		YUVSemiPlanar,
>  	};
>  
>  	void convertRGB(const Image *src, unsigned char *dst);
>  	void convertYUVPacked(const Image *src, unsigned char *dst);
> +	void convertYUVPlanar(const Image *src, unsigned char *dst);
>  	void convertYUVSemiPlanar(const Image *src, unsigned char *dst);
>  
>  	libcamera::PixelFormat format_;
> 


More information about the libcamera-devel mailing list