blob: 4d87f881ae4fd9d785af477d645789562af8bdd3 [file] [log] [blame]
/*
* 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 */