blob: 962486a278dc6d89a9e48df5783fee4ec0ddb8dc [file] [log] [blame]
/*
* Copyright (C) 2017-2020 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 "PostProcessor"
#include "PostProcessor.h"
#include "HALv3Utils.h"
namespace camera3 {
PostProcessor::PostProcessor(int cameraId, const camera3_stream_t& stream)
: mCameraId(cameraId),
mPostProcessType(icamera::POST_PROCESS_NONE),
mPostProcessorCore(std::unique_ptr<icamera::PostProcessorCore>(
new icamera::PostProcessorCore(cameraId))) {
LOG1("@%s", __func__);
}
PostProcessor::~PostProcessor() {
LOG1("@%s", __func__);
}
icamera::status_t PostProcessor::configure(const camera3_stream_t& stream,
const camera3_stream_t& srcStream) {
LOG1("@%s, stream: w:%d, h:%d, f:%d", __func__, stream.width, stream.height, stream.format);
LOG1("@%s, srcStream: w:%d, h:%d, f:%d", __func__, srcStream.width, srcStream.height,
srcStream.format);
icamera::stream_t halStream;
int ret = camera3::HalV3Utils::fillHALStreams(mCameraId, srcStream, &halStream);
LOG1("@%s, halStream: w:%d, h:%d, f:%d, size:%d, stride:%d, ret:%d", __func__, halStream.width,
halStream.height, halStream.format, halStream.size, halStream.stride, ret);
CheckError(ret != icamera::OK, ret, "fillHALStreams fails, ret %d", ret);
return configure(stream, halStream);
}
/* configure
*
* Decide post-processing is needed based on user stream and hal stream.
* The default processing order is rotate -> crop -> scale -> convert -> encode.
*/
icamera::status_t PostProcessor::configure(const camera3_stream_t& stream,
const icamera::stream_t& halStream) {
LOG1("@%s, stream: w:%d, h:%d, f:%d", __func__, stream.width, stream.height, stream.format);
LOG1("@%s, halStream: w:%d, h:%d, f:%d, size:%d, stride:%d", __func__, halStream.width,
halStream.height, halStream.format, halStream.size, halStream.stride);
icamera::PostProcessInfo info;
mPostProcessType = icamera::POST_PROCESS_NONE;
std::vector<icamera::PostProcessInfo> processingOrder;
int angle = HalV3Utils::getRotationDegrees(stream);
/* Fill the input/output information for the post processing unit.
* The input info of processing unit is the output info of last unit.
*/
icamera::stream_t inputStreamInfo = halStream;
if (angle > 0 && mPostProcessorCore->isPostProcessTypeSupported(icamera::POST_PROCESS_ROTATE)) {
mPostProcessType |= icamera::POST_PROCESS_ROTATE;
info.angle = angle;
info.type = icamera::POST_PROCESS_ROTATE;
info.inputInfo = inputStreamInfo;
info.outputInfo = inputStreamInfo;
info.outputInfo.width = inputStreamInfo.height;
info.outputInfo.height = inputStreamInfo.width;
info.outputInfo.stride = inputStreamInfo.height;
info.outputInfo.format = inputStreamInfo.format;
info.outputInfo.size = icamera::CameraUtils::getFrameSize(
info.outputInfo.format, info.outputInfo.width, info.outputInfo.height);
LOG2("%s, Rotate: input %dx%d, output: %dx%d, angle: %d", __func__, inputStreamInfo.width,
inputStreamInfo.height, info.outputInfo.width, info.outputInfo.height, angle);
inputStreamInfo = info.outputInfo;
processingOrder.push_back(info);
}
// Crop
if (inputStreamInfo.width * stream.height != inputStreamInfo.height * stream.width &&
mPostProcessorCore->isPostProcessTypeSupported(icamera::POST_PROCESS_CROP)) {
mPostProcessType |= icamera::POST_PROCESS_CROP;
info.type = icamera::POST_PROCESS_CROP;
info.inputInfo = inputStreamInfo;
// Caclulate the best crop size with same aspect ratio
if (inputStreamInfo.width * stream.height < inputStreamInfo.height * stream.width) {
info.outputInfo.width = info.inputInfo.width;
info.outputInfo.height = ALIGN(info.inputInfo.width * stream.height / stream.width, 2);
} else {
info.outputInfo.width = ALIGN(info.inputInfo.height * stream.width / stream.height, 2);
info.outputInfo.height = info.inputInfo.height;
}
info.outputInfo.format = inputStreamInfo.format;
info.outputInfo.stride = info.outputInfo.width;
info.outputInfo.size = icamera::CameraUtils::getFrameSize(
info.outputInfo.format, info.outputInfo.width, info.outputInfo.height);
LOG2("%s, Crop: input %dx%d, output: %dx%d", __func__, inputStreamInfo.width,
inputStreamInfo.height, info.outputInfo.width, info.outputInfo.height);
inputStreamInfo = info.outputInfo;
processingOrder.push_back(info);
}
// Scale
if ((uint32_t)inputStreamInfo.width * inputStreamInfo.height != stream.width * stream.height &&
mPostProcessorCore->isPostProcessTypeSupported(icamera::POST_PROCESS_SCALING)) {
mPostProcessType |= icamera::POST_PROCESS_SCALING;
info.type = icamera::POST_PROCESS_SCALING;
info.inputInfo = inputStreamInfo;
info.outputInfo.width = stream.width;
info.outputInfo.height = stream.height;
info.outputInfo.stride = stream.width;
info.outputInfo.format = inputStreamInfo.format;
info.outputInfo.size = icamera::CameraUtils::getFrameSize(
info.outputInfo.format, info.outputInfo.width, info.outputInfo.height);
LOG2("%s, Scale: input %dx%d, output: %dx%d", __func__, inputStreamInfo.width,
inputStreamInfo.height, info.outputInfo.width, info.outputInfo.height);
inputStreamInfo = info.outputInfo;
processingOrder.push_back(info);
}
// Convert
if (inputStreamInfo.format !=
HalV3Utils::HALFormatToV4l2Format(mCameraId, stream.format, stream.usage) &&
mPostProcessorCore->isPostProcessTypeSupported(icamera::POST_PROCESS_CONVERT)) {
mPostProcessType |= icamera::POST_PROCESS_CONVERT;
info.type = icamera::POST_PROCESS_CONVERT;
info.inputInfo = inputStreamInfo;
info.outputInfo.width = stream.width;
info.outputInfo.height = stream.height;
info.outputInfo.stride = stream.width;
info.outputInfo.format =
HalV3Utils::HALFormatToV4l2Format(mCameraId, stream.format, stream.usage);
info.outputInfo.size = icamera::CameraUtils::getFrameSize(
info.outputInfo.format, info.outputInfo.width, info.outputInfo.height);
LOG2("%s, Convert: input %dx%d, output: %dx%d", __func__, inputStreamInfo.width,
inputStreamInfo.height, info.outputInfo.width, info.outputInfo.height);
inputStreamInfo = info.outputInfo;
processingOrder.push_back(info);
}
// Encode
if (stream.format == HAL_PIXEL_FORMAT_BLOB &&
mPostProcessorCore->isPostProcessTypeSupported(icamera::POST_PROCESS_JPEG_ENCODING)) {
mPostProcessType |= icamera::POST_PROCESS_JPEG_ENCODING;
info.type = icamera::POST_PROCESS_JPEG_ENCODING;
info.inputInfo = inputStreamInfo;
info.outputInfo.width = stream.width;
info.outputInfo.height = stream.height;
info.outputInfo.stride = stream.width;
info.outputInfo.format =
HalV3Utils::HALFormatToV4l2Format(mCameraId, stream.format, stream.usage);
info.outputInfo.size = icamera::CameraUtils::getFrameSize(
info.outputInfo.format, info.outputInfo.width, info.outputInfo.height);
inputStreamInfo = info.outputInfo;
processingOrder.push_back(info);
}
if ((uint32_t)inputStreamInfo.width != stream.width ||
(uint32_t)inputStreamInfo.height != stream.height ||
inputStreamInfo.format !=
HalV3Utils::HALFormatToV4l2Format(mCameraId, stream.format, stream.usage)) {
LOGE("%s, stream info doesn't match between input and output stream.", __func__);
return icamera::UNKNOWN_ERROR;
}
LOG1("@%s, camera id %d, mPostProcessType %d, processing unit number: %zu", __func__, mCameraId,
mPostProcessType, processingOrder.size());
mPostProcessorCore->configure(processingOrder);
return icamera::OK;
}
icamera::status_t PostProcessor::doPostProcessing(const std::shared_ptr<Camera3Buffer>& inBuf,
const icamera::Parameters& parameter,
std::shared_ptr<Camera3Buffer> outBuf) {
return mPostProcessorCore->doPostProcessing(inBuf, parameter, outBuf);
}
} // namespace camera3