/*
|
* Copyright (c) 2021 by Allwinnertech 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.
|
*/
|
|
#include "stream_format.h"
|
|
#include <linux/videodev2.h>
|
#include <system/graphics.h>
|
|
#include "v4l2_log.h"
|
|
namespace v4l2_camera_hal {
|
|
StreamFormat::StreamFormat(int format, uint32_t width, uint32_t height)
|
// TODO(b/30000211): multiplanar support.
|
: type_(V4L2_CAPTURE_TYPE),
|
memory_(V4L2_MEMORY_MMAP),
|
v4l2_pixel_format_(StreamFormat::HalToV4L2PixelFormat(format)),
|
width_(width),
|
height_(height),
|
// Be compatibility with GPU, DE, VE, CSI, ISP.
|
// Now we set the bytes_per_line_ as width
|
// because the drivers return this one.
|
bytes_per_line_(width) {}
|
|
StreamFormat::StreamFormat(const v4l2_format& format, bool mergeStreamFlag)
|
// be compatibility with multiplanar and single planar.
|
: type_(format.type),
|
memory_(V4L2_MEMORY_MMAP),
|
nplanes_(format.fmt.pix_mp.num_planes),
|
// TODO(b/30000211): multiplanar support.
|
v4l2_pixel_format_(format.fmt.pix_mp.pixelformat),
|
width_(format.fmt.pix_mp.width),
|
height_(format.fmt.pix_mp.height),
|
bytes_per_line_(format.fmt.pix_mp.width),
|
merge_stream_flag_(mergeStreamFlag){}
|
|
void StreamFormat::FillFormatRequest(v4l2_format* format) const {
|
memset(format, 0, sizeof(*format));
|
format->type = type_;
|
format->fmt.pix_mp.pixelformat = v4l2_pixel_format_;
|
format->fmt.pix_mp.width = width_;
|
format->fmt.pix_mp.height = height_;
|
// Bytes per line and min buffer size are outputs set by the driver,
|
// not part of the request.
|
}
|
|
FormatCategory StreamFormat::Category() const {
|
switch (v4l2_pixel_format_) {
|
case V4L2_PIX_FMT_JPEG:
|
return kFormatCategoryStalling;
|
case V4L2_PIX_FMT_YUV420: // Fall through.
|
case V4L2_PIX_FMT_BGR32:
|
return kFormatCategoryNonStalling;
|
default:
|
// Note: currently no supported RAW formats.
|
return kFormatCategoryUnknown;
|
}
|
}
|
|
bool StreamFormat::operator==(const StreamFormat& other) const {
|
// Used to check that a requested format was actually set, so
|
// don't compare bytes per line or min buffer size.
|
return (type_ == other.type_ &&
|
v4l2_pixel_format_ == other.v4l2_pixel_format_ &&
|
width_ == other.width_ && height_ == other.height_);
|
}
|
|
bool StreamFormat::operator!=(const StreamFormat& other) const {
|
return !(*this == other);
|
}
|
|
int StreamFormat::V4L2ToHalPixelFormat(uint32_t v4l2_pixel_format) {
|
HAL_LOGD("Get v4l2_pixel_format %s",
|
getV4l2PixelFormatString(v4l2_pixel_format).c_str());
|
// Translate V4L2 format to HAL format.
|
int hal_pixel_format = -1;
|
switch (v4l2_pixel_format) {
|
case V4L2_PIX_FMT_JPEG:
|
hal_pixel_format = HAL_PIXEL_FORMAT_BLOB;
|
break;
|
case V4L2_PIX_FMT_NV21:
|
hal_pixel_format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
|
HAL_LOGD("Set format as %s for GPU",
|
getHalPixelFormatString(hal_pixel_format).c_str());
|
break;
|
case V4L2_PIX_FMT_NV12:
|
hal_pixel_format = HAL_PIXEL_FORMAT_YCbCr_420_888;
|
HAL_LOGD("Set format as %s",
|
getHalPixelFormatString(hal_pixel_format).c_str());
|
break;
|
case V4L2_PIX_FMT_YUV420:
|
hal_pixel_format = HAL_PIXEL_FORMAT_YCbCr_420_888;
|
HAL_LOGD("Set format as %s",
|
getHalPixelFormatString(hal_pixel_format).c_str());
|
break;
|
case V4L2_PIX_FMT_BGR32:
|
hal_pixel_format = HAL_PIXEL_FORMAT_RGBA_8888;
|
HAL_LOGD("Set format as %s",
|
getHalPixelFormatString(hal_pixel_format).c_str());
|
break;
|
default:
|
// Unrecognized format.
|
if (getV4l2PixelFormatString(v4l2_pixel_format) != "") {
|
HAL_LOGV("Unrecognized v4l2 pixel format %s",
|
getV4l2PixelFormatString(v4l2_pixel_format).c_str());
|
} else {
|
HAL_LOGV("Unrecognized v4l2 pixel format %u", v4l2_pixel_format);
|
}
|
break;
|
}
|
return hal_pixel_format;
|
}
|
|
uint32_t StreamFormat::HalToV4L2PixelFormat(int hal_pixel_format) {
|
// Translate HAL format to V4L2 format.
|
uint32_t v4l2_pixel_format = 0;
|
switch (hal_pixel_format) {
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
// Should be RGB32, but RPi doesn't support that.
|
// For now we accept that the colors will be off.
|
v4l2_pixel_format = V4L2_PIX_FMT_BGR32;
|
break;
|
// Set the default format between CSI and GPU-gralloc
|
// with HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED.
|
// In CSI we see the HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
|
// as V4L2_PIX_FMT_NV21.
|
// In GPU they see the HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
|
// as HAL_PIXEL_FORMAT_YCrCb_420_SP.
|
// PS: In CSI V4L2_PIX_FMT_YVU420 equals YV12.
|
// In CSI V4L2_PIX_FMT_YUV420 equals YV21.
|
// keep the HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED for MPLANE.
|
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: // fall-through.
|
v4l2_pixel_format = V4L2_PIX_FMT_NV21;
|
break;
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
v4l2_pixel_format = V4L2_PIX_FMT_NV21;
|
break;
|
case HAL_PIXEL_FORMAT_YCbCr_420_888:
|
v4l2_pixel_format = V4L2_PIX_FMT_NV21;
|
break;
|
case HAL_PIXEL_FORMAT_BLOB:
|
v4l2_pixel_format = V4L2_PIX_FMT_JPEG;
|
break;
|
default:
|
// Unrecognized format.
|
HAL_LOGV("Unrecognized HAL pixel format %d", hal_pixel_format);
|
break;
|
}
|
HAL_LOGD("HAL pixel format is %s. set v4l2_pixel_format to %s",
|
getHalPixelFormatString(hal_pixel_format).c_str(),
|
getV4l2PixelFormatString(v4l2_pixel_format).c_str());
|
return v4l2_pixel_format;
|
}
|
|
bool StreamFormat::GetMergeStreamFlag() {
|
return merge_stream_flag_;
|
}
|
|
} // namespace v4l2_camera_hal
|