android13/hardware/rockchip/camera/common/platformdata/gc/FormatUtils.cpp

306 lines
12 KiB
C++

/*
* Copyright (C) 2016-2017 Intel Corporation.
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
*
* 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_DECLARATION {
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, get_fourcc('B', 'G', '1', '2'), "V4L2_PIX_FMT_SBGGR12", "BGGR12", 16, FORMAT_RAW },
{ V4L2_PIX_FMT_SGBRG12, get_fourcc('G', 'B', '1', '2'), "V4L2_PIX_FMT_SGBRG12", "GBRG12", 16, FORMAT_RAW },
{ V4L2_PIX_FMT_SGRBG12, get_fourcc('G', 'R', '1', '2'), "V4L2_PIX_FMT_SGRBG12", "GRBG12", 16, FORMAT_RAW },
{ V4L2_PIX_FMT_SRGGB12, get_fourcc('R', 'G', '1', '2'), "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_SBGGR10, get_fourcc('B', 'G', '1', '0'), "V4L2_PIX_FMT_SBGGR10", "BGGR10", 10, FORMAT_RAW },
{ V4L2_PIX_FMT_SGBRG10, get_fourcc('G', 'B', '1', '0'), "V4L2_PIX_FMT_SGBRG10", "GBRG10", 10, FORMAT_RAW },
{ V4L2_PIX_FMT_SGRBG10, get_fourcc('G', 'R', '1', '0'), "V4L2_PIX_FMT_SGRBG10", "GRBG10", 10, FORMAT_RAW },
{ V4L2_PIX_FMT_SRGGB10, get_fourcc('R', 'G', '1', '0'), "V4L2_PIX_FMT_SRGGB10", "RGGB10", 10, FORMAT_RAW },
{ V4L2_PIX_FMT_NV16, get_fourcc('N', 'V', '1', '6'), "V4L2_PIX_FMT_NV16", "NV16", 16, FORMAT_YUV },
{ V4L2_PIX_FMT_NV12, get_fourcc('N', 'V', '1', '2'), "V4L2_PIX_FMT_NV12", "NV12", 12, FORMAT_YUV },
{ V4L2_PIX_FMT_YUYV, get_fourcc('Y', 'U', 'Y', 'V'), "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_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('G', 'R', '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_SBGGR12_1X12, get_fourcc('B', 'G', '1', '2'), "V4L2_MBUS_FMT_SBGGR12_1X12", "SBGGR12_1X12", 12, FORMAT_MBUS_BAYER },
{ V4L2_MBUS_FMT_SGBRG12_1X12, get_fourcc('G', 'B', '1', '2'), "V4L2_MBUS_FMT_SGBRG12_1X12", "SGBRG12_1X12", 12, FORMAT_MBUS_BAYER },
{ V4L2_MBUS_FMT_SGRBG12_1X12, get_fourcc('G', 'R', '1', '2'), "V4L2_MBUS_FMT_SGRBG12_1X12", "SGRBG12_1X12", 12, FORMAT_MBUS_BAYER },
{ V4L2_MBUS_FMT_SRGGB12_1X12, get_fourcc('R', 'G', '1', '2'), "V4L2_MBUS_FMT_SRGGB12_1X12", "SRGGB12_1X12", 12, 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, get_fourcc('N', 'V', '6', '1'), "V4L2_MBUS_FMT_YUYV8_1X16", "YUYV8_1X16", 16, FORMAT_MBUS_YUV },
{ V4L2_MBUS_FMT_YVYU8_1X16, get_fourcc('N', 'V', '1', '6'), "V4L2_MBUS_FMT_YVYU8_1X16", "YVYU8_1X16", 16, FORMAT_MBUS_YUV },
{ V4L2_MBUS_FMT_YUYV8_2X8, get_fourcc('Y', 'U', 'Y', 'V'), "V4L2_MBUS_FMT_YUYV8_2X8", "YUYV8_2X8", 16, FORMAT_MBUS_YUV },
{ V4L2_MBUS_FMT_YVYU8_2X8, get_fourcc('Y', 'V', 'Y', 'U'), "V4L2_MBUS_FMT_YVYU8_2X8", "YVYU8_2X8", 16, FORMAT_MBUS_YUV },
{ V4L2_MBUS_FMT_UYVY8_2X8, get_fourcc('U', 'Y', 'V', 'Y'), "V4L2_MBUS_FMT_UYVY8_2X8", "UYVY8_2X8", 16, FORMAT_MBUS_YUV },
};
bool isRawFormat(int32_t format) {
for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) {
if (gFormatMapping[i].pixelCode == format) {
FormatType type = gFormatMapping[i].type;
return (type == FORMAT_RAW || type == FORMAT_MBUS_BAYER) ? true : false;
}
}
LOGW("@%s:Invalid Format: 0x%x, %s", __FUNCTION__, format, v4l2Fmt2Str(format));
return false;
}
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";
}
int32_t pixelCode2fourcc(int32_t code)
{
for (size_t i = 0; i < ARRAY_SIZE(gFormatMapping); i++) {
if (gFormatMapping[i].pixelCode == code) {
return gFormatMapping[i].commonPixelCode;
}
}
LOGE("@%s :Invalid Pixel Format: 0x%x, %s ", __FUNCTION__, code, v4l2Fmt2Str(code));
return -1;
}
/**
* 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;
}
}
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].type == FORMAT_MBUS_BAYER ||
gFormatMapping[i].type == FORMAT_MBUS_YUV )
continue;
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_DECLARATION_END