• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
clamp(int x)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
R8G8B8ToYUV(uint8_t r,uint8_t g,uint8_t b,uint8_t * y,uint8_t * u,uint8_t * v)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
RGB565ToYUV(uint16_t rgb,uint8_t * y,uint8_t * u,uint8_t * v)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
RGB32ToYUV(uint32_t rgb,uint8_t * y,uint8_t * u,uint8_t * v)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
YUVToRGB565(int y,int u,int v)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
YUVToRGB32(int y,int u,int v)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
YUVToRGBPix(int y,int u,int v,uint8_t * r,uint8_t * g,uint8_t * b)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
_change_exposure(uint8_t inputY,float exp_comp)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
_change_exposure_RGB(uint8_t * r,uint8_t * g,uint8_t * b,float exp_comp)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
_change_exposure_RGB_i(int * r,int * g,int * b,float exp_comp)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
_change_white_balance_YUV(uint8_t * y,uint8_t * u,uint8_t * v,float r_scale,float g_scale,float b_scale)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
_change_white_balance_RGB(int * r,int * g,int * b,float r_scale,float g_scale,float b_scale)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
_change_white_balance_RGB_b(uint8_t * r,uint8_t * g,uint8_t * b,float r_scale,float g_scale,float b_scale)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*
_load_RGB32(const void * rgb,uint8_t * r,uint8_t * g,uint8_t * b)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*
_save_RGB32(void * rgb,uint8_t r,uint8_t g,uint8_t b)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*
_load_BRG32(const void * rgb,uint8_t * r,uint8_t * g,uint8_t * b)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*
_save_BRG32(void * rgb,uint8_t r,uint8_t g,uint8_t b)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*
_load_RGB24(const void * rgb,uint8_t * r,uint8_t * g,uint8_t * b)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*
_save_RGB24(void * rgb,uint8_t r,uint8_t g,uint8_t b)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*
_load_BRG24(const void * rgb,uint8_t * r,uint8_t * g,uint8_t * b)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*
_save_BRG24(void * rgb,uint8_t r,uint8_t g,uint8_t b)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*
_load_RGB16(const void * rgb,uint8_t * r,uint8_t * g,uint8_t * b)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*
_save_RGB16(void * rgb,uint8_t r,uint8_t g,uint8_t b)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*
_load_BRG16(const void * rgb,uint8_t * r,uint8_t * g,uint8_t * b)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*
_save_BRG16(void * rgb,uint8_t r,uint8_t g,uint8_t b)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
_UOffIntrlYUV(const YUVDesc * desc,int line,int width,int height)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
_VOffIntrlYUV(const YUVDesc * desc,int line,int width,int height)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
_UOffIntrlUV(const YUVDesc * desc,int line,int width,int height)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
_VOffIntrlUV(const YUVDesc * desc,int line,int width,int height)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
_UOffSepYUV(const YUVDesc * desc,int line,int width,int height)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
_VOffSepYUV(const YUVDesc * desc,int line,int width,int height)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
_get_bayer_color(const BayerDesc * desc,const void * buf,int x,int y,int width)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
_get_bayer_ave_hor(const BayerDesc * desc,const void * buf,int x,int y,int width,int height)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
_get_bayer_ave_vert(const BayerDesc * desc,const void * buf,int x,int y,int width,int height)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
_get_bayer_ave_cross(const BayerDesc * desc,const void * buf,int x,int y,int width,int height)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
_get_bayer_ave_diag(const BayerDesc * desc,const void * buf,int x,int y,int width,int height)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
_get_bayer_color_sel(const BayerDesc * desc,int x,int y)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
_get_bayerRGB(const BayerDesc * desc,const void * buf,int x,int y,int width,int height,int * red,int * green,int * blue)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
RGBToYUV(const RGBDesc * rgb_fmt,const YUVDesc * yuv_fmt,const void * rgb,void * yuv,int width,int height,float r_scale,float g_scale,float b_scale,float exp_comp)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
RGBToRGB(const RGBDesc * src_rgb_fmt,const RGBDesc * dst_rgb_fmt,const void * src_rgb,void * dst_rgb,int width,int height,float r_scale,float g_scale,float b_scale,float exp_comp)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
YUVToRGB(const YUVDesc * yuv_fmt,const RGBDesc * rgb_fmt,const void * yuv,void * rgb,int width,int height,float r_scale,float g_scale,float b_scale,float exp_comp)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
YUVToYUV(const YUVDesc * src_fmt,const YUVDesc * dst_fmt,const void * src,void * dst,int width,int height,float r_scale,float g_scale,float b_scale,float exp_comp)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
BAYERToRGB(const BayerDesc * bayer_fmt,const RGBDesc * rgb_fmt,const void * bayer,void * rgb,int width,int height,float r_scale,float g_scale,float b_scale,float exp_comp)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
BAYERToYUV(const BayerDesc * bayer_fmt,const YUVDesc * yuv_fmt,const void * bayer,void * yuv,int width,int height,float r_scale,float g_scale,float b_scale,float exp_comp)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*
_get_pixel_format_descriptor(uint32_t pixel_format)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
has_converter(uint32_t from,uint32_t to)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
convert_frame(const void * frame,uint32_t pixel_format,size_t framebuffer_size,int width,int height,ClientFrameBuffer * framebuffers,int fbs_num,float r_scale,float g_scale,float b_scale,float exp_comp)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