aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2011-09-20 13:32:10 -0700
committerVladimir Chtchetkine <vchtchetkine@google.com>2011-09-21 06:11:03 -0700
commit26fafb586bdb4f0d82d13bf4bde882d3f51fc939 (patch)
tree1bdf68b3f4e31126df63fe414a3a1ede9862f94a /android
parentb8dcaffaf7dcb0c795d2776abf3bb75196f8527c (diff)
downloadexternal_qemu-26fafb586bdb4f0d82d13bf4bde882d3f51fc939.zip
external_qemu-26fafb586bdb4f0d82d13bf4bde882d3f51fc939.tar.gz
external_qemu-26fafb586bdb4f0d82d13bf4bde882d3f51fc939.tar.bz2
Implements converters for BAYER pixel format
Change-Id: I68abaa8b89e2b46dc57bff1d7dbd6d9fda213dc8
Diffstat (limited to 'android')
-rwxr-xr-xandroid/camera/camera-common.h34
-rwxr-xr-xandroid/camera/camera-format-converters.c568
2 files changed, 559 insertions, 43 deletions
diff --git a/android/camera/camera-common.h b/android/camera/camera-common.h
index a3fdd5f..126b3ed 100755
--- a/android/camera/camera-common.h
+++ b/android/camera/camera-common.h
@@ -58,7 +58,39 @@
#ifndef V4L2_PIX_FMT_YYVU
#define V4L2_PIX_FMT_YYVU v4l2_fourcc('Y', 'Y', 'V', 'U')
#endif /* V4L2_PIX_FMT_YYVU */
-
+#ifndef V4L2_PIX_FMT_SGBRG8
+#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G')
+#endif /* V4L2_PIX_FMT_SGBRG8 */
+#ifndef V4L2_PIX_FMT_SGRBG8
+#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G')
+#endif /* V4L2_PIX_FMT_SGRBG8 */
+#ifndef V4L2_PIX_FMT_SRGGB8
+#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B')
+#endif /* V4L2_PIX_FMT_SRGGB8 */
+#ifndef V4L2_PIX_FMT_SBGGR10
+#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '\0')
+#endif /* V4L2_PIX_FMT_SBGGR10 */
+#ifndef V4L2_PIX_FMT_SGBRG10
+#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '\0')
+#endif /* V4L2_PIX_FMT_SGBRG10 */
+#ifndef V4L2_PIX_FMT_SGRBG10
+#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '\0')
+#endif /* V4L2_PIX_FMT_SGRBG10 */
+#ifndef V4L2_PIX_FMT_SRGGB10
+#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '\0')
+#endif /* V4L2_PIX_FMT_SRGGB10 */
+#ifndef V4L2_PIX_FMT_SBGGR12
+#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2')
+#endif /* V4L2_PIX_FMT_SBGGR12 */
+#ifndef V4L2_PIX_FMT_SGBRG12
+#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2')
+#endif /* V4L2_PIX_FMT_SGBRG12 */
+#ifndef V4L2_PIX_FMT_SGRBG12
+#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2')
+#endif /* V4L2_PIX_FMT_SGRBG12 */
+#ifndef V4L2_PIX_FMT_SRGGB12
+#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2')
+#endif /* V4L2_PIX_FMT_SRGGB12 */
/* Describes framebuffer, used by the client of camera capturing API.
* This descritptor is used in camera_device_read_frame call.
diff --git a/android/camera/camera-format-converters.c b/android/camera/camera-format-converters.c
index 172f46f..4dcb424 100755
--- a/android/camera/camera-format-converters.c
+++ b/android/camera/camera-format-converters.c
@@ -110,6 +110,17 @@ static const uint32_t kBlue8 = 0x000000ff;
#define RGB32(r, g, b) (uint32_t)(((((uint32_t)(r) << 8) | (g)) << 8) | (b))
#endif // !HOST_WORDS_BIGENDIAN
+/*
+ * BAYER bitmasks
+ */
+
+/* Bitmask for 8-bits BAYER pixel. */
+#define kBayer8 0xff
+/* Bitmask for 10-bits BAYER pixel. */
+#define kBayer10 0x3ff
+/* Bitmask for 12-bits BAYER pixel. */
+#define kBayer12 0xfff
+
/* An union that simplifies breaking 32 bit RGB into separate R, G, and B colors.
*/
typedef union RGB32_t {
@@ -306,6 +317,13 @@ YUVToRGBPix(int y, int u, int v, uint8_t* r, uint8_t* g, uint8_t* b)
* So, all these patterns can be coded in a YUV format descriptor, so there can
* just one generic way of walking YUV frame.
*
+ * BAYER format.
+ * We don't use BAYER inside the guest system, so there is no need to have a
+ * converter to the BAYER formats, only from it. The color approximation used in
+ * the BAYER format converters implemented here simply averages corresponded
+ * color values found in pixels sorrounding the one for which RGB colors are
+ * calculated.
+ *
* Performance considerations:
* Since converters implemented here are intended to work as part of the camera
* emulation, making the code super performant is not a priority at all. There
@@ -315,6 +333,7 @@ YUVToRGBPix(int y, int u, int v, uint8_t* r, uint8_t* g, uint8_t* b)
typedef struct RGBDesc RGBDesc;
typedef struct YUVDesc YUVDesc;
+typedef struct BayerDesc BayerDesc;
/* Prototype for a routine that loads RGB colors from an RGB/BRG stream.
* Param:
@@ -407,6 +426,23 @@ struct YUVDesc {
v_offset_func v_offset;
};
+/* Bayer format descriptor. */
+struct BayerDesc {
+ /* Defines color ordering in the BAYER framebuffer. Can be one of the four:
+ * - "GBRG" for GBGBGB / RGRGRG
+ * - "GRBG" for GRGRGR / BGBGBG
+ * - "RGGB" for RGRGRG / GBGBGB
+ * - "BGGR" for BGBGBG / GRGRGR
+ */
+ const char* color_order;
+ /* Bitmask for valid bits in the pixel:
+ * - 0xff For a 8-bit BAYER format
+ * - 0x3ff For a 10-bit BAYER format
+ * - 0xfff For a 12-bit BAYER format
+ */
+ int mask;
+};
+
/********************************************************************************
* RGB/BRG load / save routines.
*******************************************************************************/
@@ -614,7 +650,258 @@ _VOffSepYUV(const YUVDesc* desc, int line, int width, int height)
}
/********************************************************************************
- * Generic YUV/RGB converters
+ * Bayer routines.
+ *******************************************************************************/
+
+/* Gets a color value for the given pixel in a bayer framebuffer.
+ * Param:
+ * desc - Bayer framebuffer descriptor.
+ * buf - Beginning of the framebuffer.
+ * x, y - Coordinates of the pixel inside the framebuffer to get the color for.
+ * width - Number of pixel in a line inside the framebuffer.
+ * Return:
+ * Given pixel color.
+ */
+static __inline__ int
+_get_bayer_color(const BayerDesc* desc, const void* buf, int x, int y, int width)
+{
+ if (desc->mask == kBayer8) {
+ /* Each pixel is represented with one byte. */
+ return *((const uint8_t*)buf + y * width + x);
+ } else {
+#ifndef HOST_WORDS_BIGENDIAN
+ return *((const int16_t*)buf + y * width + x) & desc->mask;
+#else
+ const uint8_t* pixel = (const uint8_t*)buf + (y * width + x) * 2;
+ return (((uint16_t)pixel[1] << 8) | pixel[0]) & desc->mask;
+#endif /* !HOST_WORDS_BIGENDIAN */
+ }
+}
+
+/* Gets an average value of colors that are horisontally adjacent to a pixel in
+ * a bayer framebuffer.
+ * Param:
+ * desc - Bayer framebuffer descriptor.
+ * buf - Beginning of the framebuffer.
+ * x, y - Coordinates of the pixel inside the framebuffer that is the center for
+ * the calculation.
+ * width, height - Framebuffer dimensions.
+ * Return:
+ * Average color for horisontally adjacent pixels.
+ */
+static int
+_get_bayer_ave_hor(const BayerDesc* desc,
+ const void* buf,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ if (x == 0) {
+ return _get_bayer_color(desc, buf, x + 1, y, width);
+ } else if (x == (width - 1)) {
+ return _get_bayer_color(desc, buf, x - 1, y, width);
+ } else {
+ return (_get_bayer_color(desc, buf, x - 1, y, width) +
+ _get_bayer_color(desc, buf, x + 1, y, width)) / 2;
+ }
+}
+
+/* Gets an average value of colors that are vertically adjacent to a pixel in
+ * a bayer framebuffer.
+ * Param:
+ * desc - Bayer framebuffer descriptor.
+ * buf - Beginning of the framebuffer.
+ * x, y - Coordinates of the pixel inside the framebuffer that is the center for
+ * the calculation.
+ * width, height - Framebuffer dimensions.
+ * Return:
+ * Average color for vertically adjacent pixels.
+ */
+static int
+_get_bayer_ave_vert(const BayerDesc* desc,
+ const void* buf,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ if (y == 0) {
+ return _get_bayer_color(desc, buf, x, y + 1, width);
+ } else if (y == (height - 1)) {
+ return _get_bayer_color(desc, buf, x, y - 1, width);
+ } else {
+ return (_get_bayer_color(desc, buf, x, y - 1, width) +
+ _get_bayer_color(desc, buf, x, y + 1, width)) / 2;
+ }
+}
+
+/* Gets an average value of colors that are horisontally and vertically adjacent
+ * to a pixel in a bayer framebuffer.
+ * Param:
+ * desc - Bayer framebuffer descriptor.
+ * buf - Beginning of the framebuffer.
+ * x, y - Coordinates of the pixel inside the framebuffer that is the center for
+ * the calculation.
+ * width, height - Framebuffer dimensions.
+ * Return:
+ * Average color for horisontally and vertically adjacent pixels.
+ */
+static int
+_get_bayer_ave_cross(const BayerDesc* desc,
+ const void* buf,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ if (x > 0 && x < (width - 1) && y > 0 && y < (height - 1)) {
+ /* Most of the time the code will take this path. So it makes sence to
+ * special case it for performance reasons. */
+ return (_get_bayer_color(desc, buf, x - 1, y, width) +
+ _get_bayer_color(desc, buf, x + 1, y, width) +
+ _get_bayer_color(desc, buf, x, y - 1, width) +
+ _get_bayer_color(desc, buf, x, y + 1, width)) / 4;
+ } else {
+ int sum = 0;
+ int num = 0;
+
+ /* Horisontal sum */
+ if (x == 0) {
+ sum += _get_bayer_color(desc, buf, x + 1, y, width);
+ num++;
+ } else if (x == (width - 1)) {
+ sum += _get_bayer_color(desc, buf, x - 1, y, width);
+ num++;
+ } else {
+ sum += _get_bayer_color(desc, buf, x - 1, y, width) +
+ _get_bayer_color(desc, buf, x + 1, y, width);
+ num += 2;
+ }
+
+ /* Vertical sum */
+ if (y == 0) {
+ sum += _get_bayer_color(desc, buf, x, y + 1, width);
+ num++;
+ } else if (y == (height - 1)) {
+ sum += _get_bayer_color(desc, buf, x, y - 1, width);
+ num++;
+ } else {
+ sum += _get_bayer_color(desc, buf, x, y - 1, width) +
+ _get_bayer_color(desc, buf, x, y + 1, width);
+ num += 2;
+ }
+
+ return sum / num;
+ }
+}
+
+/* Gets an average value of colors that are diagonally adjacent to a pixel in a
+ * bayer framebuffer.
+ * Param:
+ * desc - Bayer framebuffer descriptor.
+ * buf - Beginning of the framebuffer.
+ * x, y - Coordinates of the pixel inside the framebuffer that is the center for
+ * the calculation.
+ * width, height - Framebuffer dimensions.
+ * Return:
+ * Average color for diagonally adjacent pixels.
+ */
+static int
+_get_bayer_ave_diag(const BayerDesc* desc,
+ const void* buf,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ if (x > 0 && x < (width - 1) && y > 0 && y < (height - 1)) {
+ /* Most of the time the code will take this path. So it makes sence to
+ * special case it for performance reasons. */
+ return (_get_bayer_color(desc, buf, x - 1, y - 1, width) +
+ _get_bayer_color(desc, buf, x + 1, y - 1, width) +
+ _get_bayer_color(desc, buf, x - 1, y + 1, width) +
+ _get_bayer_color(desc, buf, x + 1, y + 1, width)) / 4;
+ } else {
+ int sum = 0;
+ int num = 0;
+ int xx, yy;
+ for (xx = x - 1; xx < (x + 2); xx += 2) {
+ for (yy = y - 1; yy < (y + 2); yy += 2) {
+ if (xx >= 0 && yy >= 0 && xx < width && yy < height) {
+ sum += _get_bayer_color(desc, buf, xx, yy, width);
+ num++;
+ }
+ }
+ }
+ return sum / num;
+ }
+}
+
+/* Gets pixel color selector for the given pixel in a bayer framebuffer.
+ * Param:
+ * desc - Bayer framebuffer descriptor.
+ * x, y - Coordinates of the pixel inside the framebuffer to get the color
+ * selector for.
+ * Return:
+ * Pixel color selector:
+ * - 'R' - pixel is red.
+ * - 'G' - pixel is green.
+ * - 'B' - pixel is blue.
+ */
+static __inline__ char
+_get_bayer_color_sel(const BayerDesc* desc, int x, int y)
+{
+ return desc->color_order[((y & 1) << 1) | (x & 1)];
+}
+
+/* Calculates RGB colors for a pixel in a bayer framebuffer.
+ * Param:
+ * desc - Bayer framebuffer descriptor.
+ * buf - Beginning of the framebuffer.
+ * x, y - Coordinates of the pixel inside the framebuffer to get the colors for.
+ * width, height - Framebuffer dimensions.
+ * red, green bluu - Upon return will contain RGB colors calculated for the pixel.
+ */
+static void
+_get_bayerRGB(const BayerDesc* desc,
+ const void* buf,
+ int x,
+ int y,
+ int width,
+ int height,
+ int* red,
+ int* green,
+ int* blue)
+{
+ const char pixel_color = _get_bayer_color_sel(desc, x, y);
+
+ if (pixel_color == 'G') {
+ /* This is a green pixel. */
+ const char next_pixel_color = _get_bayer_color_sel(desc, x + 1, y);
+ *green = _get_bayer_color(desc, buf, x, y, width);
+ if (next_pixel_color == 'R') {
+ *red = _get_bayer_ave_hor(desc, buf, x, y, width, height);
+ *blue = _get_bayer_ave_vert(desc, buf, x, y, width, height);
+ } else {
+ *red = _get_bayer_ave_vert(desc, buf, x, y, width, height);
+ *blue = _get_bayer_ave_hor(desc, buf, x, y, width, height);
+ }
+ } else if (pixel_color == 'R') {
+ /* This is a red pixel. */
+ *red = _get_bayer_color(desc, buf, x, y, width);
+ *green = _get_bayer_ave_cross(desc, buf, x, y, width, height);
+ *blue = _get_bayer_ave_diag(desc, buf, x, y, width, height);
+ } else {
+ /* This is a blue pixel. */
+ *blue = _get_bayer_color(desc, buf, x, y, width);
+ *green = _get_bayer_ave_cross(desc, buf, x, y, width, height);
+ *red = _get_bayer_ave_diag(desc, buf, x, y, width, height);
+ }
+}
+
+/********************************************************************************
+ * Generic YUV/RGB/BAYER converters
*******************************************************************************/
/* Generic converter from an RGB/BRG format to a YUV format. */
@@ -744,6 +1031,62 @@ YUVToYUV(const YUVDesc* src_fmt,
}
}
+/* Generic converter from a BAYER format to an RGB/BRG format. */
+static void
+BAYERToRGB(const BayerDesc* bayer_fmt,
+ const RGBDesc* rgb_fmt,
+ const void* bayer,
+ void* rgb,
+ int width,
+ int height)
+{
+ int y, x;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ int r, g, b;
+ _get_bayerRGB(bayer_fmt, bayer, x, y, width, height, &r, &g, &b);
+ if (bayer_fmt->mask == kBayer10) {
+ r >>= 2; g >>= 2; b >>= 2;
+ } else if (bayer_fmt->mask == kBayer12) {
+ r >>= 4; g >>= 4; b >>= 4;
+ }
+ rgb = rgb_fmt->save_rgb(rgb, r, g, b);
+ }
+ /* Aling rgb_ptr to 16 bit */
+ if (((uintptr_t)rgb & 1) != 0) rgb = (uint8_t*)rgb + 1;
+ }
+}
+
+/* Generic converter from a BAYER format to a YUV format. */
+static void
+BAYERToYUV(const BayerDesc* bayer_fmt,
+ const YUVDesc* yuv_fmt,
+ const void* bayer,
+ void* yuv,
+ int width,
+ int height)
+{
+ int y, x;
+ const int Y_Inc = yuv_fmt->Y_inc;
+ const int UV_inc = yuv_fmt->UV_inc;
+ const int Y_next_pair = yuv_fmt->Y_next_pair;
+ uint8_t* pY = (uint8_t*)yuv + yuv_fmt->Y_offset;
+ for (y = 0; y < height; y++) {
+ uint8_t* pU =
+ (uint8_t*)yuv + yuv_fmt->u_offset(yuv_fmt, y, width, height);
+ uint8_t* pV =
+ (uint8_t*)yuv + yuv_fmt->v_offset(yuv_fmt, y, width, height);
+ for (x = 0; x < width; x += 2,
+ pY += Y_next_pair, pU += UV_inc, pV += UV_inc) {
+ int r, g, b;
+ _get_bayerRGB(bayer_fmt, bayer, x, y, width, height, &r, &g, &b);
+ R8G8B8ToYUV(r, g, b, pY, pU, pV);
+ _get_bayerRGB(bayer_fmt, bayer, x + 1, y, width, height, &r, &g, &b);
+ pY[Y_Inc] = RGB2Y(r, g, b);
+ }
+ }
+}
+
/********************************************************************************
* RGB format descriptors.
*/
@@ -922,51 +1265,164 @@ static const YUVDesc _NV21 =
};
/********************************************************************************
+ * RGB bayer format descriptors.
+ */
+
+/* Descriptor for a 8-bit GBGB / RGRG format. */
+static const BayerDesc _GB8 =
+{
+ .mask = kBayer8,
+ .color_order = "GBRG"
+};
+
+/* Descriptor for a 8-bit GRGR / BGBG format. */
+static const BayerDesc _GR8 =
+{
+ .mask = kBayer8,
+ .color_order = "GRBG"
+};
+
+/* Descriptor for a 8-bit BGBG / GRGR format. */
+static const BayerDesc _BG8 =
+{
+ .mask = kBayer8,
+ .color_order = "BGGR"
+};
+
+/* Descriptor for a 8-bit RGRG / GBGB format. */
+static const BayerDesc _RG8 =
+{
+ .mask = kBayer8,
+ .color_order = "RGGB"
+};
+
+/* Descriptor for a 10-bit GBGB / RGRG format. */
+static const BayerDesc _GB10 =
+{
+ .mask = kBayer10,
+ .color_order = "GBRG"
+};
+
+/* Descriptor for a 10-bit GRGR / BGBG format. */
+static const BayerDesc _GR10 =
+{
+ .mask = kBayer10,
+ .color_order = "GRBG"
+};
+
+/* Descriptor for a 10-bit BGBG / GRGR format. */
+static const BayerDesc _BG10 =
+{
+ .mask = kBayer10,
+ .color_order = "BGGR"
+};
+
+/* Descriptor for a 10-bit RGRG / GBGB format. */
+static const BayerDesc _RG10 =
+{
+ .mask = kBayer10,
+ .color_order = "RGGB"
+};
+
+/* Descriptor for a 12-bit GBGB / RGRG format. */
+static const BayerDesc _GB12 =
+{
+ .mask = kBayer12,
+ .color_order = "GBRG"
+};
+
+/* Descriptor for a 12-bit GRGR / BGBG format. */
+static const BayerDesc _GR12 =
+{
+ .mask = kBayer12,
+ .color_order = "GRBG"
+};
+
+/* Descriptor for a 12-bit BGBG / GRGR format. */
+static const BayerDesc _BG12 =
+{
+ .mask = kBayer12,
+ .color_order = "BGGR"
+};
+
+/* Descriptor for a 12-bit RGRG / GBGB format. */
+static const BayerDesc _RG12 =
+{
+ .mask = kBayer12,
+ .color_order = "RGGB"
+};
+
+
+/********************************************************************************
* List of descriptors for supported formats.
*******************************************************************************/
+/* Enumerates pixel formats supported by converters. */
+typedef enum PIXFormatSel {
+ /* Pixel format is RGB/BGR */
+ PIX_FMT_RGB,
+ /* Pixel format is YUV */
+ PIX_FMT_YUV,
+ /* Pixel format is BAYER */
+ PIX_FMT_BAYER
+} PIXFormatSel;
+
/* Formats entry in the list of descriptors for supported formats. */
typedef struct PIXFormat {
/* "FOURCC" (V4L2_PIX_FMT_XXX) format type. */
uint32_t fourcc_type;
- /* RGB/YUV selector:
- * 1 - Entry is related to an RGB/BRG format.
- * 0 - Entry is related to a YUV format. */
- int is_RGB;
+ /* RGB/YUV/BAYER format selector */
+ PIXFormatSel format_sel;
union {
/* References RGB format descriptor for that format. */
- const RGBDesc* rgb_desc;
+ const RGBDesc* rgb_desc;
/* References YUV format descriptor for that format. */
- const YUVDesc* yuv_desc;
+ const YUVDesc* yuv_desc;
+ /* References BAYER format descriptor for that format. */
+ const BayerDesc* bayer_desc;
} desc;
} PIXFormat;
/* Array of supported pixel format descriptors. */
static const PIXFormat _PIXFormats[] = {
/* RGB/BRG formats. */
- { V4L2_PIX_FMT_RGB32, 1, .desc.rgb_desc = &_RGB32 },
- { V4L2_PIX_FMT_BGR32, 1, .desc.rgb_desc = &_BRG32 },
- { V4L2_PIX_FMT_RGB565, 1, .desc.rgb_desc = &_RGB16 },
- { V4L2_PIX_FMT_RGB24, 1, .desc.rgb_desc = &_RGB24 },
- { V4L2_PIX_FMT_BGR24, 1, .desc.rgb_desc = &_BRG24 },
+ { V4L2_PIX_FMT_RGB32, PIX_FMT_RGB, .desc.rgb_desc = &_RGB32 },
+ { V4L2_PIX_FMT_BGR32, PIX_FMT_RGB, .desc.rgb_desc = &_BRG32 },
+ { V4L2_PIX_FMT_RGB565, PIX_FMT_RGB, .desc.rgb_desc = &_RGB16 },
+ { V4L2_PIX_FMT_RGB24, PIX_FMT_RGB, .desc.rgb_desc = &_RGB24 },
+ { V4L2_PIX_FMT_BGR24, PIX_FMT_RGB, .desc.rgb_desc = &_BRG24 },
/* YUV 4:2:0 formats. */
- { V4L2_PIX_FMT_YVU420, 0, .desc.yuv_desc = &_YV12 },
- { V4L2_PIX_FMT_NV12, 0, .desc.yuv_desc = &_NV12 },
- { V4L2_PIX_FMT_NV21, 0, .desc.yuv_desc = &_NV21 },
+ { V4L2_PIX_FMT_YVU420, PIX_FMT_YUV, .desc.yuv_desc = &_YV12 },
+ { V4L2_PIX_FMT_NV12, PIX_FMT_YUV, .desc.yuv_desc = &_NV12 },
+ { V4L2_PIX_FMT_NV21, PIX_FMT_YUV, .desc.yuv_desc = &_NV21 },
/* YUV 4:2:2 formats. */
- { V4L2_PIX_FMT_YUYV, 0, .desc.yuv_desc = &_YUYV },
- { V4L2_PIX_FMT_YYUV, 0, .desc.yuv_desc = &_YYUV },
- { V4L2_PIX_FMT_YVYU, 0, .desc.yuv_desc = &_YVYU },
- { V4L2_PIX_FMT_UYVY, 0, .desc.yuv_desc = &_UYVY },
- { V4L2_PIX_FMT_VYUY, 0, .desc.yuv_desc = &_VYUY },
- { V4L2_PIX_FMT_YVYU, 0, .desc.yuv_desc = &_YVYU },
- { V4L2_PIX_FMT_VYUY, 0, .desc.yuv_desc = &_VYUY },
- { V4L2_PIX_FMT_YYVU, 0, .desc.yuv_desc = &_YYVU },
- { V4L2_PIX_FMT_YUY2, 0, .desc.yuv_desc = &_YUYV },
- { V4L2_PIX_FMT_YUNV, 0, .desc.yuv_desc = &_YUYV },
- { V4L2_PIX_FMT_V422, 0, .desc.yuv_desc = &_YUYV },
+ { V4L2_PIX_FMT_YUYV, PIX_FMT_YUV, .desc.yuv_desc = &_YUYV },
+ { V4L2_PIX_FMT_YYUV, PIX_FMT_YUV, .desc.yuv_desc = &_YYUV },
+ { V4L2_PIX_FMT_YVYU, PIX_FMT_YUV, .desc.yuv_desc = &_YVYU },
+ { V4L2_PIX_FMT_UYVY, PIX_FMT_YUV, .desc.yuv_desc = &_UYVY },
+ { V4L2_PIX_FMT_VYUY, PIX_FMT_YUV, .desc.yuv_desc = &_VYUY },
+ { V4L2_PIX_FMT_YVYU, PIX_FMT_YUV, .desc.yuv_desc = &_YVYU },
+ { V4L2_PIX_FMT_VYUY, PIX_FMT_YUV, .desc.yuv_desc = &_VYUY },
+ { V4L2_PIX_FMT_YYVU, PIX_FMT_YUV, .desc.yuv_desc = &_YYVU },
+ { V4L2_PIX_FMT_YUY2, PIX_FMT_YUV, .desc.yuv_desc = &_YUYV },
+ { V4L2_PIX_FMT_YUNV, PIX_FMT_YUV, .desc.yuv_desc = &_YUYV },
+ { V4L2_PIX_FMT_V422, PIX_FMT_YUV, .desc.yuv_desc = &_YUYV },
+
+ /* BAYER formats. */
+ { V4L2_PIX_FMT_SBGGR8, PIX_FMT_BAYER, .desc.bayer_desc = &_BG8 },
+ { V4L2_PIX_FMT_SGBRG8, PIX_FMT_BAYER, .desc.bayer_desc = &_GB8 },
+ { V4L2_PIX_FMT_SGRBG8, PIX_FMT_BAYER, .desc.bayer_desc = &_GR8 },
+ { V4L2_PIX_FMT_SRGGB8, PIX_FMT_BAYER, .desc.bayer_desc = &_RG8 },
+ { V4L2_PIX_FMT_SBGGR10, PIX_FMT_BAYER, .desc.bayer_desc = &_BG10 },
+ { V4L2_PIX_FMT_SGBRG10, PIX_FMT_BAYER, .desc.bayer_desc = &_GB10 },
+ { V4L2_PIX_FMT_SGRBG10, PIX_FMT_BAYER, .desc.bayer_desc = &_GR10 },
+ { V4L2_PIX_FMT_SRGGB10, PIX_FMT_BAYER, .desc.bayer_desc = &_RG10 },
+ { V4L2_PIX_FMT_SBGGR12, PIX_FMT_BAYER, .desc.bayer_desc = &_BG12 },
+ { V4L2_PIX_FMT_SGBRG12, PIX_FMT_BAYER, .desc.bayer_desc = &_GB12 },
+ { V4L2_PIX_FMT_SGRBG12, PIX_FMT_BAYER, .desc.bayer_desc = &_GR12 },
+ { V4L2_PIX_FMT_SRGGB12, PIX_FMT_BAYER, .desc.bayer_desc = &_RG12 },
};
static const int _PIXFormats_num = sizeof(_PIXFormats) / sizeof(*_PIXFormats);
@@ -1035,22 +1491,50 @@ convert_frame(const void* frame,
__FUNCTION__, (const char*)&framebuffers[n].pixel_format);
return -1;
}
- if (src_desc->is_RGB) {
- if (dst_desc->is_RGB) {
- RGBToRGB(src_desc->desc.rgb_desc, dst_desc->desc.rgb_desc,
- frame, framebuffers[n].framebuffer, width, height);
- } else {
- RGBToYUV(src_desc->desc.rgb_desc, dst_desc->desc.yuv_desc,
- frame, framebuffers[n].framebuffer, width, height);
- }
- } else {
- if (dst_desc->is_RGB) {
- YUVToRGB(src_desc->desc.yuv_desc, dst_desc->desc.rgb_desc,
- frame, framebuffers[n].framebuffer, width, height);
- } else {
- YUVToYUV(src_desc->desc.yuv_desc, dst_desc->desc.yuv_desc,
- frame, framebuffers[n].framebuffer, width, height);
- }
+ switch (src_desc->format_sel) {
+ case PIX_FMT_RGB:
+ if (dst_desc->format_sel == PIX_FMT_RGB) {
+ RGBToRGB(src_desc->desc.rgb_desc, dst_desc->desc.rgb_desc,
+ frame, framebuffers[n].framebuffer, width, height);
+ } else if (dst_desc->format_sel == PIX_FMT_YUV) {
+ RGBToYUV(src_desc->desc.rgb_desc, dst_desc->desc.yuv_desc,
+ frame, framebuffers[n].framebuffer, width, height);
+ } else {
+ E("%s: Unexpected destination pixel format %d",
+ __FUNCTION__, dst_desc->format_sel);
+ return -1;
+ }
+ break;
+ case PIX_FMT_YUV:
+ if (dst_desc->format_sel == PIX_FMT_RGB) {
+ YUVToRGB(src_desc->desc.yuv_desc, dst_desc->desc.rgb_desc,
+ frame, framebuffers[n].framebuffer, width, height);
+ } else if (dst_desc->format_sel == PIX_FMT_YUV) {
+ YUVToYUV(src_desc->desc.yuv_desc, dst_desc->desc.yuv_desc,
+ frame, framebuffers[n].framebuffer, width, height);
+ } else {
+ E("%s: Unexpected destination pixel format %d",
+ __FUNCTION__, dst_desc->format_sel);
+ return -1;
+ }
+ break;
+ case PIX_FMT_BAYER:
+ if (dst_desc->format_sel == PIX_FMT_RGB) {
+ BAYERToRGB(src_desc->desc.bayer_desc, dst_desc->desc.rgb_desc,
+ frame, framebuffers[n].framebuffer, width, height);
+ } else if (dst_desc->format_sel == PIX_FMT_YUV) {
+ BAYERToYUV(src_desc->desc.bayer_desc, dst_desc->desc.yuv_desc,
+ frame, framebuffers[n].framebuffer, width, height);
+ } else {
+ E("%s: Unexpected destination pixel format %d",
+ __FUNCTION__, dst_desc->format_sel);
+ return -1;
+ }
+ break;
+ default:
+ E("%s: Unexpected source pixel format %d",
+ __FUNCTION__, dst_desc->format_sel);
+ return -1;
}
}
}