[Interest] QVideoFrame 32 bit formats byte order

Stefan Fabian stefan.fabian.dev at hotmail.com
Thu Nov 14 20:54:37 CET 2019


Hey guys,

I'm interfacing external camera input to Qt/QML (version 5.9.5 on Ubuntu 18.04).
For this, I'm using a custom video source and present the frames using QVideoFrame and QAbstractVideoBuffer.
The image is displayed in QML using a VideoOutput.
Since not all formats can be mapped directly, I have to do some conversions.
The issue:

The formats RGB32 and BGR32 don't act as expected.
According to the docs, the former is 0xffRRGGBB and the latter 0xBBGGRRff. Unfortunately, it is not specified whether the endianness of the computer is used or big-endian.

Here's the conversion to RGB32:

auto output = reinterpret_cast<uint32_t *>(*data);
iterateImage( img, bytes_per_pixel, [ & ]( const uint8_t *stream )
{
  *output = (255U << 24U) | (static_cast<uint32_t>(static_cast<uint8_t>(R( stream, 0, 255 ))) << 16U) |
            (static_cast<uint32_t>(static_cast<uint8_t>(G( stream, 0, 255 ))) << 8U) |
            static_cast<uint32_t>(static_cast<uint8_t>(B( stream, 0, 255 )));
  ++output;
} );

and this is to BGR32:

auto output = reinterpret_cast<uint32_t *>(*data);
iterateImage( img, bytes_per_pixel, [ & ]( const uint8_t *stream )
{
  *output = (static_cast<uint32_t>(static_cast<uint8_t>(B( stream, 0, 255 ))) << 24U) |
            (static_cast<uint32_t>(static_cast<uint8_t>(G( stream, 0, 255 ))) << 16U) |
            (static_cast<uint32_t>(static_cast<uint8_t>(R( stream, 0, 255 ))) << 8U) |
            255U;
  ++output;
} );

The functions B, G, R extract the channels from the pixel at stream and map the values to the given range.
The problem:
Whereas for RGB32, the image is as expected (gray), for BGR32 for some reason the image is semi-transparent red which shouldn't be possible since the B, G, R functions are the same in this case (input is a single channel image).

To test my hypothesis that the order is not as expected I used the following test:

auto output = reinterpret_cast<uint32_t *>(*data);
int count = img.width * img.height / 4;
int i = 0;
iterateImage( img, bytes_per_pixel, [ & ]( const uint8_t *stream )
{
  if ((i / count) == 0) *output = 0xff000000;
  else if ((i / count) == 1) *output = 0x00ff0000;
  else if ((i / count) == 2) *output = 0x0000ff00;
  else if ((i / count) == 3) *output = 0x000000ff;
  ++output;
  ++i;
} );

And indeed the image is 4 bars, from top to bottom: black, blue, green and red.

It appears as if the format for BGR32 (and BGRA32) is actually either 0xAABBGGRR or 0xRRGGBBAA in big-endian. Is this a (known) bug in the docs/implementation or am I missing something?

Best regards,
Stefan Fabian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20191114/efc2b811/attachment.html>


More information about the Interest mailing list