[v2,4/4] apps: cam: sdl_sink: Support more single-plane formats
diff mbox series

Message ID 20250425104703.805170-5-barnabas.pocze@ideasonboard.com
State Superseded
Headers show
Series
  • apps: cam: sdl_sink: Support more RGB and YUV formats
Related show

Commit Message

Barnabás Pőcze April 25, 2025, 10:47 a.m. UTC
With the newly introduced `SDLTexture1Plane` it is easy to handle
any single-plane format that has an SDL equivalent. So use it for
more YUV and RGB formats.

The mapping of RGB formats is not entirely straightforward because
`SDL_PIXELFORMAT_ZZZ...888...` defines a format where the order of
the components is endian dependent, while libcamera's `ZZZ...888...`
formats are derived from the matching DRM formats, and the RGB formats
in question are defined to be little-endian there. So the
endian-independent `SDL_PIXELFORMAT_{ZZZ24,ZZZZ32}` are used.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 src/apps/cam/sdl_sink.cpp | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

Comments

Kieran Bingham April 25, 2025, 12:07 p.m. UTC | #1
Quoting Barnabás Pőcze (2025-04-25 11:47:03)
> With the newly introduced `SDLTexture1Plane` it is easy to handle
> any single-plane format that has an SDL equivalent. So use it for
> more YUV and RGB formats.
> 
> The mapping of RGB formats is not entirely straightforward because
> `SDL_PIXELFORMAT_ZZZ...888...` defines a format where the order of
> the components is endian dependent, while libcamera's `ZZZ...888...`
> formats are derived from the matching DRM formats, and the RGB formats
> in question are defined to be little-endian there. So the
> endian-independent `SDL_PIXELFORMAT_{ZZZ24,ZZZZ32}` are used.
> 
> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> ---
>  src/apps/cam/sdl_sink.cpp | 36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp
> index b295675dc..2edbb523d 100644
> --- a/src/apps/cam/sdl_sink.cpp
> +++ b/src/apps/cam/sdl_sink.cpp
> @@ -77,6 +77,42 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)
>         case libcamera::formats::YUYV:
>                 texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YUY2, cfg.stride);
>                 break;
> +       case libcamera::formats::UYVY:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_UYVY, cfg.stride);
> +               break;
> +       case libcamera::formats::YVYU:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YVYU, cfg.stride);
> +               break;
> +       case libcamera::formats::ARGB8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRA32, cfg.stride);
> +               break;
> +       case libcamera::formats::XRGB8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRX32, cfg.stride);
> +               break;
> +       case libcamera::formats::RGBA8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ABGR32, cfg.stride);
> +               break;
> +       case libcamera::formats::RGBX8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XBGR32, cfg.stride);
> +               break;
> +       case libcamera::formats::ABGR8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBA32, cfg.stride);
> +               break;
> +       case libcamera::formats::XBGR8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBX32, cfg.stride);
> +               break;
> +       case libcamera::formats::BGRA8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ARGB32, cfg.stride);
> +               break;
> +       case libcamera::formats::BGRX8888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XRGB32, cfg.stride);
> +               break;
> +       case libcamera::formats::RGB888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGR24, cfg.stride);
> +               break;
> +       case libcamera::formats::BGR888:
> +               texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGB24, cfg.stride);
> +               break;

all of those are in the ordering I would expect:

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

>         default:
>                 std::cerr << "Unsupported pixel format "
>                           << cfg.pixelFormat.toString() << std::endl;
> -- 
> 2.49.0
>
Laurent Pinchart April 25, 2025, 12:45 p.m. UTC | #2
Hi Barnabás,

Thank you for the patch.

On Fri, Apr 25, 2025 at 12:47:03PM +0200, Barnabás Pőcze wrote:
> With the newly introduced `SDLTexture1Plane` it is easy to handle
> any single-plane format that has an SDL equivalent. So use it for
> more YUV and RGB formats.
> 
> The mapping of RGB formats is not entirely straightforward because
> `SDL_PIXELFORMAT_ZZZ...888...` defines a format where the order of
> the components is endian dependent, while libcamera's `ZZZ...888...`
> formats are derived from the matching DRM formats, and the RGB formats
> in question are defined to be little-endian there. So the
> endian-independent `SDL_PIXELFORMAT_{ZZZ24,ZZZZ32}` are used.

