Question

I'm capturing image data from a webcam using Video4Linux2. The pixel format returned by the device is V4L2_PIX_FMT_YUYV. According to http://linuxtv.org/downloads/v4l-dvb-apis/V4L2-PIX-FMT-YUYV.html this is the same as YUV422 so I used a YUV422 to RGB24 conversion based on the description at http://paulbourke.net/dataformats/yuv/ .

Amazingly the result is a strange violet/green picture. So it seems YUYV is something different than YUV422 (and there also exists a pixel format V4L2_PIX_FMT_YUV422P which is/is not the same?).

So I'm totally confused now: how can I convert a V4L2_PIX_FMT_YUYV bitmap to real RGB24? Are there any examples out there?

Was it helpful?

Solution

Too long to put in a comment...

4:2:2 is not a pixel-format, it is just a notation about how the chroma-data have been subsampled. According to the linuxtv-link, V4L2_PIX_FMT_YUYV is identical to YUYV or YUY2. The ultimate reference on the subject is http://www.fourcc.org. Have a look at what it says about YUY2 at http://www.fourcc.org/yuv.php#YUYV

       Horizontal   Vertical
Y Sample Period 1   1
V Sample Period 2   1
U Sample Period 2   1

To verify that that the input format indeed is YUYV you can use a viewer I wrote using SDL; which natively supports this format (among others)

https://github.com/figgis/yuv-viewer

See also http://www.fourcc.org/fccyvrgb.php for correct formulas for rgb/yuv-conversion.

Take it from there and drop me a comment if you need further assistance...

OTHER TIPS

I had a similar problem and the issue was endianness. V4L returns pixel data as a series of bytes which I was casting to 16 bit ints. Because of the endianness of my machine the Y and Cb (or Y and Cr for odd pixels) values were getting swapped and I was getting a weird violet/green image.

The solution was just to change how I was extracting Y, Cb and Cr from my 16 bit ints. That is to say, instead of this:

int y = pixbuf[i] & 0xFF00) >> 8;
int u = pixbuf[(i / 2) * 2] & 0xFF;
int v = pixbuf[(i / 2) * 2 + 1] & 0xFF;

I should have done this:

int y = (pixbuf[i] & 0xFF);
int u = (pixbuf[(i / 2) * 2] & 0xFF00) >> 8;
int v = (pixbuf[(i / 2) * 2 + 1] & 0xFF00) >> 8;

Or indeed just processed them as a sequence of bytes like a sensible person...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top