| /* |
| * Copyright (C) 2016-2018 Intel Corporation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "FormatUtils" |
| |
| |
| #include <stdint.h> |
| #include <math.h> |
| #include <linux/v4l2-mediabus.h> |
| #include <string> |
| #include <sstream> |
| #include "FormatUtils.h" |
| #include "LogHelper.h" |
| #include "UtilityMacros.h" |
| #include "Camera3V4l2Format.h" |
| |
| namespace cros { |
| namespace intel { |
| using std::string; |
| |
| /** |
| * Utilities to query information about V4L2 types in graph config |
| */ |
| |
| namespace graphconfig { |
| namespace utils { |
| |
| enum FormatType { |
| FORMAT_RAW, |
| FORMAT_RAW_VEC, |
| FORMAT_YUV, |
| FORMAT_YUV_VEC, |
| FORMAT_RGB, |
| FORMAT_MBUS_BAYER, |
| FORMAT_MBUS_YUV, |
| FORMAT_JPEG |
| }; |
| |
| struct FormatInfo { |
| int32_t pixelCode; // OS specific pixel code, in this case V4L2 or Media bus |
| int32_t commonPixelCode; // Common pixel code used by CIPF and GCSS in settings |
| string fullName; |
| string shortName; |
| int32_t bpp; |
| FormatType type; |
| }; |
| /** |
| * gFormatMapping |
| * |
| * Table for mapping OS agnostic formats defined in CIPF and OS specific ones |
| * (in this case V4L2, or media bus). |
| * The table also helps provide textual representation and bits per pixel. |
| * CIPF does not define most of the formats, only the ones it needs, that is why |
| * most of the entries have 0 on the common pixel format. |
| * Conversely there are some new formats introduce by CIPF that do not have |
| * V4L2 representation. |
| */ |
| static const FormatInfo gFormatMapping[] = { |
| { V4L2_PIX_FMT_SBGGR8, 0, "V4L2_PIX_FMT_SBGGR8", "BGGR8", 8, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SGBRG8, 0, "V4L2_PIX_FMT_SGBRG8", "GBRG8", 8, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SGRBG8, 0, "V4L2_PIX_FMT_SGRBG8", "GRBG8", 8, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SRGGB8, 0, "V4L2_PIX_FMT_SRGGB8", "RGGB8", 8, FORMAT_RAW }, |
| |
| { V4L2_PIX_FMT_SBGGR12, 0, "V4L2_PIX_FMT_SBGGR12", "BGGR12", 16, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SGBRG12, 0, "V4L2_PIX_FMT_SGBRG12", "GBRG12", 16, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SGRBG12, 0, "V4L2_PIX_FMT_SGRBG12", "GRBG12", 16, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SRGGB12, 0, "V4L2_PIX_FMT_SRGGB12", "RGGB12", 16, FORMAT_RAW }, |
| |
| { V4L2_PIX_FMT_SBGGR10P, 0, "V4L2_PIX_FMT_SBGGR10P", "BGGR10P", 10, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SGBRG10P, 0, "V4L2_PIX_FMT_SGBRG10P", "GBRG10P", 10, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SGRBG10P, 0, "V4L2_PIX_FMT_SGRBG10P", "GRBG10P", 10, FORMAT_RAW }, |
| { V4L2_PIX_FMT_SRGGB10P, 0, "V4L2_PIX_FMT_SRGGB10P", "RGGB10P", 10, FORMAT_RAW }, |
| |
| { V4L2_PIX_FMT_IPU3_SBGGR10, 0, "V4L2_PIX_FMT_IPU3_SBGGR10", "BGGR10", 16, FORMAT_RAW_VEC }, |
| { V4L2_PIX_FMT_IPU3_SGBRG10, 0, "V4L2_PIX_FMT_IPU3_SGBRG10", "GBRG10", 16, FORMAT_RAW_VEC }, |
| { V4L2_PIX_FMT_IPU3_SGRBG10, 0, "V4L2_PIX_FMT_IPU3_SGRBG10", "GRBG10", 16, FORMAT_RAW_VEC }, |
| { V4L2_PIX_FMT_IPU3_SRGGB10, 0, "V4L2_PIX_FMT_IPU3_SRGGB10", "RGGB10", 16, FORMAT_RAW_VEC }, |
| |
| { V4L2_PIX_FMT_NV16, 0, "V4L2_PIX_FMT_NV16", "NV16", 16, FORMAT_YUV }, |
| { V4L2_PIX_FMT_YUYV, 0, "V4L2_PIX_FMT_YUYV", "YUYV", 16, FORMAT_YUV }, |
| |
| { V4L2_PIX_FMT_YUV420, 0, "V4L2_PIX_FMT_YUV420", "YUV420", 12, FORMAT_YUV }, |
| { V4L2_PIX_FMT_YVU420, 0, "V4L2_PIX_FMT_YVU420", "YVU420", 12, FORMAT_YUV }, |
| { V4L2_PIX_FMT_YUV422P, 0, "V4L2_PIX_FMT_YUV422P", "YUV422P", 16, FORMAT_YUV }, |
| |
| { V4L2_PIX_FMT_BGR24, 0, "V4L2_PIX_FMT_BGR24", "BGR24", 24, FORMAT_RGB }, |
| { V4L2_PIX_FMT_XBGR32, 0, "V4L2_PIX_FMT_XBGR32", "XBGR32", 32, FORMAT_RGB }, |
| { V4L2_PIX_FMT_XRGB32, 0, "V4L2_PIX_FMT_XRGB32", "XRGB32", 32, FORMAT_RGB }, |
| { V4L2_PIX_FMT_RGB565, 0, "V4L2_PIX_FMT_RGB565", "RGB565", 16, FORMAT_RGB }, |
| |
| { V4L2_PIX_FMT_JPEG, 0, "V4L2_PIX_FMT_JPEG", "JPEG", 0, FORMAT_JPEG }, |
| |
| { V4L2_MBUS_FMT_SBGGR12_1X12, 0, "V4L2_MBUS_FMT_SBGGR12_1X12", "SBGGR12_1X12", 12, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SGBRG12_1X12, 0, "V4L2_MBUS_FMT_SGBRG12_1X12", "SGBRG12_1X12", 12, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SGRBG12_1X12, 0, "V4L2_MBUS_FMT_SGRBG12_1X12", "SGRBG12_1X12", 12, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SRGGB12_1X12, 0, "V4L2_MBUS_FMT_SRGGB12_1X12", "SRGGB12_1X12", 12, FORMAT_MBUS_BAYER }, |
| |
| { V4L2_MBUS_FMT_SBGGR10_1X10, get_fourcc('B', 'G', '1', '0'), "V4L2_MBUS_FMT_SBGGR10_1X10", "SBGGR10_1X10", 10, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SGBRG10_1X10, get_fourcc('G', 'B', '1', '0'), "V4L2_MBUS_FMT_SGBRG10_1X10", "SGBRG10_1X10", 10, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SGRBG10_1X10, get_fourcc('B', 'A', '1', '0'), "V4L2_MBUS_FMT_SGRBG10_1X10", "SGRBG10_1X10", 10, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SRGGB10_1X10, get_fourcc('R', 'G', '1', '0'), "V4L2_MBUS_FMT_SRGGB10_1X10", "SRGGB10_1X10", 10, FORMAT_MBUS_BAYER }, |
| |
| { V4L2_MBUS_FMT_SBGGR8_1X8, 0, "V4L2_MBUS_FMT_SBGGR8_1X8", "SBGGR8_1X8", 8, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SGBRG8_1X8, 0, "V4L2_MBUS_FMT_SGBRG8_1X8", "SGBRG8_1X8", 8, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SGRBG8_1X8, 0, "V4L2_MBUS_FMT_SGRBG8_1X8", "SGRBG8_1X8", 8, FORMAT_MBUS_BAYER }, |
| { V4L2_MBUS_FMT_SRGGB8_1X8, 0, "V4L2_MBUS_FMT_SRGGB8_1X8", "SRGGB8_1X8", 8, FORMAT_MBUS_BAYER }, |
| |
| { V4L2_MBUS_FMT_YUYV8_1X16, 0, "V4L2_MBUS_FMT_YUYV8_1X16", "YUYV8_1X16", 16, FORMAT_MBUS_YUV } |
| }; |
| |
| const string pixelCode2String(int32_t code) |
| { |
| |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].pixelCode == code) { |
| return gFormatMapping[i].fullName; |
| } |
| } |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].commonPixelCode == code) { |
| return gFormatMapping[i].fullName; |
| } |
| } |
| |
| LOGE("Invalid Pixel Format: 0x%x, %s", code, v4l2Fmt2Str(code)); |
| return "INVALID FORMAT"; |
| } |
| |
| /** |
| * Calculate bytes per line(bpl) based on fourcc format. |
| * |
| * \param[in] format 4CC code in OS specific format |
| * \return bpl bytes per line |
| */ |
| int32_t getBpl(int32_t format, int32_t width) |
| { |
| int32_t bpl = 0; |
| switch (format) { |
| default: |
| bpl = width; |
| LOGW("bpl defaulting to width"); |
| break; |
| } |
| return bpl; |
| } |
| |
| /** |
| * Retrieve the bits per pixel from the OS specific pixel code. |
| * This is ususally used for buffer allocation calculations |
| * |
| * \param [in] format 4CC code in OS specific format |
| * \return bits per pixel |
| */ |
| int32_t getBpp(int32_t format) |
| { |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].pixelCode == format) { |
| return gFormatMapping[i].bpp; |
| } |
| } |
| |
| LOGE("There is no bpp supplied for format %s", |
| pixelCode2String(format).c_str()); |
| return -1; |
| } |
| |
| /** |
| * Retrieve the bits per pixel from the common pixel code format (CIPF) |
| * This is usually used for buffer allocation calculations |
| * |
| * \param [in] format 4CC code in Common format |
| * \return bits per pixel |
| */ |
| int32_t getBppFromCommon(int32_t format) |
| { |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].commonPixelCode == format) { |
| return gFormatMapping[i].bpp; |
| } |
| } |
| |
| LOGE("There is no bpp supplied for format %s", |
| pixelCode2String(format).c_str()); |
| return -1; |
| } |
| |
| /** |
| * For a given bayer order and bpp combination it searches the table to find |
| * a valid MBUS format. |
| * The search is done on the shortname. |
| * |
| * \param [in] bayerOrder String with bayer order. Ex: RGGB |
| * \param [in] bpp Bits per pixe |
| * \return pixel code of the MBUS format that matches that bayer order and |
| * bpp, or -1 if not found. |
| * |
| */ |
| |
| int32_t getMBusFormat(const std::string& bayerOrder, const int32_t bpp) |
| { |
| std::ostringstream stringStream; |
| stringStream << bpp; |
| string bppAsStr = stringStream.str(); |
| |
| string targetFormat = bayerOrder + bppAsStr; |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].type == FORMAT_MBUS_BAYER) { |
| if (gFormatMapping[i].shortName.find(targetFormat) != string::npos) |
| return gFormatMapping[i].pixelCode; |
| } else if (gFormatMapping[i].type == FORMAT_MBUS_YUV) { |
| if (gFormatMapping[i].shortName.find(bppAsStr) != string::npos) |
| return gFormatMapping[i].pixelCode; |
| } else if (gFormatMapping[i].type == FORMAT_RAW_VEC) { |
| if (gFormatMapping[i].shortName.compare(targetFormat) == 0) { |
| return gFormatMapping[i].pixelCode; |
| } |
| } |
| } |
| |
| LOGE("Failed to find any MBUS format with format %s",targetFormat.c_str()); |
| return -1; |
| } |
| |
| int32_t getMBusFormat(int32_t commonPixelFormat) |
| { |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].type == FORMAT_MBUS_BAYER || |
| gFormatMapping[i].type == FORMAT_MBUS_YUV ) { |
| if (gFormatMapping[i].commonPixelCode == commonPixelFormat) |
| return gFormatMapping[i].pixelCode; |
| } |
| } |
| |
| LOGE("Failed to find any MBUS format with format %s", |
| pixelCode2String(commonPixelFormat).c_str()); |
| return -1; |
| } |
| |
| int32_t getV4L2Format(const int32_t commonPixelFormat) |
| { |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].commonPixelCode == commonPixelFormat) |
| return gFormatMapping[i].pixelCode; |
| } |
| |
| LOGE("Failed to find any V4L2 format with format %s", |
| pixelCode2String(commonPixelFormat).c_str()); |
| return -1; |
| } |
| |
| int32_t getV4L2Format(const std::string& formatName) |
| { |
| for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) { |
| if (gFormatMapping[i].fullName.compare(formatName) == 0) |
| return gFormatMapping[i].pixelCode; |
| } |
| |
| LOGE("Failed to find any V4L2 format with format %s", |
| formatName.c_str()); |
| return -1; |
| } |
| |
| } // namespace utils |
| } // namespace graphconfig |
| } /* namespace intel */ |
| } /* namespace cros */ |