Format mapping is always painful :-(

> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> ---
>  src/apps/cam/sdl_sink.cpp | 36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp
> index b295675dc..2edbb523d 100644
> --- a/src/apps/cam/sdl_sink.cpp
> +++ b/src/apps/cam/sdl_sink.cpp
> @@ -77,6 +77,42 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)
>  	case libcamera::formats::YUYV:
>  		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YUY2, cfg.stride);
>  		break;
> +	case libcamera::formats::UYVY:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_UYVY, cfg.stride);
> +		break;
> +	case libcamera::formats::YVYU:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YVYU, cfg.stride);
> +		break;
> +	case libcamera::formats::ARGB8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRA32, cfg.stride);
> +		break;
> +	case libcamera::formats::XRGB8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRX32, cfg.stride);
> +		break;
> +	case libcamera::formats::RGBA8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ABGR32, cfg.stride);
> +		break;
> +	case libcamera::formats::RGBX8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XBGR32, cfg.stride);
> +		break;
> +	case libcamera::formats::ABGR8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBA32, cfg.stride);
> +		break;
> +	case libcamera::formats::XBGR8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBX32, cfg.stride);
> +		break;
> +	case libcamera::formats::BGRA8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ARGB32, cfg.stride);
> +		break;
> +	case libcamera::formats::BGRX8888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XRGB32, cfg.stride);
> +		break;
> +	case libcamera::formats::RGB888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGR24, cfg.stride);
> +		break;
> +	case libcamera::formats::BGR888:
> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGB24, cfg.stride);
> +		break;

I'm tempted to avoid all the constructor calls by instead adding a
sdlFormat variable and filling it in the switch, and then creating the
texture after the switch.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

>  	default:
>  		std::cerr << "Unsupported pixel format "
>  			  << cfg.pixelFormat.toString() << std::endl;
Barnabás Pőcze April 25, 2025, 12:58 p.m. UTC | #3
Hi


2025. 04. 25. 14:45 keltezéssel, Laurent Pinchart írta:
> Hi Barnabás,
> 
> Thank you for the patch.
> 
> On Fri, Apr 25, 2025 at 12:47:03PM +0200, Barnabás Pőcze wrote:
>> With the newly introduced `SDLTexture1Plane` it is easy to handle
>> any single-plane format that has an SDL equivalent. So use it for
>> more YUV and RGB formats.
>>
>> The mapping of RGB formats is not entirely straightforward because
>> `SDL_PIXELFORMAT_ZZZ...888...` defines a format where the order of
>> the components is endian dependent, while libcamera's `ZZZ...888...`
>> formats are derived from the matching DRM formats, and the RGB formats
>> in question are defined to be little-endian there. So the
>> endian-independent `SDL_PIXELFORMAT_{ZZZ24,ZZZZ32}` are used.
> 
> Format mapping is always painful :-(
> 
>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>> ---
>>   src/apps/cam/sdl_sink.cpp | 36 ++++++++++++++++++++++++++++++++++++
>>   1 file changed, 36 insertions(+)
>>
>> diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp
>> index b295675dc..2edbb523d 100644
>> --- a/src/apps/cam/sdl_sink.cpp
>> +++ b/src/apps/cam/sdl_sink.cpp
>> @@ -77,6 +77,42 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)
>>   	case libcamera::formats::YUYV:
>>   		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YUY2, cfg.stride);
>>   		break;
>> +	case libcamera::formats::UYVY:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_UYVY, cfg.stride);
>> +		break;
>> +	case libcamera::formats::YVYU:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YVYU, cfg.stride);
>> +		break;
>> +	case libcamera::formats::ARGB8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRA32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::XRGB8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRX32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::RGBA8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ABGR32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::RGBX8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XBGR32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::ABGR8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBA32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::XBGR8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBX32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::BGRA8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ARGB32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::BGRX8888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XRGB32, cfg.stride);
>> +		break;
>> +	case libcamera::formats::RGB888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGR24, cfg.stride);
>> +		break;
>> +	case libcamera::formats::BGR888:
>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGB24, cfg.stride);
>> +		break;
> 
> I'm tempted to avoid all the constructor calls by instead adding a
> sdlFormat variable and filling it in the switch, and then creating the
> texture after the switch.

Yes, indeed, and I had thought about that for a bit, but there is also
SDLTextureNV12 (conditionally), and I didn't really see a good way to
reconcile the two.


Regards,
Barnabás Pőcze

> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
>>   	default:
>>   		std::cerr << "Unsupported pixel format "
>>   			  << cfg.pixelFormat.toString() << std::endl;
>
Laurent Pinchart April 25, 2025, 2:41 p.m. UTC | #4
On Fri, Apr 25, 2025 at 02:58:08PM +0200, Barnabás Pőcze wrote:
> Hi
> 
> 
> 2025. 04. 25. 14:45 keltezéssel, Laurent Pinchart írta:
> > Hi Barnabás,
> > 
> > Thank you for the patch.
> > 
> > On Fri, Apr 25, 2025 at 12:47:03PM +0200, Barnabás Pőcze wrote:
> >> With the newly introduced `SDLTexture1Plane` it is easy to handle
> >> any single-plane format that has an SDL equivalent. So use it for
> >> more YUV and RGB formats.
> >>
> >> The mapping of RGB formats is not entirely straightforward because
> >> `SDL_PIXELFORMAT_ZZZ...888...` defines a format where the order of
> >> the components is endian dependent, while libcamera's `ZZZ...888...`
> >> formats are derived from the matching DRM formats, and the RGB formats
> >> in question are defined to be little-endian there. So the
> >> endian-independent `SDL_PIXELFORMAT_{ZZZ24,ZZZZ32}` are used.
> > 
> > Format mapping is always painful :-(
> > 
> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> >> ---
> >>   src/apps/cam/sdl_sink.cpp | 36 ++++++++++++++++++++++++++++++++++++
> >>   1 file changed, 36 insertions(+)
> >>
> >> diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp
> >> index b295675dc..2edbb523d 100644
> >> --- a/src/apps/cam/sdl_sink.cpp
> >> +++ b/src/apps/cam/sdl_sink.cpp
> >> @@ -77,6 +77,42 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)
> >>   	case libcamera::formats::YUYV:
> >>   		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YUY2, cfg.stride);
> >>   		break;
> >> +	case libcamera::formats::UYVY:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_UYVY, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::YVYU:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YVYU, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::ARGB8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRA32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::XRGB8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRX32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::RGBA8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ABGR32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::RGBX8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XBGR32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::ABGR8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBA32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::XBGR8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBX32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::BGRA8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ARGB32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::BGRX8888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XRGB32, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::RGB888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGR24, cfg.stride);
> >> +		break;
> >> +	case libcamera::formats::BGR888:
> >> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGB24, cfg.stride);
> >> +		break;
> > 
> > I'm tempted to avoid all the constructor calls by instead adding a
> > sdlFormat variable and filling it in the switch, and then creating the
> > texture after the switch.
> 
> Yes, indeed, and I had thought about that for a bit, but there is also
> SDLTextureNV12 (conditionally), and I didn't really see a good way to
> reconcile the two.


	switch (cfg.pixelFormat) {
#ifdef HAVE_LIBJPEG
	case libcamera::formats::MJPEG:
		texture_ = std::make_unique<SDLTextureMJPG>(rect_);
		break;
#endif
#if SDL_VERSION_ATLEAST(2, 0, 16)
	case libcamera::formats::NV12:
		texture_ = std::make_unique<SDLTextureNV12>(rect_, cfg.stride);
		break;
#endif
 	case libcamera::formats::YUYV:
 		sdlFormat = SDL_PIXELFORMAT_YUY2;
 		break;
	case libcamera::formats::UYVY:
 		sdlFormat = SDL_PIXELFORMAT_UYVY;
		break;
...
	default:
		std::cerr << "Unsupported pixel format "
			  << cfg.pixelFormat.toString() << std::endl;
		return -EINVAL;
	};

	if (sdlFormat)
		texture_ = std::make_unique<SDLTexture1Plane>(rect_, sdlFormat, cfg.stride);

> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > 
> >>   	default:
> >>   		std::cerr << "Unsupported pixel format "
> >>   			  << cfg.pixelFormat.toString() << std::endl;
Barnabás Pőcze April 28, 2025, 8:52 a.m. UTC | #5
Hi


