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