***********
YUV support
***********

README.yuv Contributors:
 Pascal Bauermeister <pascal.bauermeister@smartdata.ch>


What is YUV ?
------------- 

YUV is the standard for supplying a video signal to a TV. It is common
denominator for most TV standards, using a lot of variants, such as:

  - YIQ:
    NTSC takes U & V component, rotates them by 33 degree, then
    renames them I & Q (in phase, in quadrature), hence "YIQ". NTSC
    stands for "National Television System Committee".

  - YUV:
    PAL takes U & V and inverts V's phase every second line. PAL
    stands for "Phase Alternation Line".

  - YDrDb:
    SECAM is using a different color matrix and transmits Red and Blue
    alternately on separated FM carriers. SECAM stands, in French, for
    "Sequentiel Couleur A Memoire".

The theory of YUV encoding is beyond the scope of this README, but
here is, in short, the difference between RGB and YUV: While RGB
describes a pixel by its red, green and blue chroma components, YUV
describes a pixel by its luminance and two chrominance components, as
follows:

  Name Role            Formula                              Range
  ---- --------------- ------------------------------------ -----------
  - Y  luma            0.299 * R  + 0.587 * G  + 0.114 * B  [   0..255]
  - U  'blue' chroma   0.492 * ( B - Y )                    [-112..112]
  - V  'red' chroma    0.877 * ( R - Y )                    [-157..157]

When only Y is transmitted, the image can be seen in monochrome. This
is a reminiscence of the b/w television.

When we talk about color encoding, there are three distinct aspects to
consider:

  - The electrical signal, made by the encoder, carried by the wires.
  - The digital stream format, as well as the file format.
  - The memory representation, subject to different organisations,
    that can save (or not) memory, and ease (or not) graphical
    operations, and reduce (or not) the complexity of the encoder.

While RGB is commonly used in the computer world, YUV encoding is very
much used in the world of video devices (digital cams, DVD players,
set-top-boxes, etc). Some graphical engines support YUV natively.


YUV and the linux framebuffer
-----------------------------

With a kernel supporting /dev/fb for a YUV engine, fbdev.c is the
right place to integrate YUV encoding in pgserver, because only pixel
encoding is concerned (all other operations are identical).

As with RGB, there are several ways to represent a YUV pixel in the fb
memory.


YUV and pgserver
----------------

1. The wanted YUV support must be selected by doing 'make menuconfig'
and selecting the wanted options under 'Video Drivers' -> 'Linux
framebuffer device'.

2. The framebuffer's depth and resolution should be set prior to
starting pgserver, using the fbset program:

   fbset -depth <your_depth> <other_options>


YUV8 encoding
-------------

It is available when depth is 8.

If /dev/fb supports RGB palette loading (which is the case of
RedWood4), YUV8 does not need anything particular other than having
'Video Drivers' -> 'Linux framebuffer device' checked
(DRIVER_FBDEV=y).


YUV16 encoding
--------------

It is available when depth is 16, and 'Video Drivers' -> 'Linux
framebuffer device' -> 'YUV16' is checked (CONFIG_FB_YUV16_422_PLANAR=y).

The fb memory is organized in two equal consecutive segments, each one
of xres*yres bytes (thus the total memory is xres*yres*2 bytes, as
expected), following the so-called "4:2:2" scheme:

  - The first segment holds Y bytes, one for each pixel.
  - The second segment holds UV pairs (i.e. one U byte followed by one
    V byte), each pair shared by two consecutively horizontal pixels.

Due to the fact that UV sharing leads to a quality loss, especially
when multiple pixel/getpixel operations are done. However, the
spectrum of available colors is equivalent to a depth of 32 bpp. The
16 bpp depth introduces a spatial loss (chroma dirty borders effect),
rhather than a reduced color sensitivity.

Implementation notes:

Pgserver is set to 32 bpp so that offscreen bitmaps hold the full
color information and not just 16 bpp RGB. The YUV conversion is done
in pixel() when we write to the fb mem. A 32 bpp shadow buffer is used
to a) compensate the spatial loss due to the fact that two pixels
share the same UV pair and b) to avoid having to do a YUV -> RGB
conversion in getpixel().


Todo list
--------- 

- Write a YUV16 accelerator functions (e.g. in a fbdev_yuv16_acc.c
  file).
- Support more YUV depths if needed.

[END]