2025. 04. 25. 16:41 keltezéssel, Laurent Pinchart írta:
> On Fri, Apr 25, 2025 at 02:58:08PM +0200, Barnabás Pőcze wrote:
>> Hi
>>
>>
>> 2025. 04. 25. 14:45 keltezéssel, Laurent Pinchart írta:
>>> Hi Barnabás,
>>>
>>> Thank you for the patch.
>>>
>>> On Fri, Apr 25, 2025 at 12:47:03PM +0200, Barnabás Pőcze wrote:
>>>> With the newly introduced `SDLTexture1Plane` it is easy to handle
>>>> any single-plane format that has an SDL equivalent. So use it for
>>>> more YUV and RGB formats.
>>>>
>>>> The mapping of RGB formats is not entirely straightforward because
>>>> `SDL_PIXELFORMAT_ZZZ...888...` defines a format where the order of
>>>> the components is endian dependent, while libcamera's `ZZZ...888...`
>>>> formats are derived from the matching DRM formats, and the RGB formats
>>>> in question are defined to be little-endian there. So the
>>>> endian-independent `SDL_PIXELFORMAT_{ZZZ24,ZZZZ32}` are used.
>>>
>>> Format mapping is always painful :-(
>>>
>>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>>>> ---
>>>>    src/apps/cam/sdl_sink.cpp | 36 ++++++++++++++++++++++++++++++++++++
>>>>    1 file changed, 36 insertions(+)
>>>>
>>>> diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp
>>>> index b295675dc..2edbb523d 100644
>>>> --- a/src/apps/cam/sdl_sink.cpp
>>>> +++ b/src/apps/cam/sdl_sink.cpp
>>>> @@ -77,6 +77,42 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)
>>>>    	case libcamera::formats::YUYV:
>>>>    		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YUY2, cfg.stride);
>>>>    		break;
>>>> +	case libcamera::formats::UYVY:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_UYVY, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::YVYU:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YVYU, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::ARGB8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRA32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::XRGB8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRX32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::RGBA8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ABGR32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::RGBX8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XBGR32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::ABGR8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBA32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::XBGR8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBX32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::BGRA8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ARGB32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::BGRX8888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XRGB32, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::RGB888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGR24, cfg.stride);
>>>> +		break;
>>>> +	case libcamera::formats::BGR888:
>>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGB24, cfg.stride);
>>>> +		break;
>>>
>>> I'm tempted to avoid all the constructor calls by instead adding a
>>> sdlFormat variable and filling it in the switch, and then creating the
>>> texture after the switch.
>>
>> Yes, indeed, and I had thought about that for a bit, but there is also
>> SDLTextureNV12 (conditionally), and I didn't really see a good way to
>> reconcile the two.
> 
> 
> 	switch (cfg.pixelFormat) {
> #ifdef HAVE_LIBJPEG
> 	case libcamera::formats::MJPEG:
> 		texture_ = std::make_unique<SDLTextureMJPG>(rect_);
> 		break;
> #endif
> #if SDL_VERSION_ATLEAST(2, 0, 16)
> 	case libcamera::formats::NV12:
> 		texture_ = std::make_unique<SDLTextureNV12>(rect_, cfg.stride);
> 		break;
> #endif
>   	case libcamera::formats::YUYV:
>   		sdlFormat = SDL_PIXELFORMAT_YUY2;
>   		break;
> 	case libcamera::formats::UYVY:
>   		sdlFormat = SDL_PIXELFORMAT_UYVY;
> 		break;
> ...
> 	default:
> 		std::cerr << "Unsupported pixel format "
> 			  << cfg.pixelFormat.toString() << std::endl;
> 		return -EINVAL;
> 	};
> 
> 	if (sdlFormat)
> 		texture_ = std::make_unique<SDLTexture1Plane>(rect_, sdlFormat, cfg.stride);
> 

