If you have any experience in programming computer graphics, you probably know all about red/green/blue (RGB) video modes and pixel formats. Guess what? It is all useless now that you are working on video codec technology!
No, that’s not entirely true. Some video codecs operate on RGB video natively. A majority of modern codecs use some kind of YUV colorspace. We will get to that. Since many programmers are familiar with RGB pixel formats, let’s use that as a starting point.
RGB Colors
To review, computers generally display RGB pixels. These pixels have red (R), green (G), and blue (B) components to them. Here are the various combinations of R, G, and B components at their minimum (0) and maximum (255/0xFF) values:
R | G | B | color | notes: |
---|---|---|---|---|
0x00 | 0x00 | 0x00 | absence of R, G, and B = full black | |
0x00 | 0x00 | 0xFF | full blue | |
0x00 | 0xFF | 0x00 | full green | |
0x00 | 0xFF | 0xFF | ||
0xFF | 0x00 | 0x00 | full red | |
0xFF | 0x00 | 0xFF | ||
0xFF | 0xFF | 0x00 | ||
0xFF | 0xFF | 0xFF | full R, G, and B combine to make full white |
YUV Colors
If you are used to dealing with RGB colors, YUV will seem a bit unintuitive at first. What does YUV stand for? Nothing you would guess. It turns out Y stands for intensity. U stands for blue and V stands for red. U is also denoted as Cb and V is also denoted as Cr. So YUV is sometimes written as YCbCr.
Here are the various combinations of Y, U, and V components at their minimum (0) and maximum (255/0xFF) values:
Y | U/ Cb |
V/ Cr |
color | notes |
---|---|---|---|---|
0x00 | 0x00 | 0x00 | ||
0x00 | 0x00 | 0xFF | ||
0x00 | 0xFF | 0x00 | ||
0x00 | 0xFF | 0xFF | ||
0xFF | 0x00 | 0x00 | full green | |
0xFF | 0x00 | 0xFF | ||
0xFF | 0xFF | 0x00 | ||
0xFF | 0xFF | 0xFF | ||
0x00 | 0x80 | 0x80 | full black | |
0x80 | 0x80 | 0x80 | ||
0xFF | 0x80 | 0x80 | full white |
So, all minimum and all maximum components do not generate intuitive (read: similar to RGB) results. In fact, all 0s in the YUV colorspace result in a dull green rather than black. That last point is useful to understand when a video is displaying a lot of green block errors– that probably means that the decoder is skipping blocks of data completely and leaving the underlying YUV data as all 0.
Further Reading:
- YCbCr at the MultimediaWiki
- YCbCr Formats category page at the MultimediaWiki
Hey, U and V are actually signed! So really we talk about 0xFF 0 0 as white and 0 0 0 as black, and green would be (X -128 -128).
Color gamut warrants a mention. YUV=0,-128,-128 doesn’t correspond to any RGB color. It should have negative R and B values, i.e. green colored but with total brightness 0, if that makes any sense :). Dull green is just an approximation you get by clipping the negative values to 0. It is the conventional approximation, but I think that has more to do with computational efficiency than correctness.
This is eerily reminiscent of when I posted about Sound Blaster frequencies (and here is the correction).
However, the formulas I was working from are:
R = Y + C1 * (V – 128)
G = Y – C2 * (V – 128) – C3 * (U – 128)
B = Y + C4 * (U – 128)
So that accounts for the scale.
@Pengvado: Indeed, there is a lot of theory behind this. Then there is the difference between regular YUV and full-scale/JPEG YUV in FFmpeg (PIX_FMT_YUV420P vs. PIX_FMT_YUVJ420P).
I produce LCD TVs for bathrooms.
When feeding the TV via HDMI from an IP STB the screen colours are ok. When I place the TV into stand-by and then turn the TV on again from stand-by the colours are bright green.
The main board manufacturer has asked if the STB is transmitting in RGB, YUV 422 or 444.
Any ideas please anyone..?
Chris