Home | History | Annotate | Download | only in camera
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdint.h>
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 #ifdef _WIN32
     21 #elif _DARWIN_C_SOURCE
     22 #else
     23 #include <linux/videodev2.h>
     24 #endif
     25 #include "android/camera/camera-format-converters.h"
     26 
     27 #define  E(...)    derror(__VA_ARGS__)
     28 #define  W(...)    dwarning(__VA_ARGS__)
     29 #define  D(...)    VERBOSE_PRINT(camera,__VA_ARGS__)
     30 #define  D_ACTIVE  VERBOSE_CHECK(camera)
     31 
     32  /*
     33  * NOTE: RGB and big/little endian considerations. Wherewer in this code RGB
     34  * pixels are represented as WORD, or DWORD, the color order inside the
     35  * WORD / DWORD matches the one that would occur if that WORD / DWORD would have
     36  * been read from the typecasted framebuffer:
     37  *
     38  *      const uint32_t rgb = *reinterpret_cast<const uint32_t*>(framebuffer);
     39  *
     40  * So, if this code runs on the little endian CPU, red color in 'rgb' would be
     41  * masked as 0x000000ff, and blue color would be masked as 0x00ff0000, while if
     42  * the code runs on a big endian CPU, the red color in 'rgb' would be masked as
     43  * 0xff000000, and blue color would be masked as 0x0000ff00,
     44  */
     45 
     46 /*
     47  * RGB565 color masks
     48  */
     49 
     50 #ifndef HOST_WORDS_BIGENDIAN
     51 static const uint16_t kRed5     = 0x001f;
     52 static const uint16_t kGreen6   = 0x07e0;
     53 static const uint16_t kBlue5    = 0xf800;
     54 #else   // !HOST_WORDS_BIGENDIAN
     55 static const uint16_t kRed5     = 0xf800;
     56 static const uint16_t kGreen6   = 0x07e0;
     57 static const uint16_t kBlue5    = 0x001f;
     58 #endif  // !HOST_WORDS_BIGENDIAN
     59 
     60 /*
     61  * RGB32 color masks
     62  */
     63 
     64 #ifndef HOST_WORDS_BIGENDIAN
     65 static const uint32_t kRed8     = 0x000000ff;
     66 static const uint32_t kGreen8   = 0x0000ff00;
     67 static const uint32_t kBlue8    = 0x00ff0000;
     68 #else   // !HOST_WORDS_BIGENDIAN
     69 static const uint32_t kRed8     = 0x00ff0000;
     70 static const uint32_t kGreen8   = 0x0000ff00;
     71 static const uint32_t kBlue8    = 0x000000ff;
     72 #endif  // !HOST_WORDS_BIGENDIAN
     73 
     74 /*
     75  * Extracting, and saving color bytes from / to WORD / DWORD RGB.
     76  */
     77 
     78 #ifndef HOST_WORDS_BIGENDIAN
     79 /* Extract red, green, and blue bytes from RGB565 word. */
     80 #define R16(rgb)    (uint8_t)((rgb) & kRed5)
     81 #define G16(rgb)    (uint8_t)(((rgb) & kGreen6) >> 5)
     82 #define B16(rgb)    (uint8_t)(((rgb) & kBlue5) >> 11)
     83 /* Make 8 bits red, green, and blue, extracted from RGB565 word. */
     84 #define R16_32(rgb) (uint8_t)((((rgb) & kRed5) << 3) | (((rgb) & kRed5) >> 2))
     85 #define G16_32(rgb) (uint8_t)((((rgb) & kGreen6) >> 3) | (((rgb) & kGreen6) >> 9))
     86 #define B16_32(rgb) (uint8_t)((((rgb) & kBlue5) >> 8) | (((rgb) & kBlue5) >> 14))
     87 /* Extract red, green, and blue bytes from RGB32 dword. */
     88 #define R32(rgb)    (uint8_t)((rgb) & kRed8)
     89 #define G32(rgb)    (uint8_t)((((rgb) & kGreen8) >> 8) & 0xff)
     90 #define B32(rgb)    (uint8_t)((((rgb) & kBlue8) >> 16) & 0xff)
     91 /* Build RGB565 word from red, green, and blue bytes. */
     92 #define RGB565(r, g, b) (uint16_t)(((((uint16_t)(b) << 6) | (g)) << 5) | (r))
     93 /* Build RGB32 dword from red, green, and blue bytes. */
     94 #define RGB32(r, g, b) (uint32_t)(((((uint32_t)(b) << 8) | (g)) << 8) | (r))
     95 #else   // !HOST_WORDS_BIGENDIAN
     96 /* Extract red, green, and blue bytes from RGB565 word. */
     97 #define R16(rgb)    (uint8_t)(((rgb) & kRed5) >> 11)
     98 #define G16(rgb)    (uint8_t)(((rgb) & kGreen6) >> 5)
     99 #define B16(rgb)    (uint8_t)((rgb) & kBlue5)
    100 /* Make 8 bits red, green, and blue, extracted from RGB565 word. */
    101 #define R16_32(rgb) (uint8_t)((((rgb) & kRed5) >> 8) | (((rgb) & kRed5) >> 14))
    102 #define G16_32(rgb) (uint8_t)((((rgb) & kGreen6) >> 3) | (((rgb) & kGreen6) >> 9))
    103 #define B16_32(rgb) (uint8_t)((((rgb) & kBlue5) << 3) | (((rgb) & kBlue5) >> 2))
    104 /* Extract red, green, and blue bytes from RGB32 dword. */
    105 #define R32(rgb)    (uint8_t)(((rgb) & kRed8) >> 16)
    106 #define G32(rgb)    (uint8_t)(((rgb) & kGreen8) >> 8)
    107 #define B32(rgb)    (uint8_t)((rgb) & kBlue8)
    108 /* Build RGB565 word from red, green, and blue bytes. */
    109 #define RGB565(r, g, b) (uint16_t)(((((uint16_t)(r) << 6) | (g)) << 5) | (b))
    110 /* Build RGB32 dword from red, green, and blue bytes. */
    111 #define RGB32(r, g, b) (uint32_t)(((((uint32_t)(r) << 8) | (g)) << 8) | (b))
    112 #endif  // !HOST_WORDS_BIGENDIAN
    113 
    114 /*
    115  * BAYER bitmasks
    116  */
    117 
    118 /* Bitmask for 8-bits BAYER pixel. */
    119 #define kBayer8     0xff
    120 /* Bitmask for 10-bits BAYER pixel. */
    121 #define kBayer10    0x3ff
    122 /* Bitmask for 12-bits BAYER pixel. */
    123 #define kBayer12    0xfff
    124 
    125 /* An union that simplifies breaking 32 bit RGB into separate R, G, and B colors.
    126  */
    127 typedef union RGB32_t {
    128     uint32_t    color;
    129     struct {
    130 #ifndef HOST_WORDS_BIGENDIAN
    131         uint8_t r; uint8_t g; uint8_t b; uint8_t a;
    132 #else   // !HOST_WORDS_BIGENDIAN
    133         uint8_t a; uint8_t b; uint8_t g; uint8_t r;
    134 #endif  // HOST_WORDS_BIGENDIAN
    135     };
    136 } RGB32_t;
    137 
    138 /* Clips a value to the unsigned 0-255 range, treating negative values as zero.
    139  */
    140 static __inline__ int
    141 clamp(int x)
    142 {
    143     if (x > 255) return 255;
    144     if (x < 0)   return 0;
    145     return x;
    146 }
    147 
    148 /********************************************************************************
    149  * Basics of RGB -> YUV conversion
    150  *******************************************************************************/
    151 
    152 /*
    153  * RGB -> YUV conversion macros
    154  */
    155 #define RGB2Y(r, g, b) (uint8_t)(((66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) +  16)
    156 #define RGB2U(r, g, b) (uint8_t)(((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128)
    157 #define RGB2V(r, g, b) (uint8_t)(((112 * (r) - 94 * (g) -  18 * (b) + 128) >> 8) + 128)
    158 
    159 /* Converts R8 G8 B8 color to YUV. */
    160 static __inline__ void
    161 R8G8B8ToYUV(uint8_t r, uint8_t g, uint8_t b, uint8_t* y, uint8_t* u, uint8_t* v)
    162 {
    163     *y = RGB2Y((int)r, (int)g, (int)b);
    164     *u = RGB2U((int)r, (int)g, (int)b);
    165     *v = RGB2V((int)r, (int)g, (int)b);
    166 }
    167 
    168 /* Converts RGB565 color to YUV. */
    169 static __inline__ void
    170 RGB565ToYUV(uint16_t rgb, uint8_t* y, uint8_t* u, uint8_t* v)
    171 {
    172     R8G8B8ToYUV(R16_32(rgb), G16_32(rgb), B16_32(rgb), y, u, v);
    173 }
    174 
    175 /* Converts RGB32 color to YUV. */
    176 static __inline__ void
    177 RGB32ToYUV(uint32_t rgb, uint8_t* y, uint8_t* u, uint8_t* v)
    178 {
    179     RGB32_t rgb_c;
    180     rgb_c.color = rgb;
    181     R8G8B8ToYUV(rgb_c.r, rgb_c.g, rgb_c.b, y, u, v);
    182 }
    183 
    184 /********************************************************************************
    185  * Basics of YUV -> RGB conversion.
    186  *******************************************************************************/
    187 
    188 /*
    189  * YUV -> RGB conversion macros
    190  */
    191 
    192 /* "Optimized" macros that take specialy prepared Y, U, and V values:
    193  *  C = Y - 16
    194  *  D = U - 128
    195  *  E = V - 128
    196  */
    197 #define YUV2RO(C, D, E) clamp((298 * (C) + 409 * (E) + 128) >> 8)
    198 #define YUV2GO(C, D, E) clamp((298 * (C) - 100 * (D) - 208 * (E) + 128) >> 8)
    199 #define YUV2BO(C, D, E) clamp((298 * (C) + 516 * (D) + 128) >> 8)
    200 
    201 /*
    202  *  Main macros that take the original Y, U, and V values
    203  */
    204 #define YUV2R(y, u, v) clamp((298 * ((y)-16) + 409 * ((v)-128) + 128) >> 8)
    205 #define YUV2G(y, u, v) clamp((298 * ((y)-16) - 100 * ((u)-128) - 208 * ((v)-128) + 128) >> 8)
    206 #define YUV2B(y, u, v) clamp((298 * ((y)-16) + 516 * ((u)-128) + 128) >> 8)
    207 
    208 
    209 /* Converts YUV color to RGB565. */
    210 static __inline__ uint16_t
    211 YUVToRGB565(int y, int u, int v)
    212 {
    213     /* Calculate C, D, and E values for the optimized macro. */
    214     y -= 16; u -= 128; v -= 128;
    215     const uint16_t r = YUV2RO(y,u,v) >> 3;
    216     const uint16_t g = YUV2GO(y,u,v) >> 2;
    217     const uint16_t b = YUV2BO(y,u,v) >> 3;
    218     return RGB565(r, g, b);
    219 }
    220 
    221 /* Converts YUV color to RGB32. */
    222 static __inline__ uint32_t
    223 YUVToRGB32(int y, int u, int v)
    224 {
    225     /* Calculate C, D, and E values for the optimized macro. */
    226     y -= 16; u -= 128; v -= 128;
    227     RGB32_t rgb;
    228     rgb.r = YUV2RO(y,u,v);
    229     rgb.g = YUV2GO(y,u,v);
    230     rgb.b = YUV2BO(y,u,v);
    231     return rgb.color;
    232 }
    233 
    234 /* Converts YUV color to separated RGB32 colors. */
    235 static __inline__ void
    236 YUVToRGBPix(int y, int u, int v, uint8_t* r, uint8_t* g, uint8_t* b)
    237 {
    238     /* Calculate C, D, and E values for the optimized macro. */
    239     y -= 16; u -= 128; v -= 128;
    240     *r = (uint8_t)YUV2RO(y,u,v);
    241     *g = (uint8_t)YUV2GO(y,u,v);
    242     *b = (uint8_t)YUV2BO(y,u,v);
    243 }
    244 
    245 /* Computes a luminance value after taking the exposure compensation.
    246  * value into account.
    247  *
    248  * Param:
    249  * inputY - The input luminance value.
    250  * Return:
    251  * The luminance value after adjusting the exposure compensation.
    252  */
    253 static __inline__ uint8_t
    254 _change_exposure(uint8_t inputY, float exp_comp)
    255 {
    256     return (uint8_t)clamp((float)inputY * exp_comp);
    257 }
    258 
    259 /* Adjusts an RGB pixel for the given exposure compensation. */
    260 static __inline__ void
    261 _change_exposure_RGB(uint8_t* r, uint8_t* g, uint8_t* b, float exp_comp)
    262 {
    263     uint8_t y, u, v;
    264     R8G8B8ToYUV(*r, *g, *b, &y, &u, &v);
    265     YUVToRGBPix(_change_exposure(y, exp_comp), u, v, r, g, b);
    266 }
    267 
    268 /* Adjusts an RGB pixel for the given exposure compensation. */
    269 static __inline__ void
    270 _change_exposure_RGB_i(int* r, int* g, int* b, float exp_comp)
    271 {
    272     uint8_t y, u, v;
    273     R8G8B8ToYUV(*r, *g, *b, &y, &u, &v);
    274     y = _change_exposure(y, exp_comp);
    275     *r = YUV2RO(y,u,v);
    276     *g = YUV2GO(y,u,v);
    277     *b = YUV2BO(y,u,v);
    278 }
    279 
    280 /* Computes the pixel value after adjusting the white balance to the current
    281  * one. The input the y, u, v channel of the pixel and the adjusted value will
    282  * be stored in place. The adjustment is done in RGB space.
    283  */
    284 static __inline__ void
    285 _change_white_balance_YUV(uint8_t* y,
    286                           uint8_t* u,
    287                           uint8_t* v,
    288                           float r_scale,
    289                           float g_scale,
    290                           float b_scale)
    291 {
    292     int r = (float)(YUV2R((int)*y, (int)*u, (int)*v)) / r_scale;
    293     int g = (float)(YUV2G((int)*y, (int)*u, (int)*v)) / g_scale;
    294     int b = (float)(YUV2B((int)*y, (int)*u, (int)*v)) / b_scale;
    295 
    296     *y = RGB2Y(r, g, b);
    297     *u = RGB2U(r, g, b);
    298     *v = RGB2V(r, g, b);
    299 }
    300 
    301 /* Computes the pixel value after adjusting the white balance to the current
    302  * one. The input the r, and b channels of the pixel and the adjusted value will
    303  * be stored in place.
    304  */
    305 static __inline__ void
    306 _change_white_balance_RGB(int* r,
    307                           int* g,
    308                           int* b,
    309                           float r_scale,
    310                           float g_scale,
    311                           float b_scale)
    312 {
    313     *r = (float)*r / r_scale;
    314     *g = (float)*g / g_scale;
    315     *b = (float)*b / b_scale;
    316 }
    317 
    318 /* Computes the pixel value after adjusting the white balance to the current
    319  * one. The input the r, and b channels of the pixel and the adjusted value will
    320  * be stored in place.
    321  */
    322 static __inline__ void
    323 _change_white_balance_RGB_b(uint8_t* r,
    324                             uint8_t* g,
    325                             uint8_t* b,
    326                             float r_scale,
    327                             float g_scale,
    328                             float b_scale)
    329 {
    330     *r = (float)*r / r_scale;
    331     *g = (float)*g / g_scale;
    332     *b = (float)*b / b_scale;
    333 }
    334 
    335 /********************************************************************************
    336  * Generic converters between YUV and RGB formats
    337  *******************************************************************************/
    338 
    339 /*
    340  * The converters go line by line, convering one frame format to another.
    341  * It's pretty much straight forward for RGB/BRG, where all colors are
    342  * grouped next to each other in memory. The only two things that differ one RGB
    343  * format from another are:
    344  * - Is it an RGB, or BRG (i.e. color ordering)
    345  * - Is it 16, 24, or 32 bits format.
    346  * All these differences are addressed by load_rgb / save_rgb routines, provided
    347  * for each format in the RGB descriptor to load / save RGB color bytes from / to
    348  * the buffer. As far as moving from one RGB pixel to the next, there
    349  * are two question to consider:
    350  * - How many bytes it takes to encode one RGB pixel (could be 2, 3, or 4)
    351  * - How many bytes it takes to encode a line (i.e. line alignment issue, which
    352  *   makes sence only for 24-bit formats, since 16, and 32 bit formats provide
    353  *   automatic word alignment.)
    354  * The first question is answered with the 'rgb_inc' field of the RGB descriptor,
    355  * and the second one is done by aligning rgb pointer up to the nearest 16 bit
    356  * boundaries at the end of each line.
    357  * YUV format has much greater complexity for conversion. in YUV color encoding
    358  * is divided into three separate panes that can be mixed together in any way
    359  * imaginable. Fortunately, there are still some consistent patterns in different
    360 
    361  * YUV formats that can be abstracted through a descriptor:
    362  * - At the line-by-line level, colors are always groupped aroud pairs of pixels,
    363  *   where each pixel in the pair has its own Y value, and each pair of pixels
    364  *   share thesame U, and V values.
    365  * - Position of Y, U, and V is the same for each pair, so the distance between
    366  *   Ys, and U/V for adjacent pairs is the same.
    367  * - Inside the pair, the distance between two Ys is always the same.
    368 
    369  * Moving between the lines in YUV can also be easily formalized. Essentially,
    370  * there are three ways how color panes are arranged:
    371  * 1. All interleaved, where all three Y, U, and V values are encoded together in
    372  *    one block:
    373  *               1,2  3,4  5,6      n,n+1
    374  *              YUVY YUVY YUVY .... YUVY
    375  *
    376  *    This type is used to encode YUV 4:2:2 formats.
    377  *
    378  * 2. One separate block of memory for Y pane, and one separate block of memory
    379  *    containing interleaved U, and V panes.
    380  *
    381  *      YY | YY | YY | YY
    382  *      YY | YY | YY | YY
    383  *      -----------------
    384  *      UV | UV | UV | UV
    385  *      -----------------
    386  *
    387  *    This type is used to encode 4:2:0 formats.
    388  *
    389  * 3. Three separate blocks of memory for each pane.
    390  *
    391  *      YY | YY | YY | YY
    392  *      YY | YY | YY | YY
    393  *      -----------------
    394  *      U  | U  | U  | U
    395  *      V  | V  | V  | V
    396  *      -----------------
    397  *
    398  *    This type is also used to encode 4:2:0 formats.
    399  *
    400  * Note that in cases 2, and 3 each pair of U and V is shared among four pixels,
    401  * grouped together as they are groupped in the framebeffer: divide the frame's
    402  * rectangle into 2x2 pixels squares, starting from 0,0 corner - and each square
    403  * represents the group of pixels that share same pair of UV values. So, each
    404  * line in the U/V panes table is shared between two adjacent lines in Y pane,
    405  * which provides a pattern on how to move between U/V lines as we move between
    406  * Y lines.
    407  *
    408  * So, all these patterns can be coded in a YUV format descriptor, so there can
    409  * just one generic way of walking YUV frame.
    410  *
    411  * BAYER format.
    412  * We don't use BAYER inside the guest system, so there is no need to have a
    413  * converter to the BAYER formats, only from it. The color approximation  used in
    414  * the BAYER format converters implemented here simply averages corresponded
    415  * color values found in pixels sorrounding the one for which RGB colors are
    416  * calculated.
    417  *
    418  * Performance considerations:
    419  * Since converters implemented here are intended to work as part of the camera
    420  * emulation, making the code super performant is not a priority at all. There
    421  * will be enough loses in other parts of the emultion to overlook any slight
    422  * inefficiences in the conversion algorithm as neglectable.
    423  */
    424 
    425 typedef struct RGBDesc RGBDesc;
    426 typedef struct YUVDesc YUVDesc;
    427 typedef struct BayerDesc BayerDesc;
    428 
    429 /* Prototype for a routine that loads RGB colors from an RGB/BRG stream.
    430  * Param:
    431  *  rgb - Pointer to a pixel inside the stream where to load colors from.
    432  *  r, g, b - Upon return will contain red, green, and blue colors for the pixel
    433  *      addressed by 'rgb' pointer.
    434  * Return:
    435  *  Pointer to the next pixel in the stream.
    436  */
    437 typedef const void* (*load_rgb_func)(const void* rgb,
    438                                      uint8_t* r,
    439                                      uint8_t* g,
    440                                      uint8_t* b);
    441 
    442 /* Prototype for a routine that saves RGB colors to an RGB/BRG stream.
    443  * Param:
    444  *  rgb - Pointer to a pixel inside the stream where to save colors.
    445  *  r, g, b - Red, green, and blue colors to save to the pixel addressed by
    446  *      'rgb' pointer.
    447  * Return:
    448  *  Pointer to the next pixel in the stream.
    449  */
    450 typedef void* (*save_rgb_func)(void* rgb, uint8_t r, uint8_t g, uint8_t b);
    451 
    452 /* Prototype for a routine that calculates an offset of the first U value for the
    453  * given line in a YUV framebuffer.
    454  * Param:
    455  *  desc - Descriptor for the YUV frame for which the offset is being calculated.
    456  *  line - Zero-based line number for which to calculate the offset.
    457  *  width, height - Frame dimensions.
    458  * Return:
    459  *  Offset of the first U value for the given frame line. The offset returned
    460  *  here is relative to the beginning of the YUV framebuffer.
    461  */
    462 typedef int (*u_offset_func)(const YUVDesc* desc, int line, int width, int height);
    463 
    464 /* Prototype for a routine that calculates an offset of the first V value for the
    465  * given line in a YUV framebuffer.
    466  * Param:
    467  *  desc - Descriptor for the YUV frame for which the offset is being calculated.
    468  *  line - Zero-based line number for which to calculate the offset.
    469  *  width, height - Frame dimensions.
    470  * Return:
    471  *  Offset of the first V value for the given frame line. The offset returned
    472  *  here is relative to the beginning of the YUV framebuffer.
    473  */
    474 typedef int (*v_offset_func)(const YUVDesc* desc, int line, int width, int height);
    475 
    476 /* RGB/BRG format descriptor. */
    477 struct RGBDesc {
    478     /* Routine that loads RGB colors from a buffer. */
    479     load_rgb_func   load_rgb;
    480     /* Routine that saves RGB colors into a buffer. */
    481     save_rgb_func   save_rgb;
    482     /* Byte size of an encoded RGB pixel. */
    483     int             rgb_inc;
    484 };
    485 
    486 /* YUV format descriptor. */
    487 struct YUVDesc {
    488     /* Offset of the first Y value in a fully interleaved YUV framebuffer. */
    489     int             Y_offset;
    490     /* Distance between two Y values inside a pair of pixels in a fully
    491      * interleaved YUV framebuffer. */
    492     int             Y_inc;
    493     /* Distance between first Y values of the adjacent pixel pairs in a fully
    494      * interleaved YUV framebuffer. */
    495     int             Y_next_pair;
    496     /* Increment between adjacent U/V values in a YUV framebuffer. */
    497     int             UV_inc;
    498     /* Controls location of the first U value in YUV framebuffer. Depending on
    499      * the actual YUV format can mean three things:
    500      *  - For fully interleaved YUV formats contains offset of the first U value
    501      *    in each line.
    502      *  - For YUV format that use separate, but interleaved UV pane, this field
    503      *    contains an offset of the first U value in the UV pane.
    504      *  - For YUV format that use fully separated Y, U, and V panes this field
    505      *    defines order of U and V panes in the framebuffer:
    506      *      = 1 - U pane comes first, right after Y pane.
    507      *      = 0 - U pane follows V pane that startes right after Y pane. */
    508     int             U_offset;
    509     /* Controls location of the first V value in YUV framebuffer.
    510      * See comments to U_offset for more info. */
    511     int             V_offset;
    512     /* Routine that calculates an offset of the first U value for the given line
    513      * in a YUV framebuffer. */
    514     u_offset_func   u_offset;
    515     /* Routine that calculates an offset of the first V value for the given line
    516      * in a YUV framebuffer. */
    517     v_offset_func   v_offset;
    518 };
    519 
    520 /* Bayer format descriptor. */
    521 struct BayerDesc {
    522     /* Defines color ordering in the BAYER framebuffer. Can be one of the four:
    523      *  - "GBRG" for GBGBGB / RGRGRG
    524      *  - "GRBG" for GRGRGR / BGBGBG
    525      *  - "RGGB" for RGRGRG / GBGBGB
    526      *  - "BGGR" for BGBGBG / GRGRGR
    527      */
    528     const char* color_order;
    529     /* Bitmask for valid bits in the pixel:
    530      *  - 0xff  For a 8-bit BAYER format
    531      *  - 0x3ff For a 10-bit BAYER format
    532      *  - 0xfff For a 12-bit BAYER format
    533      */
    534     int         mask;
    535 };
    536 
    537 /********************************************************************************
    538  * RGB/BRG load / save routines.
    539  *******************************************************************************/
    540 
    541 /* Loads R, G, and B colors from a RGB32 framebuffer. */
    542 static const void*
    543 _load_RGB32(const void* rgb, uint8_t* r, uint8_t* g, uint8_t* b)
    544 {
    545     const uint8_t* rgb_ptr = (const uint8_t*)rgb;
    546     *r = rgb_ptr[0]; *g = rgb_ptr[1]; *b = rgb_ptr[2];
    547     return rgb_ptr + 4;
    548 }
    549 
    550 /* Saves R, G, and B colors to a RGB32 framebuffer. */
    551 static void*
    552 _save_RGB32(void* rgb, uint8_t r, uint8_t g, uint8_t b)
    553 {
    554     uint8_t* rgb_ptr = (uint8_t*)rgb;
    555     rgb_ptr[0] = r; rgb_ptr[1] = g; rgb_ptr[2] = b;
    556     return rgb_ptr + 4;
    557 }
    558 
    559 /* Loads R, G, and B colors from a BRG32 framebuffer. */
    560 static const void*
    561 _load_BRG32(const void* rgb, uint8_t* r, uint8_t* g, uint8_t* b)
    562 {
    563     const uint8_t* rgb_ptr = (const uint8_t*)rgb;
    564     *r = rgb_ptr[2]; *g = rgb_ptr[1]; *b = rgb_ptr[0];
    565     return rgb_ptr + 4;
    566 }
    567 
    568 /* Saves R, G, and B colors to a BRG32 framebuffer. */
    569 static void*
    570 _save_BRG32(void* rgb, uint8_t r, uint8_t g, uint8_t b)
    571 {
    572     uint8_t* rgb_ptr = (uint8_t*)rgb;
    573     rgb_ptr[2] = r; rgb_ptr[1] = g; rgb_ptr[0] = b;
    574     return rgb_ptr + 4;
    575 }
    576 
    577 /* Loads R, G, and B colors from a RGB24 framebuffer.
    578  * Note that it's the caller's responsibility to ensure proper alignment of the
    579  * returned pointer at the line's break. */
    580 static const void*
    581 _load_RGB24(const void* rgb, uint8_t* r, uint8_t* g, uint8_t* b)
    582 {
    583     const uint8_t* rgb_ptr = (const uint8_t*)rgb;
    584     *r = rgb_ptr[0]; *g = rgb_ptr[1]; *b = rgb_ptr[2];
    585     return rgb_ptr + 3;
    586 }
    587 
    588 /* Saves R, G, and B colors to a RGB24 framebuffer.
    589  * Note that it's the caller's responsibility to ensure proper alignment of the
    590  * returned pointer at the line's break. */
    591 static void*
    592 _save_RGB24(void* rgb, uint8_t r, uint8_t g, uint8_t b)
    593 {
    594     uint8_t* rgb_ptr = (uint8_t*)rgb;
    595     rgb_ptr[0] = r; rgb_ptr[1] = g; rgb_ptr[2] = b;
    596     return rgb_ptr + 3;
    597 }
    598 
    599 /* Loads R, G, and B colors from a BRG32 framebuffer.
    600  * Note that it's the caller's responsibility to ensure proper alignment of the
    601  * returned pointer at the line's break. */
    602 static const void*
    603 _load_BRG24(const void* rgb, uint8_t* r, uint8_t* g, uint8_t* b)
    604 {
    605     const uint8_t* rgb_ptr = (const uint8_t*)rgb;
    606     *r = rgb_ptr[2]; *g = rgb_ptr[1]; *b = rgb_ptr[0];
    607     return rgb_ptr + 3;
    608 }
    609 
    610 /* Saves R, G, and B colors to a BRG24 framebuffer.
    611  * Note that it's the caller's responsibility to ensure proper alignment of the
    612  * returned pointer at the line's break. */
    613 static void*
    614 _save_BRG24(void* rgb, uint8_t r, uint8_t g, uint8_t b)
    615 {
    616     uint8_t* rgb_ptr = (uint8_t*)rgb;
    617     rgb_ptr[2] = r; rgb_ptr[1] = g; rgb_ptr[0] = b;
    618     return rgb_ptr + 3;
    619 }
    620 
    621 /* Loads R, G, and B colors from a RGB565 framebuffer. */
    622 static const void*
    623 _load_RGB16(const void* rgb, uint8_t* r, uint8_t* g, uint8_t* b)
    624 {
    625     const uint16_t rgb16 = *(const uint16_t*)rgb;
    626     *r = R16(rgb16); *g = G16(rgb16); *b = B16(rgb16);
    627     return (const uint8_t*)rgb + 2;
    628 }
    629 
    630 /* Saves R, G, and B colors to a RGB565 framebuffer. */
    631 static void*
    632 _save_RGB16(void* rgb, uint8_t r, uint8_t g, uint8_t b)
    633 {
    634     *(uint16_t*)rgb = RGB565(r & 0x1f, g & 0x3f, b & 0x1f);
    635     return (uint8_t*)rgb + 2;
    636 }
    637 
    638 /* Loads R, G, and B colors from a BRG565 framebuffer. */
    639 static const void*
    640 _load_BRG16(const void* rgb, uint8_t* r, uint8_t* g, uint8_t* b)
    641 {
    642     const uint16_t rgb16 = *(const uint16_t*)rgb;
    643     *r = B16(rgb16); *g = G16(rgb16); *b = R16(rgb16);
    644     return (const uint8_t*)rgb + 2;
    645 }
    646 
    647 /* Saves R, G, and B colors to a BRG565 framebuffer. */
    648 static void*
    649 _save_BRG16(void* rgb, uint8_t r, uint8_t g, uint8_t b)
    650 {
    651     *(uint16_t*)rgb = RGB565(b & 0x1f, g & 0x3f, r & 0x1f);
    652     return (uint8_t*)rgb + 2;
    653 }
    654 
    655 /********************************************************************************
    656  * YUV's U/V offset calculation routines.
    657  *******************************************************************************/
    658 
    659 /* U offset in a fully interleaved YUV 4:2:2 */
    660 static int
    661 _UOffIntrlYUV(const YUVDesc* desc, int line, int width, int height)
    662 {
    663     /* In interleaved YUV 4:2:2 each pair of pixels is encoded with 4 consecutive
    664      * bytes (or 2 bytes per pixel). So line size in a fully interleaved YUV 4:2:2
    665      * is twice its width. */
    666     return line * width * 2 + desc->U_offset;
    667 }
    668 
    669 /* V offset in a fully interleaved YUV 4:2:2 */
    670 static int
    671 _VOffIntrlYUV(const YUVDesc* desc, int line, int width, int height)
    672 {
    673     /* See _UOffIntrlYUV comments. */
    674     return line * width * 2 + desc->V_offset;
    675 }
    676 
    677 /* U offset in an interleaved UV pane of YUV 4:2:0 */
    678 static int
    679 _UOffIntrlUV(const YUVDesc* desc, int line, int width, int height)
    680 {
    681     /* UV pane starts right after the Y pane, that occupies 'height * width'
    682      * bytes. Eacht line in UV pane contains width / 2 'UV' pairs, which makes UV
    683      * lane to contain as many bytes, as the width is.
    684      * Each line in the UV pane is shared between two Y lines. So, final formula
    685      * for the beggining of the UV pane's line for the given line in YUV
    686      * framebuffer is:
    687      *
    688      *    height * width + (line / 2) * width = (height + line / 2) * width
    689      */
    690     return (height + line / 2) * width + desc->U_offset;
    691 }
    692 
    693 /* V offset in an interleaved UV pane of YUV 4:2:0 */
    694 static int
    695 _VOffIntrlUV(const YUVDesc* desc, int line, int width, int height)
    696 {
    697     /* See comments in _UOffIntrlUV. */
    698     return (height + line / 2) * width + desc->V_offset;
    699 }
    700 
    701 /* U offset in a 3-pane YUV 4:2:0 */
    702 static int
    703 _UOffSepYUV(const YUVDesc* desc, int line, int width, int height)
    704 {
    705     /* U, or V pane starts right after the Y pane, that occupies 'height * width'
    706      * bytes. Eacht line in each of U and V panes contains width / 2 elements.
    707      * Also, each line in each of U and V panes is shared between two Y lines.
    708      * So, final formula for the beggining of a line in the U/V pane is:
    709      *
    710      *    <Y pane size> + (line / 2) * width / 2
    711      *
    712      * for the pane that follows right after the Y pane, or
    713      *
    714      *    <Y pane size> + <Y pane size> / 4 + (line / 2) * width / 2
    715      *
    716      * for the second pane.
    717      */
    718     const int y_pane_size = height * width;
    719     if (desc->U_offset) {
    720         /* U pane comes right after the Y pane. */
    721         return y_pane_size + (line / 2) * width / 2;
    722     } else {
    723         /* U pane follows V pane. */
    724         return y_pane_size + y_pane_size / 4 + (line / 2) * width / 2;
    725     }
    726 }
    727 
    728 /* V offset in a 3-pane YUV 4:2:0 */
    729 static int
    730 _VOffSepYUV(const YUVDesc* desc, int line, int width, int height)
    731 {
    732     /* See comment for _UOffSepYUV. */
    733     const int y_pane_size = height * width;
    734     if (desc->V_offset) {
    735         /* V pane comes right after the Y pane. */
    736         return y_pane_size + (line / 2) * width / 2;
    737     } else {
    738         /* V pane follows U pane. */
    739         return y_pane_size + y_pane_size / 4 + (line / 2) * width / 2;
    740     }
    741 }
    742 
    743 /********************************************************************************
    744  * Bayer routines.
    745  *******************************************************************************/
    746 
    747 /* Gets a color value for the given pixel in a bayer framebuffer.
    748  * Param:
    749  *  desc - Bayer framebuffer descriptor.
    750  *  buf - Beginning of the framebuffer.
    751  *  x, y - Coordinates of the pixel inside the framebuffer to get the color for.
    752  *  width - Number of pixel in a line inside the framebuffer.
    753  * Return:
    754  *  Given pixel color.
    755  */
    756 static __inline__ int
    757 _get_bayer_color(const BayerDesc* desc, const void* buf, int x, int y, int width)
    758 {
    759     if (desc->mask == kBayer8) {
    760         /* Each pixel is represented with one byte. */
    761         return *((const uint8_t*)buf + y * width + x);
    762     } else {
    763 #ifndef HOST_WORDS_BIGENDIAN
    764         return *((const int16_t*)buf + y * width + x) & desc->mask;
    765 #else
    766         const uint8_t* pixel = (const uint8_t*)buf + (y * width + x) * 2;
    767         return (((uint16_t)pixel[1] << 8) | pixel[0]) & desc->mask;
    768 #endif  /* !HOST_WORDS_BIGENDIAN */
    769     }
    770 }
    771 
    772 /* Gets an average value of colors that are horisontally adjacent to a pixel in
    773  * a bayer framebuffer.
    774  * Param:
    775  *  desc - Bayer framebuffer descriptor.
    776  *  buf - Beginning of the framebuffer.
    777  *  x, y - Coordinates of the pixel inside the framebuffer that is the center for
    778  *      the calculation.
    779  *  width, height - Framebuffer dimensions.
    780  * Return:
    781  *  Average color for horisontally adjacent pixels.
    782  */
    783 static int
    784 _get_bayer_ave_hor(const BayerDesc* desc,
    785                    const void* buf,
    786                    int x,
    787                    int y,
    788                    int width,
    789                    int height)
    790 {
    791     if (x == 0) {
    792         return _get_bayer_color(desc, buf, x + 1, y, width);
    793     } else if (x == (width - 1)) {
    794         return _get_bayer_color(desc, buf, x - 1, y, width);
    795     } else {
    796         return (_get_bayer_color(desc, buf, x - 1, y, width) +
    797                 _get_bayer_color(desc, buf, x + 1, y, width)) / 2;
    798     }
    799 }
    800 
    801 /* Gets an average value of colors that are vertically adjacent to a pixel in
    802  * a bayer framebuffer.
    803  * Param:
    804  *  desc - Bayer framebuffer descriptor.
    805  *  buf - Beginning of the framebuffer.
    806  *  x, y - Coordinates of the pixel inside the framebuffer that is the center for
    807  *      the calculation.
    808  *  width, height - Framebuffer dimensions.
    809  * Return:
    810  *  Average color for vertically adjacent pixels.
    811  */
    812 static int
    813 _get_bayer_ave_vert(const BayerDesc* desc,
    814                     const void* buf,
    815                     int x,
    816                     int y,
    817                     int width,
    818                     int height)
    819 {
    820     if (y == 0) {
    821         return _get_bayer_color(desc, buf, x, y + 1, width);
    822     } else if (y == (height - 1)) {
    823         return _get_bayer_color(desc, buf, x, y - 1, width);
    824     } else {
    825         return (_get_bayer_color(desc, buf, x, y - 1, width) +
    826                 _get_bayer_color(desc, buf, x, y + 1, width)) / 2;
    827     }
    828 }
    829 
    830 /* Gets an average value of colors that are horisontally and vertically adjacent
    831  * to a pixel in a bayer framebuffer.
    832  * Param:
    833  *  desc - Bayer framebuffer descriptor.
    834  *  buf - Beginning of the framebuffer.
    835  *  x, y - Coordinates of the pixel inside the framebuffer that is the center for
    836  *      the calculation.
    837  *  width, height - Framebuffer dimensions.
    838  * Return:
    839  *  Average color for horisontally and vertically adjacent pixels.
    840  */
    841 static int
    842 _get_bayer_ave_cross(const BayerDesc* desc,
    843                      const void* buf,
    844                      int x,
    845                      int y,
    846                      int width,
    847                      int height)
    848 {
    849     if (x > 0 && x < (width - 1) && y > 0 && y < (height - 1)) {
    850         /* Most of the time the code will take this path. So it makes sence to
    851          * special case it for performance reasons. */
    852         return (_get_bayer_color(desc, buf, x - 1, y, width) +
    853                 _get_bayer_color(desc, buf, x + 1, y, width) +
    854                 _get_bayer_color(desc, buf, x, y - 1, width) +
    855                 _get_bayer_color(desc, buf, x, y + 1, width)) / 4;
    856     } else {
    857         int sum = 0;
    858         int num = 0;
    859 
    860         /* Horisontal sum */
    861         if (x == 0) {
    862             sum += _get_bayer_color(desc, buf, x + 1, y, width);
    863             num++;
    864         } else if (x == (width - 1)) {
    865             sum += _get_bayer_color(desc, buf, x - 1, y, width);
    866             num++;
    867         } else {
    868             sum += _get_bayer_color(desc, buf, x - 1, y, width) +
    869                    _get_bayer_color(desc, buf, x + 1, y, width);
    870             num += 2;
    871         }
    872 
    873         /* Vertical sum */
    874         if (y == 0) {
    875             sum += _get_bayer_color(desc, buf, x, y + 1, width);
    876             num++;
    877         } else if (y == (height - 1)) {
    878             sum += _get_bayer_color(desc, buf, x, y - 1, width);
    879             num++;
    880         } else {
    881             sum += _get_bayer_color(desc, buf, x, y - 1, width) +
    882                    _get_bayer_color(desc, buf, x, y + 1, width);
    883             num += 2;
    884         }
    885 
    886         return sum / num;
    887     }
    888 }
    889 
    890 /* Gets an average value of colors that are diagonally adjacent to a pixel in a
    891  * bayer framebuffer.
    892  * Param:
    893  *  desc - Bayer framebuffer descriptor.
    894  *  buf - Beginning of the framebuffer.
    895  *  x, y - Coordinates of the pixel inside the framebuffer that is the center for
    896  *      the calculation.
    897  *  width, height - Framebuffer dimensions.
    898  * Return:
    899  *  Average color for diagonally adjacent pixels.
    900  */
    901 static int
    902 _get_bayer_ave_diag(const BayerDesc* desc,
    903                     const void* buf,
    904                     int x,
    905                     int y,
    906                     int width,
    907                     int height)
    908 {
    909     if (x > 0 && x < (width - 1) && y > 0 && y < (height - 1)) {
    910         /* Most of the time the code will take this path. So it makes sence to
    911          * special case it for performance reasons. */
    912         return (_get_bayer_color(desc, buf, x - 1, y - 1, width) +
    913                 _get_bayer_color(desc, buf, x + 1, y - 1, width) +
    914                 _get_bayer_color(desc, buf, x - 1, y + 1, width) +
    915                 _get_bayer_color(desc, buf, x + 1, y + 1, width)) / 4;
    916     } else {
    917         int sum = 0;
    918         int num = 0;
    919         int xx, yy;
    920         for (xx = x - 1; xx < (x + 2); xx += 2) {
    921             for (yy = y - 1; yy < (y + 2); yy += 2) {
    922                 if (xx >= 0 && yy >= 0 && xx < width && yy < height) {
    923                     sum += _get_bayer_color(desc, buf, xx, yy, width);
    924                     num++;
    925                 }
    926             }
    927         }
    928         return sum / num;
    929     }
    930 }
    931 
    932 /* Gets pixel color selector for the given pixel in a bayer framebuffer.
    933  * Param:
    934  *  desc - Bayer framebuffer descriptor.
    935  *  x, y - Coordinates of the pixel inside the framebuffer to get the color
    936  *      selector for.
    937  * Return:
    938  *  Pixel color selector:
    939  *      - 'R' - pixel is red.
    940  *      - 'G' - pixel is green.
    941  *      - 'B' - pixel is blue.
    942  */
    943 static __inline__ char
    944 _get_bayer_color_sel(const BayerDesc* desc, int x, int y)
    945 {
    946     return desc->color_order[((y & 1) << 1) | (x & 1)];
    947 }
    948 
    949 /* Calculates RGB colors for a pixel in a bayer framebuffer.
    950  * Param:
    951  *  desc - Bayer framebuffer descriptor.
    952  *  buf - Beginning of the framebuffer.
    953  *  x, y - Coordinates of the pixel inside the framebuffer to get the colors for.
    954  *  width, height - Framebuffer dimensions.
    955  *  red, green bluu - Upon return will contain RGB colors calculated for the pixel.
    956  */
    957 static void
    958 _get_bayerRGB(const BayerDesc* desc,
    959               const void* buf,
    960               int x,
    961               int y,
    962               int width,
    963               int height,
    964               int* red,
    965               int* green,
    966               int* blue)
    967 {
    968     const char pixel_color = _get_bayer_color_sel(desc, x, y);
    969 
    970     if (pixel_color == 'G') {
    971         /* This is a green pixel. */
    972         const char next_pixel_color = _get_bayer_color_sel(desc, x + 1, y);
    973         *green = _get_bayer_color(desc, buf, x, y, width);
    974         if (next_pixel_color == 'R') {
    975             *red = _get_bayer_ave_hor(desc, buf, x, y, width, height);
    976             *blue = _get_bayer_ave_vert(desc, buf, x, y, width, height);
    977         } else {
    978             *red = _get_bayer_ave_vert(desc, buf, x, y, width, height);
    979             *blue = _get_bayer_ave_hor(desc, buf, x, y, width, height);
    980         }
    981     } else if (pixel_color == 'R') {
    982         /* This is a red pixel. */
    983         *red = _get_bayer_color(desc, buf, x, y, width);
    984         *green = _get_bayer_ave_cross(desc, buf, x, y, width, height);
    985         *blue = _get_bayer_ave_diag(desc, buf, x, y, width, height);
    986     } else {
    987         /* This is a blue pixel. */
    988         *blue = _get_bayer_color(desc, buf, x, y, width);
    989         *green = _get_bayer_ave_cross(desc, buf, x, y, width, height);
    990         *red = _get_bayer_ave_diag(desc, buf, x, y, width, height);
    991     }
    992 }
    993 
    994 /********************************************************************************
    995  * Generic YUV/RGB/BAYER converters
    996  *******************************************************************************/
    997 
    998 /* Generic converter from an RGB/BRG format to a YUV format. */
    999 static void
   1000 RGBToYUV(const RGBDesc* rgb_fmt,
   1001          const YUVDesc* yuv_fmt,
   1002          const void* rgb,
   1003          void* yuv,
   1004          int width,
   1005          int height,
   1006          float r_scale,
   1007          float g_scale,
   1008          float b_scale,
   1009          float exp_comp)
   1010 {
   1011     int y, x;
   1012     const int Y_Inc = yuv_fmt->Y_inc;
   1013     const int UV_inc = yuv_fmt->UV_inc;
   1014     const int Y_next_pair = yuv_fmt->Y_next_pair;
   1015     uint8_t* pY = (uint8_t*)yuv + yuv_fmt->Y_offset;
   1016     for (y = 0; y < height; y++) {
   1017         uint8_t* pU =
   1018             (uint8_t*)yuv + yuv_fmt->u_offset(yuv_fmt, y, width, height);
   1019         uint8_t* pV =
   1020             (uint8_t*)yuv + yuv_fmt->v_offset(yuv_fmt, y, width, height);
   1021         for (x = 0; x < width; x += 2,
   1022                                pY += Y_next_pair, pU += UV_inc, pV += UV_inc) {
   1023             uint8_t r, g, b;
   1024             rgb = rgb_fmt->load_rgb(rgb, &r, &g, &b);
   1025             _change_white_balance_RGB_b(&r, &g, &b, r_scale, g_scale, b_scale);
   1026             _change_exposure_RGB(&r, &g, &b, exp_comp);
   1027             R8G8B8ToYUV(r, g, b, pY, pU, pV);
   1028             rgb = rgb_fmt->load_rgb(rgb, &r, &g, &b);
   1029             _change_white_balance_RGB_b(&r, &g, &b, r_scale, g_scale, b_scale);
   1030             _change_exposure_RGB(&r, &g, &b, exp_comp);
   1031             pY[Y_Inc] = RGB2Y((int)r, (int)g, (int)b);
   1032         }
   1033         /* Aling rgb_ptr to 16 bit */
   1034         if (((uintptr_t)rgb & 1) != 0) rgb = (const uint8_t*)rgb + 1;
   1035     }
   1036 }
   1037 
   1038 /* Generic converter from one RGB/BRG format to another RGB/BRG format. */
   1039 static void
   1040 RGBToRGB(const RGBDesc* src_rgb_fmt,
   1041          const RGBDesc* dst_rgb_fmt,
   1042          const void* src_rgb,
   1043          void* dst_rgb,
   1044          int width,
   1045          int height,
   1046          float r_scale,
   1047          float g_scale,
   1048          float b_scale,
   1049          float exp_comp)
   1050 {
   1051     int x, y;
   1052     for (y = 0; y < height; y++) {
   1053         for (x = 0; x < width; x++) {
   1054             uint8_t r, g, b;
   1055             src_rgb = src_rgb_fmt->load_rgb(src_rgb, &r, &g, &b);
   1056             _change_white_balance_RGB_b(&r, &g, &b, r_scale, g_scale, b_scale);
   1057             _change_exposure_RGB(&r, &g, &b, exp_comp);
   1058             dst_rgb = dst_rgb_fmt->save_rgb(dst_rgb, r, g, b);
   1059         }
   1060         /* Aling rgb pinters to 16 bit */
   1061         if (((uintptr_t)src_rgb & 1) != 0) src_rgb = (uint8_t*)src_rgb + 1;
   1062         if (((uintptr_t)dst_rgb & 1) != 0) dst_rgb = (uint8_t*)dst_rgb + 1;
   1063     }
   1064 }
   1065 
   1066 /* Generic converter from a YUV format to an RGB/BRG format. */
   1067 static void
   1068 YUVToRGB(const YUVDesc* yuv_fmt,
   1069          const RGBDesc* rgb_fmt,
   1070          const void* yuv,
   1071          void* rgb,
   1072          int width,
   1073          int height,
   1074          float r_scale,
   1075          float g_scale,
   1076          float b_scale,
   1077          float exp_comp)
   1078 {
   1079     int y, x;
   1080     const int Y_Inc = yuv_fmt->Y_inc;
   1081     const int UV_inc = yuv_fmt->UV_inc;
   1082     const int Y_next_pair = yuv_fmt->Y_next_pair;
   1083     const uint8_t* pY = (const uint8_t*)yuv + yuv_fmt->Y_offset;
   1084     for (y = 0; y < height; y++) {
   1085         const uint8_t* pU =
   1086             (const uint8_t*)yuv + yuv_fmt->u_offset(yuv_fmt, y, width, height);
   1087         const uint8_t* pV =
   1088             (const uint8_t*)yuv + yuv_fmt->v_offset(yuv_fmt, y, width, height);
   1089         for (x = 0; x < width; x += 2,
   1090                                pY += Y_next_pair, pU += UV_inc, pV += UV_inc) {
   1091             uint8_t r, g, b;
   1092             const uint8_t U = *pU;
   1093             const uint8_t V = *pV;
   1094             YUVToRGBPix(*pY, U, V, &r, &g, &b);
   1095             _change_white_balance_RGB_b(&r, &g, &b, r_scale, g_scale, b_scale);
   1096             _change_exposure_RGB(&r, &g, &b, exp_comp);
   1097             rgb = rgb_fmt->save_rgb(rgb, r, g, b);
   1098             YUVToRGBPix(pY[Y_Inc], U, V, &r, &g, &b);
   1099             _change_white_balance_RGB_b(&r, &g, &b, r_scale, g_scale, b_scale);
   1100             _change_exposure_RGB(&r, &g, &b, exp_comp);
   1101             rgb = rgb_fmt->save_rgb(rgb, r, g, b);
   1102         }
   1103         /* Aling rgb_ptr to 16 bit */
   1104         if (((uintptr_t)rgb & 1) != 0) rgb = (uint8_t*)rgb + 1;
   1105     }
   1106 }
   1107 
   1108 /* Generic converter from one YUV format to another YUV format. */
   1109 static void
   1110 YUVToYUV(const YUVDesc* src_fmt,
   1111          const YUVDesc* dst_fmt,
   1112          const void* src,
   1113          void* dst,
   1114          int width,
   1115          int height,
   1116          float r_scale,
   1117          float g_scale,
   1118          float b_scale,
   1119          float exp_comp)
   1120 {
   1121     int y, x;
   1122     const int Y_Inc_src = src_fmt->Y_inc;
   1123     const int UV_inc_src = src_fmt->UV_inc;
   1124     const int Y_next_pair_src = src_fmt->Y_next_pair;
   1125     const int Y_Inc_dst = dst_fmt->Y_inc;
   1126     const int UV_inc_dst = dst_fmt->UV_inc;
   1127     const int Y_next_pair_dst = dst_fmt->Y_next_pair;
   1128     const uint8_t* pYsrc = (const uint8_t*)src + src_fmt->Y_offset;
   1129     uint8_t* pYdst = (uint8_t*)dst + dst_fmt->Y_offset;
   1130     for (y = 0; y < height; y++) {
   1131         const uint8_t* pUsrc =
   1132             (const uint8_t*)src + src_fmt->u_offset(src_fmt, y, width, height);
   1133         const uint8_t* pVsrc =
   1134             (const uint8_t*)src + src_fmt->v_offset(src_fmt, y, width, height);
   1135         uint8_t* pUdst =
   1136             (uint8_t*)dst + dst_fmt->u_offset(dst_fmt, y, width, height);
   1137         uint8_t* pVdst =
   1138             (uint8_t*)dst + dst_fmt->v_offset(dst_fmt, y, width, height);
   1139         for (x = 0; x < width; x += 2, pYsrc += Y_next_pair_src,
   1140                                        pUsrc += UV_inc_src,
   1141                                        pVsrc += UV_inc_src,
   1142                                        pYdst += Y_next_pair_dst,
   1143                                        pUdst += UV_inc_dst,
   1144                                        pVdst += UV_inc_dst) {
   1145             *pYdst = *pYsrc; *pUdst = *pUsrc; *pVdst = *pVsrc;
   1146             _change_white_balance_YUV(pYdst, pUdst, pVdst, r_scale, g_scale, b_scale);
   1147             *pYdst = _change_exposure(*pYdst, exp_comp);
   1148             pYdst[Y_Inc_dst] = _change_exposure(pYsrc[Y_Inc_src], exp_comp);
   1149         }
   1150     }
   1151 }
   1152 
   1153 /* Generic converter from a BAYER format to an RGB/BRG format. */
   1154 static void
   1155 BAYERToRGB(const BayerDesc* bayer_fmt,
   1156            const RGBDesc* rgb_fmt,
   1157            const void* bayer,
   1158            void* rgb,
   1159            int width,
   1160            int height,
   1161            float r_scale,
   1162            float g_scale,
   1163            float b_scale,
   1164            float exp_comp)
   1165 {
   1166     int y, x;
   1167     for (y = 0; y < height; y++) {
   1168         for (x = 0; x < width; x++) {
   1169             int r, g, b;
   1170             _get_bayerRGB(bayer_fmt, bayer, x, y, width, height, &r, &g, &b);
   1171             if (bayer_fmt->mask == kBayer10) {
   1172                 r >>= 2; g >>= 2; b >>= 2;
   1173             } else if (bayer_fmt->mask == kBayer12) {
   1174                 r >>= 4; g >>= 4; b >>= 4;
   1175             }
   1176             _change_white_balance_RGB(&r, &g, &b, r_scale, g_scale, b_scale);
   1177             _change_exposure_RGB_i(&r, &g, &b, exp_comp);
   1178             rgb = rgb_fmt->save_rgb(rgb, r, g, b);
   1179         }
   1180         /* Aling rgb_ptr to 16 bit */
   1181         if (((uintptr_t)rgb & 1) != 0) rgb = (uint8_t*)rgb + 1;
   1182     }
   1183 }
   1184 
   1185 /* Generic converter from a BAYER format to a YUV format. */
   1186 static void
   1187 BAYERToYUV(const BayerDesc* bayer_fmt,
   1188            const YUVDesc* yuv_fmt,
   1189            const void* bayer,
   1190            void* yuv,
   1191            int width,
   1192            int height,
   1193            float r_scale,
   1194            float g_scale,
   1195            float b_scale,
   1196            float exp_comp)
   1197 {
   1198     int y, x;
   1199     const int Y_Inc = yuv_fmt->Y_inc;
   1200     const int UV_inc = yuv_fmt->UV_inc;
   1201     const int Y_next_pair = yuv_fmt->Y_next_pair;
   1202     uint8_t* pY = (uint8_t*)yuv + yuv_fmt->Y_offset;
   1203     for (y = 0; y < height; y++) {
   1204         uint8_t* pU =
   1205             (uint8_t*)yuv + yuv_fmt->u_offset(yuv_fmt, y, width, height);
   1206         uint8_t* pV =
   1207             (uint8_t*)yuv + yuv_fmt->v_offset(yuv_fmt, y, width, height);
   1208         for (x = 0; x < width; x += 2,
   1209                                pY += Y_next_pair, pU += UV_inc, pV += UV_inc) {
   1210             int r, g, b;
   1211             _get_bayerRGB(bayer_fmt, bayer, x, y, width, height, &r, &g, &b);
   1212             _change_white_balance_RGB(&r, &g, &b, r_scale, g_scale, b_scale);
   1213             _change_exposure_RGB_i(&r, &g, &b, exp_comp);
   1214             R8G8B8ToYUV(r, g, b, pY, pU, pV);
   1215             _get_bayerRGB(bayer_fmt, bayer, x + 1, y, width, height, &r, &g, &b);
   1216             _change_white_balance_RGB(&r, &g, &b, r_scale, g_scale, b_scale);
   1217             _change_exposure_RGB_i(&r, &g, &b, exp_comp);
   1218             pY[Y_Inc] = RGB2Y(r, g, b);
   1219         }
   1220     }
   1221 }
   1222 
   1223 /********************************************************************************
   1224  * RGB format descriptors.
   1225  */
   1226 
   1227 /* Describes RGB32 format. */
   1228 static const RGBDesc _RGB32 =
   1229 {
   1230     .load_rgb   = _load_RGB32,
   1231     .save_rgb   = _save_RGB32,
   1232     .rgb_inc    = 4
   1233 };
   1234 
   1235 /* Describes BRG32 format. */
   1236 static const RGBDesc _BRG32 =
   1237 {
   1238     .load_rgb   = _load_BRG32,
   1239     .save_rgb   = _save_BRG32,
   1240     .rgb_inc    = 4
   1241 };
   1242 
   1243 /* Describes RGB24 format. */
   1244 static const RGBDesc _RGB24 =
   1245 {
   1246     .load_rgb   = _load_RGB24,
   1247     .save_rgb   = _save_RGB24,
   1248     .rgb_inc    = 3
   1249 };
   1250 
   1251 /* Describes BRG24 format. */
   1252 static const RGBDesc _BRG24 =
   1253 {
   1254     .load_rgb   = _load_BRG24,
   1255     .save_rgb   = _save_BRG24,
   1256     .rgb_inc    = 3
   1257 };
   1258 
   1259 /* Describes RGB16 format. */
   1260 static const RGBDesc _RGB16 =
   1261 {
   1262     .load_rgb   = _load_RGB16,
   1263     .save_rgb   = _save_RGB16,
   1264     .rgb_inc    = 2
   1265 };
   1266 
   1267 /* Describes BRG16 format. */
   1268 static const RGBDesc _BRG16 =
   1269 {
   1270     .load_rgb   = _load_BRG16,
   1271     .save_rgb   = _save_BRG16,
   1272     .rgb_inc    = 2
   1273 };
   1274 
   1275 /********************************************************************************
   1276  * YUV 4:2:2 format descriptors.
   1277  */
   1278 
   1279 /* YUYV: 4:2:2, YUV are interleaved. */
   1280 static const YUVDesc _YUYV =
   1281 {
   1282     .Y_offset       = 0,
   1283     .Y_inc          = 2,
   1284     .Y_next_pair    = 4,
   1285     .UV_inc         = 4,
   1286     .U_offset       = 1,
   1287     .V_offset       = 3,
   1288     .u_offset       = &_UOffIntrlYUV,
   1289     .v_offset       = &_VOffIntrlYUV
   1290 };
   1291 
   1292 /* UYVY: 4:2:2, YUV are interleaved. */
   1293 static const YUVDesc _UYVY =
   1294 {
   1295     .Y_offset       = 1,
   1296     .Y_inc          = 2,
   1297     .Y_next_pair    = 4,
   1298     .UV_inc         = 4,
   1299     .U_offset       = 0,
   1300     .V_offset       = 2,
   1301     .u_offset       = &_UOffIntrlYUV,
   1302     .v_offset       = &_VOffIntrlYUV
   1303 };
   1304 
   1305 /* YVYU: 4:2:2, YUV are interleaved. */
   1306 static const YUVDesc _YVYU =
   1307 {
   1308     .Y_offset       = 0,
   1309     .Y_inc          = 2,
   1310     .Y_next_pair    = 4,
   1311     .UV_inc         = 4,
   1312     .U_offset       = 3,
   1313     .V_offset       = 1,
   1314     .u_offset       = &_UOffIntrlYUV,
   1315     .v_offset       = &_VOffIntrlYUV
   1316 };
   1317 
   1318 /* VYUY: 4:2:2, YUV are interleaved. */
   1319 static const YUVDesc _VYUY =
   1320 {
   1321     .Y_offset       = 1,
   1322     .Y_inc          = 2,
   1323     .Y_next_pair    = 4,
   1324     .UV_inc         = 4,
   1325     .U_offset       = 2,
   1326     .V_offset       = 0,
   1327     .u_offset       = &_UOffIntrlYUV,
   1328     .v_offset       = &_VOffIntrlYUV
   1329 };
   1330 
   1331 /* YYUV (also YUY2, YUNV, V422) : 4:2:2, YUV are interleaved. */
   1332 static const YUVDesc _YYUV =
   1333 {
   1334     .Y_offset       = 0,
   1335     .Y_inc          = 1,
   1336     .Y_next_pair    = 4,
   1337     .UV_inc         = 4,
   1338     .U_offset       = 2,
   1339     .V_offset       = 3,
   1340     .u_offset       = &_UOffIntrlYUV,
   1341     .v_offset       = &_VOffIntrlYUV
   1342 };
   1343 
   1344 /* YYVU: 4:2:2, YUV are interleaved. */
   1345 static const YUVDesc _YYVU =
   1346 {
   1347     .Y_offset       = 0,
   1348     .Y_inc          = 1,
   1349     .Y_next_pair    = 4,
   1350     .UV_inc         = 4,
   1351     .U_offset       = 3,
   1352     .V_offset       = 2,
   1353     .u_offset       = &_UOffIntrlYUV,
   1354     .v_offset       = &_VOffIntrlYUV
   1355 };
   1356 
   1357 /********************************************************************************
   1358  * YUV 4:2:0 descriptors.
   1359  */
   1360 
   1361 /* YV12: 4:2:0, YUV are fully separated, U pane follows V pane */
   1362 static const YUVDesc _YV12 =
   1363 {
   1364     .Y_offset       = 0,
   1365     .Y_inc          = 1,
   1366     .Y_next_pair    = 2,
   1367     .UV_inc         = 1,
   1368     .U_offset       = 0,
   1369     .V_offset       = 1,
   1370     .u_offset       = &_UOffSepYUV,
   1371     .v_offset       = &_VOffSepYUV
   1372 };
   1373 
   1374 /* YU12: 4:2:0, YUV are fully separated, V pane follows U pane */
   1375 static const YUVDesc _YU12 =
   1376 {
   1377     .Y_offset       = 0,
   1378     .Y_inc          = 1,
   1379     .Y_next_pair    = 2,
   1380     .UV_inc         = 1,
   1381     .U_offset       = 1,
   1382     .V_offset       = 0,
   1383     .u_offset       = &_UOffSepYUV,
   1384     .v_offset       = &_VOffSepYUV
   1385 };
   1386 
   1387 /* NV12: 4:2:0, UV are interleaved, V follows U in UV pane */
   1388 static const YUVDesc _NV12 =
   1389 {
   1390     .Y_offset       = 0,
   1391     .Y_inc          = 1,
   1392     .Y_next_pair    = 2,
   1393     .UV_inc         = 2,
   1394     .U_offset       = 0,
   1395     .V_offset       = 1,
   1396     .u_offset       = &_UOffIntrlUV,
   1397     .v_offset       = &_VOffIntrlUV
   1398 };
   1399 
   1400 /* NV21: 4:2:0, UV are interleaved, U follows V in UV pane */
   1401 static const YUVDesc _NV21 =
   1402 {
   1403     .Y_offset       = 0,
   1404     .Y_inc          = 1,
   1405     .Y_next_pair    = 2,
   1406     .UV_inc         = 2,
   1407     .U_offset       = 1,
   1408     .V_offset       = 0,
   1409     .u_offset       = &_UOffIntrlUV,
   1410     .v_offset       = &_VOffIntrlUV
   1411 };
   1412 
   1413 /********************************************************************************
   1414  * RGB bayer format descriptors.
   1415  */
   1416 
   1417 /* Descriptor for a 8-bit GBGB / RGRG format. */
   1418 static const BayerDesc _GB8 =
   1419 {
   1420     .mask           = kBayer8,
   1421     .color_order    = "GBRG"
   1422 };
   1423 
   1424 /* Descriptor for a 8-bit GRGR / BGBG format. */
   1425 static const BayerDesc _GR8 =
   1426 {
   1427     .mask           = kBayer8,
   1428     .color_order    = "GRBG"
   1429 };
   1430 
   1431 /* Descriptor for a 8-bit BGBG / GRGR format. */
   1432 static const BayerDesc _BG8 =
   1433 {
   1434     .mask           = kBayer8,
   1435     .color_order    = "BGGR"
   1436 };
   1437 
   1438 /* Descriptor for a 8-bit RGRG / GBGB format. */
   1439 static const BayerDesc _RG8 =
   1440 {
   1441     .mask           = kBayer8,
   1442     .color_order    = "RGGB"
   1443 };
   1444 
   1445 /* Descriptor for a 10-bit GBGB / RGRG format. */
   1446 static const BayerDesc _GB10 =
   1447 {
   1448     .mask           = kBayer10,
   1449     .color_order    = "GBRG"
   1450 };
   1451 
   1452 /* Descriptor for a 10-bit GRGR / BGBG format. */
   1453 static const BayerDesc _GR10 =
   1454 {
   1455     .mask           = kBayer10,
   1456     .color_order    = "GRBG"
   1457 };
   1458 
   1459 /* Descriptor for a 10-bit BGBG / GRGR format. */
   1460 static const BayerDesc _BG10 =
   1461 {
   1462     .mask           = kBayer10,
   1463     .color_order    = "BGGR"
   1464 };
   1465 
   1466 /* Descriptor for a 10-bit RGRG / GBGB format. */
   1467 static const BayerDesc _RG10 =
   1468 {
   1469     .mask           = kBayer10,
   1470     .color_order    = "RGGB"
   1471 };
   1472 
   1473 /* Descriptor for a 12-bit GBGB / RGRG format. */
   1474 static const BayerDesc _GB12 =
   1475 {
   1476     .mask           = kBayer12,
   1477     .color_order    = "GBRG"
   1478 };
   1479 
   1480 /* Descriptor for a 12-bit GRGR / BGBG format. */
   1481 static const BayerDesc _GR12 =
   1482 {
   1483     .mask           = kBayer12,
   1484     .color_order    = "GRBG"
   1485 };
   1486 
   1487 /* Descriptor for a 12-bit BGBG / GRGR format. */
   1488 static const BayerDesc _BG12 =
   1489 {
   1490     .mask           = kBayer12,
   1491     .color_order    = "BGGR"
   1492 };
   1493 
   1494 /* Descriptor for a 12-bit RGRG / GBGB format. */
   1495 static const BayerDesc _RG12 =
   1496 {
   1497     .mask           = kBayer12,
   1498     .color_order    = "RGGB"
   1499 };
   1500 
   1501 
   1502 /********************************************************************************
   1503  * List of descriptors for supported formats.
   1504  *******************************************************************************/
   1505 
   1506 /* Enumerates pixel formats supported by converters. */
   1507 typedef enum PIXFormatSel {
   1508     /* Pixel format is RGB/BGR */
   1509     PIX_FMT_RGB,
   1510     /* Pixel format is YUV */
   1511     PIX_FMT_YUV,
   1512     /* Pixel format is BAYER */
   1513     PIX_FMT_BAYER
   1514 } PIXFormatSel;
   1515 
   1516 /* Formats entry in the list of descriptors for supported formats. */
   1517 typedef struct PIXFormat {
   1518     /* "FOURCC" (V4L2_PIX_FMT_XXX) format type. */
   1519     uint32_t        fourcc_type;
   1520     /* RGB/YUV/BAYER format selector */
   1521     PIXFormatSel    format_sel;
   1522     union {
   1523         /* References RGB format descriptor for that format. */
   1524         const RGBDesc*      rgb_desc;
   1525         /* References YUV format descriptor for that format. */
   1526         const YUVDesc*      yuv_desc;
   1527         /* References BAYER format descriptor for that format. */
   1528         const BayerDesc*    bayer_desc;
   1529     } desc;
   1530 } PIXFormat;
   1531 
   1532 /* Array of supported pixel format descriptors. */
   1533 static const PIXFormat _PIXFormats[] = {
   1534     /* RGB/BRG formats. */
   1535     { V4L2_PIX_FMT_RGB32,   PIX_FMT_RGB,    .desc.rgb_desc = &_RGB32  },
   1536     { V4L2_PIX_FMT_BGR32,   PIX_FMT_RGB,    .desc.rgb_desc = &_BRG32  },
   1537     { V4L2_PIX_FMT_RGB565,  PIX_FMT_RGB,    .desc.rgb_desc = &_RGB16  },
   1538     { V4L2_PIX_FMT_RGB24,   PIX_FMT_RGB,    .desc.rgb_desc = &_RGB24  },
   1539     { V4L2_PIX_FMT_BGR24,   PIX_FMT_RGB,    .desc.rgb_desc = &_BRG24  },
   1540 
   1541     /* YUV 4:2:0 formats. */
   1542     { V4L2_PIX_FMT_YVU420,  PIX_FMT_YUV,    .desc.yuv_desc = &_YV12   },
   1543     { V4L2_PIX_FMT_YUV420,  PIX_FMT_YUV,    .desc.yuv_desc = &_YU12   },
   1544     { V4L2_PIX_FMT_NV12,    PIX_FMT_YUV,    .desc.yuv_desc = &_NV12   },
   1545     { V4L2_PIX_FMT_NV21,    PIX_FMT_YUV,    .desc.yuv_desc = &_NV21   },
   1546 
   1547     /* YUV 4:2:2 formats. */
   1548     { V4L2_PIX_FMT_YUYV,    PIX_FMT_YUV,    .desc.yuv_desc = &_YUYV   },
   1549     { V4L2_PIX_FMT_YYUV,    PIX_FMT_YUV,    .desc.yuv_desc = &_YYUV   },
   1550     { V4L2_PIX_FMT_YVYU,    PIX_FMT_YUV,    .desc.yuv_desc = &_YVYU   },
   1551     { V4L2_PIX_FMT_UYVY,    PIX_FMT_YUV,    .desc.yuv_desc = &_UYVY   },
   1552     { V4L2_PIX_FMT_VYUY,    PIX_FMT_YUV,    .desc.yuv_desc = &_VYUY   },
   1553     { V4L2_PIX_FMT_YVYU,    PIX_FMT_YUV,    .desc.yuv_desc = &_YVYU   },
   1554     { V4L2_PIX_FMT_VYUY,    PIX_FMT_YUV,    .desc.yuv_desc = &_VYUY   },
   1555     { V4L2_PIX_FMT_YYVU,    PIX_FMT_YUV,    .desc.yuv_desc = &_YYVU   },
   1556     { V4L2_PIX_FMT_YUY2,    PIX_FMT_YUV,    .desc.yuv_desc = &_YUYV   },
   1557     { V4L2_PIX_FMT_YUNV,    PIX_FMT_YUV,    .desc.yuv_desc = &_YUYV   },
   1558     { V4L2_PIX_FMT_V422,    PIX_FMT_YUV,    .desc.yuv_desc = &_YUYV   },
   1559 
   1560     /* BAYER formats. */
   1561     { V4L2_PIX_FMT_SBGGR8,  PIX_FMT_BAYER,  .desc.bayer_desc = &_BG8  },
   1562     { V4L2_PIX_FMT_SGBRG8,  PIX_FMT_BAYER,  .desc.bayer_desc = &_GB8  },
   1563     { V4L2_PIX_FMT_SGRBG8,  PIX_FMT_BAYER,  .desc.bayer_desc = &_GR8  },
   1564     { V4L2_PIX_FMT_SRGGB8,  PIX_FMT_BAYER,  .desc.bayer_desc = &_RG8  },
   1565     { V4L2_PIX_FMT_SBGGR10, PIX_FMT_BAYER,  .desc.bayer_desc = &_BG10 },
   1566     { V4L2_PIX_FMT_SGBRG10, PIX_FMT_BAYER,  .desc.bayer_desc = &_GB10 },
   1567     { V4L2_PIX_FMT_SGRBG10, PIX_FMT_BAYER,  .desc.bayer_desc = &_GR10 },
   1568     { V4L2_PIX_FMT_SRGGB10, PIX_FMT_BAYER,  .desc.bayer_desc = &_RG10 },
   1569     { V4L2_PIX_FMT_SBGGR12, PIX_FMT_BAYER,  .desc.bayer_desc = &_BG12 },
   1570     { V4L2_PIX_FMT_SGBRG12, PIX_FMT_BAYER,  .desc.bayer_desc = &_GB12 },
   1571     { V4L2_PIX_FMT_SGRBG12, PIX_FMT_BAYER,  .desc.bayer_desc = &_GR12 },
   1572     { V4L2_PIX_FMT_SRGGB12, PIX_FMT_BAYER,  .desc.bayer_desc = &_RG12 },
   1573 };
   1574 static const int _PIXFormats_num = sizeof(_PIXFormats) / sizeof(*_PIXFormats);
   1575 
   1576 /* Get an entry in the array of supported pixel format descriptors.
   1577  * Param:
   1578  *  pixel_format - "fourcc" pixel format to lookup an entry for.
   1579  * Return"
   1580  *  Pointer to the found entry, or NULL if no entry exists for the given pixel
   1581  *  format.
   1582  */
   1583 static const PIXFormat*
   1584 _get_pixel_format_descriptor(uint32_t pixel_format)
   1585 {
   1586     int f;
   1587     for (f = 0; f < _PIXFormats_num; f++) {
   1588         if (_PIXFormats[f].fourcc_type == pixel_format) {
   1589             return &_PIXFormats[f];
   1590         }
   1591     }
   1592     W("%s: Pixel format %.4s is unknown",
   1593       __FUNCTION__, (const char*)&pixel_format);
   1594     return NULL;
   1595 }
   1596 
   1597 /********************************************************************************
   1598  * Public API
   1599  *******************************************************************************/
   1600 
   1601 int
   1602 has_converter(uint32_t from, uint32_t to)
   1603 {
   1604     if (from == to) {
   1605         /* Same format: converter esists. */
   1606         return 1;
   1607     }
   1608     return _get_pixel_format_descriptor(from) != NULL &&
   1609            _get_pixel_format_descriptor(to) != NULL;
   1610 }
   1611 
   1612 int
   1613 convert_frame(const void* frame,
   1614               uint32_t pixel_format,
   1615               size_t framebuffer_size,
   1616               int width,
   1617               int height,
   1618               ClientFrameBuffer* framebuffers,
   1619               int fbs_num,
   1620               float r_scale,
   1621               float g_scale,
   1622               float b_scale,
   1623               float exp_comp)
   1624 {
   1625     int n;
   1626     const PIXFormat* src_desc = _get_pixel_format_descriptor(pixel_format);
   1627     if (src_desc == NULL) {
   1628         E("%s: Source pixel format %.4s is unknown",
   1629           __FUNCTION__, (const char*)&pixel_format);
   1630         return -1;
   1631     }
   1632 
   1633     for (n = 0; n < fbs_num; n++) {
   1634         /* Note that we need to apply white balance, exposure compensation, etc.
   1635          * when we transfer the captured frame to the user framebuffer. So, even
   1636          * if source and destination formats are the same, we will have to go
   1637          * thrugh the converters to apply these things. */
   1638         const PIXFormat* dst_desc =
   1639             _get_pixel_format_descriptor(framebuffers[n].pixel_format);
   1640         if (dst_desc == NULL) {
   1641             E("%s: Destination pixel format %.4s is unknown",
   1642               __FUNCTION__, (const char*)&framebuffers[n].pixel_format);
   1643             return -1;
   1644         }
   1645         switch (src_desc->format_sel) {
   1646             case PIX_FMT_RGB:
   1647                 if (dst_desc->format_sel == PIX_FMT_RGB) {
   1648                     RGBToRGB(src_desc->desc.rgb_desc, dst_desc->desc.rgb_desc,
   1649                              frame, framebuffers[n].framebuffer, width, height,
   1650                              r_scale, g_scale, b_scale, exp_comp);
   1651                 } else if (dst_desc->format_sel == PIX_FMT_YUV) {
   1652                     RGBToYUV(src_desc->desc.rgb_desc, dst_desc->desc.yuv_desc,
   1653                              frame, framebuffers[n].framebuffer, width, height,
   1654                              r_scale, g_scale, b_scale, exp_comp);
   1655                 } else {
   1656                     E("%s: Unexpected destination pixel format %d",
   1657                       __FUNCTION__, dst_desc->format_sel);
   1658                     return -1;
   1659                 }
   1660                 break;
   1661             case PIX_FMT_YUV:
   1662                 if (dst_desc->format_sel == PIX_FMT_RGB) {
   1663                     YUVToRGB(src_desc->desc.yuv_desc, dst_desc->desc.rgb_desc,
   1664                              frame, framebuffers[n].framebuffer, width, height,
   1665                              r_scale, g_scale, b_scale, exp_comp);
   1666                 } else if (dst_desc->format_sel == PIX_FMT_YUV) {
   1667                     YUVToYUV(src_desc->desc.yuv_desc, dst_desc->desc.yuv_desc,
   1668                              frame, framebuffers[n].framebuffer, width, height,
   1669                              r_scale, g_scale, b_scale, exp_comp);
   1670                 } else {
   1671                     E("%s: Unexpected destination pixel format %d",
   1672                       __FUNCTION__, dst_desc->format_sel);
   1673                     return -1;
   1674                 }
   1675                 break;
   1676             case PIX_FMT_BAYER:
   1677                 if (dst_desc->format_sel == PIX_FMT_RGB) {
   1678                     BAYERToRGB(src_desc->desc.bayer_desc, dst_desc->desc.rgb_desc,
   1679                               frame, framebuffers[n].framebuffer, width, height,
   1680                               r_scale, g_scale, b_scale, exp_comp);
   1681                 } else if (dst_desc->format_sel == PIX_FMT_YUV) {
   1682                     BAYERToYUV(src_desc->desc.bayer_desc, dst_desc->desc.yuv_desc,
   1683                                frame, framebuffers[n].framebuffer, width, height,
   1684                                r_scale, g_scale, b_scale, exp_comp);
   1685                 } else {
   1686                     E("%s: Unexpected destination pixel format %d",
   1687                       __FUNCTION__, dst_desc->format_sel);
   1688                     return -1;
   1689                 }
   1690                 break;
   1691             default:
   1692                 E("%s: Unexpected source pixel format %d",
   1693                   __FUNCTION__, dst_desc->format_sel);
   1694                 return -1;
   1695         }
   1696     }
   1697 
   1698     return 0;
   1699 }
   1700