I have looked at something like this, but I am not a fan at all. :(


Regards,
Barnabás Pőcze


>>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>
>>>>    	default:
>>>>    		std::cerr << "Unsupported pixel format "
>>>>    			  << cfg.pixelFormat.toString() << std::endl;
>
Laurent Pinchart April 28, 2025, 9:14 a.m. UTC | #6
On Mon, Apr 28, 2025 at 10:52:39AM +0200, Barnabás Pőcze wrote:
> 2025. 04. 25. 16:41 keltezéssel, Laurent Pinchart írta:
> > On Fri, Apr 25, 2025 at 02:58:08PM +0200, Barnabás Pőcze wrote:
> >> 2025. 04. 25. 14:45 keltezéssel, Laurent Pinchart írta:
> >>> On Fri, Apr 25, 2025 at 12:47:03PM +0200, Barnabás Pőcze wrote:
> >>>> With the newly introduced `SDLTexture1Plane` it is easy to handle
> >>>> any single-plane format that has an SDL equivalent. So use it for
> >>>> more YUV and RGB formats.
> >>>>
> >>>> The mapping of RGB formats is not entirely straightforward because
> >>>> `SDL_PIXELFORMAT_ZZZ...888...` defines a format where the order of
> >>>> the components is endian dependent, while libcamera's `ZZZ...888...`
> >>>> formats are derived from the matching DRM formats, and the RGB formats
> >>>> in question are defined to be little-endian there. So the
> >>>> endian-independent `SDL_PIXELFORMAT_{ZZZ24,ZZZZ32}` are used.
> >>>
> >>> Format mapping is always painful :-(
> >>>
> >>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> >>>> ---
> >>>>    src/apps/cam/sdl_sink.cpp | 36 ++++++++++++++++++++++++++++++++++++
> >>>>    1 file changed, 36 insertions(+)
> >>>>
> >>>> diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp
> >>>> index b295675dc..2edbb523d 100644
> >>>> --- a/src/apps/cam/sdl_sink.cpp
> >>>> +++ b/src/apps/cam/sdl_sink.cpp
> >>>> @@ -77,6 +77,42 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)
> >>>>    	case libcamera::formats::YUYV:
> >>>>    		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YUY2, cfg.stride);
> >>>>    		break;
> >>>> +	case libcamera::formats::UYVY:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_UYVY, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::YVYU:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YVYU, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::ARGB8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRA32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::XRGB8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRX32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::RGBA8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ABGR32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::RGBX8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XBGR32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::ABGR8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBA32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::XBGR8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBX32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::BGRA8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ARGB32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::BGRX8888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XRGB32, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::RGB888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGR24, cfg.stride);
> >>>> +		break;
> >>>> +	case libcamera::formats::BGR888:
> >>>> +		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGB24, cfg.stride);
> >>>> +		break;
> >>>
> >>> I'm tempted to avoid all the constructor calls by instead adding a
> >>> sdlFormat variable and filling it in the switch, and then creating the
> >>> texture after the switch.
> >>
> >> Yes, indeed, and I had thought about that for a bit, but there is also
> >> SDLTextureNV12 (conditionally), and I didn't really see a good way to
> >> reconcile the two.
> > 
> > 
> > 	switch (cfg.pixelFormat) {
> > #ifdef HAVE_LIBJPEG
> > 	case libcamera::formats::MJPEG:
> > 		texture_ = std::make_unique<SDLTextureMJPG>(rect_);
> > 		break;
> > #endif
> > #if SDL_VERSION_ATLEAST(2, 0, 16)
> > 	case libcamera::formats::NV12:
> > 		texture_ = std::make_unique<SDLTextureNV12>(rect_, cfg.stride);
> > 		break;
> > #endif
> >   	case libcamera::formats::YUYV:
> >   		sdlFormat = SDL_PIXELFORMAT_YUY2;
> >   		break;
> > 	case libcamera::formats::UYVY:
> >   		sdlFormat = SDL_PIXELFORMAT_UYVY;
> > 		break;
> > ...
> > 	default:
> > 		std::cerr << "Unsupported pixel format "
> > 			  << cfg.pixelFormat.toString() << std::endl;
> > 		return -EINVAL;
> > 	};
> > 
> > 	if (sdlFormat)
> > 		texture_ = std::make_unique<SDLTexture1Plane>(rect_, sdlFormat, cfg.stride);
> > 
> 
> I have looked at something like this, but I am not a fan at all. :(

I understand why and I probably have the same feeling. I still think
it's a bit better than duplicating the calls though.

> >>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>>
> >>>>    	default:
> >>>>    		std::cerr << "Unsupported pixel format "
> >>>>    			  << cfg.pixelFormat.toString() << std::endl;

Patch
diff mbox series

diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp
index b295675dc..2edbb523d 100644
--- a/src/apps/cam/sdl_sink.cpp
+++ b/src/apps/cam/sdl_sink.cpp
@@ -77,6 +77,42 @@  int SDLSink::configure(const libcamera::CameraConfiguration &config)
 	case libcamera::formats::YUYV:
 		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YUY2, cfg.stride);
 		break;
+	case libcamera::formats::UYVY:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_UYVY, cfg.stride);
+		break;
+	case libcamera::formats::YVYU:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_YVYU, cfg.stride);
+		break;
+	case libcamera::formats::ARGB8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRA32, cfg.stride);
+		break;
+	case libcamera::formats::XRGB8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGRX32, cfg.stride);
+		break;
+	case libcamera::formats::RGBA8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ABGR32, cfg.stride);
+		break;
+	case libcamera::formats::RGBX8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XBGR32, cfg.stride);
+		break;
+	case libcamera::formats::ABGR8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBA32, cfg.stride);
+		break;
+	case libcamera::formats::XBGR8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGBX32, cfg.stride);
+		break;
+	case libcamera::formats::BGRA8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_ARGB32, cfg.stride);
+		break;
+	case libcamera::formats::BGRX8888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_XRGB32, cfg.stride);
+		break;
+	case libcamera::formats::RGB888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_BGR24, cfg.stride);
+		break;
+	case libcamera::formats::BGR888:
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, SDL_PIXELFORMAT_RGB24, cfg.stride);
+		break;
 	default:
 		std::cerr << "Unsupported pixel format "
 			  << cfg.pixelFormat.toString() << std::endl;