blob: b4f812178684a3504f3f76898fdcf690ff5da487 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* 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_NDEBUG 0
#define LOG_TAG "GCH_DepthProcessBlock"
#define ATRACE_TAG ATRACE_TAG_CAMERA
#include <cutils/properties.h>
#include <hardware/gralloc1.h>
#include <log/log.h>
#include <sys/mman.h>
#include <utils/Trace.h>
#include <dlfcn.h>
#include "depth_process_block.h"
#include "hal_types.h"
#include "hal_utils.h"
#include "result_processor.h"
namespace android {
namespace google_camera_hal {
#if GCH_HWL_USE_DLOPEN
static std::string kDepthGeneratorLib = "/vendor/lib64/libdepthgenerator.so";
using android::depth_generator::CreateDepthGenerator_t;
#endif
const float kSmallOffset = 0.01f;
std::unique_ptr<DepthProcessBlock> DepthProcessBlock::Create(
CameraDeviceSessionHwl* device_session_hwl,
HwlRequestBuffersFunc request_stream_buffers,
const DepthProcessBlockCreateData& create_data) {
ATRACE_CALL();
if (device_session_hwl == nullptr) {
ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
return nullptr;
}
auto block = std::unique_ptr<DepthProcessBlock>(
new DepthProcessBlock(request_stream_buffers, create_data));
if (block == nullptr) {
ALOGE("%s: Creating DepthProcessBlock failed.", __FUNCTION__);
return nullptr;
}
status_t res = block->InitializeBufferManagementStatus(device_session_hwl);
if (res != OK) {
ALOGE("%s: Failed to initialize HAL Buffer Management status.",
__FUNCTION__);
return nullptr;
}
res = block->CalculateActiveArraySizeRatio(device_session_hwl);
if (res != OK) {
ALOGE("%s: Calculating active array size ratio failed.", __FUNCTION__);
return nullptr;
}
// TODO(b/128633958): remove this after FLL syncing is verified
block->force_internal_stream_ =
property_get_bool("persist.vendor.camera.rgbird.forceinternal", false);
if (block->force_internal_stream_) {
ALOGI("%s: Force creating internal streams for IR pipelines", __FUNCTION__);
}
block->pipelined_depth_engine_enabled_ = property_get_bool(
"persist.vendor.camera.frontdepth.enablepipeline", true);
// TODO(b/129910835): Change the controlling prop into some deterministic
// logic that controls when the front depth autocal will be triggered.
// depth_process_block does not control autocal in current implementation.
// Whenever there is a YUV buffer in the process block request, it will
// trigger the AutoCal. So the condition is completely controlled by
// rt_request_processor and result_request_processor.
block->rgb_ir_auto_cal_enabled_ =
property_get_bool("vendor.camera.frontdepth.enableautocal", true);
return block;
}
status_t DepthProcessBlock::InitializeBufferManagementStatus(
CameraDeviceSessionHwl* device_session_hwl) {
// Query characteristics to check if buffer management supported
std::unique_ptr<google_camera_hal::HalCameraMetadata> characteristics;
status_t res = device_session_hwl->GetCameraCharacteristics(&characteristics);
if (res != OK) {
ALOGE("%s: Get camera characteristics failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return res;
}
camera_metadata_ro_entry entry = {};
res = characteristics->Get(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION,
&entry);
if (res == OK && entry.count > 0) {
buffer_management_supported_ =
(entry.data.u8[0] >=
ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
}
return OK;
}
DepthProcessBlock::DepthProcessBlock(
HwlRequestBuffersFunc request_stream_buffers,
const DepthProcessBlockCreateData& create_data)
: request_stream_buffers_(request_stream_buffers),
rgb_internal_yuv_stream_id_(create_data.rgb_internal_yuv_stream_id),
ir1_internal_raw_stream_id_(create_data.ir1_internal_raw_stream_id),
ir2_internal_raw_stream_id_(create_data.ir2_internal_raw_stream_id) {
}
DepthProcessBlock::~DepthProcessBlock() {
ATRACE_CALL();
depth_generator_ = nullptr;
if (depth_generator_lib_handle_ != nullptr) {
dlclose(depth_generator_lib_handle_);
depth_generator_lib_handle_ = nullptr;
}
}
status_t DepthProcessBlock::SetResultProcessor(
std::unique_ptr<ResultProcessor> result_processor) {
ATRACE_CALL();
if (result_processor == nullptr) {
ALOGE("%s: result_processor is nullptr", __FUNCTION__);
return BAD_VALUE;
}
std::lock_guard<std::mutex> lock(result_processor_lock_);
if (result_processor_ != nullptr) {
ALOGE("%s: result_processor_ was already set.", __FUNCTION__);
return ALREADY_EXISTS;
}
result_processor_ = std::move(result_processor);
return OK;
}
status_t DepthProcessBlock::GetStreamBufferSize(const Stream& stream,
int32_t* buffer_size) {
ATRACE_CALL();
// TODO(b/130764929): Use actual gralloc buffer stride instead of stream dim
switch (stream.format) {
case HAL_PIXEL_FORMAT_Y8:
*buffer_size = stream.width * stream.height;
break;
case HAL_PIXEL_FORMAT_Y16:
*buffer_size = stream.width * stream.height * 2;
break;
case HAL_PIXEL_FORMAT_YCBCR_420_888:
*buffer_size = static_cast<int32_t>(stream.width * stream.height * 1.5);
break;
default:
ALOGW("%s: Unsupported format:%d", __FUNCTION__, stream.format);
*buffer_size = 0;
break;
}
return OK;
}
status_t DepthProcessBlock::ConfigureStreams(
const StreamConfiguration& stream_config,
const StreamConfiguration& /*overall_config*/) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(configure_lock_);
if (is_configured_) {
ALOGE("%s: Already configured.", __FUNCTION__);
return ALREADY_EXISTS;
}
// TODO(b/128633958): remove this after FLL syncing is verified
if (force_internal_stream_) {
// Nothing to configure if this is force internal mode
ALOGV("%s: Force internal enabled, skip depth block config.", __FUNCTION__);
is_configured_ = true;
return OK;
}
uint32_t num_depth_stream = 0;
for (auto& stream : stream_config.streams) {
if (utils::IsDepthStream(stream)) {
num_depth_stream++;
// Save depth stream as HAL configured stream
depth_stream_.id = stream.id;
depth_stream_.override_format = stream.format;
depth_stream_.producer_usage = GRALLOC1_PRODUCER_USAGE_CAMERA;
depth_stream_.consumer_usage = 0;
depth_stream_.max_buffers = kDepthStreamMaxBuffers;
depth_stream_.override_data_space = stream.data_space;
depth_stream_.is_physical_camera_stream = false;
depth_stream_.physical_camera_id = 0;
}
// Save stream information for mapping purposes
depth_io_streams_[stream.id] = stream;
int32_t buffer_size = 0;
status_t res = GetStreamBufferSize(stream, &buffer_size);
if (res != OK) {
ALOGE("%s: Failed to get stream buffer size.", __FUNCTION__);
return res;
}
stream_buffer_sizes_[stream.id] = buffer_size;
}
if (num_depth_stream != 1) {
ALOGE(
"%s: Depth Process Block can only config 1 depth stream. There are "
"%zu streams, including %u depth stream.",
__FUNCTION__, stream_config.streams.size(), num_depth_stream);
return BAD_VALUE;
}
if (depth_generator_ == nullptr) {
status_t res = LoadDepthGenerator(&depth_generator_);
if (res != OK) {
ALOGE("%s: Creating DepthGenerator failed.", __FUNCTION__);
return NO_INIT;
}
if (pipelined_depth_engine_enabled_ == true) {
auto depth_result_callback =
android::depth_generator::DepthResultCallbackFunction(
[this](DepthResultStatus result_status, uint32_t frame_number) {
status_t res = ProcessDepthResult(result_status, frame_number);
if (res != OK) {
ALOGE("%s: Failed to process the depth result for frame %d.",
__FUNCTION__, frame_number);
}
});
ALOGI("%s: Async depth api is used. Callback func is set.", __FUNCTION__);
depth_generator_->SetResultCallback(depth_result_callback);
} else {
ALOGI("%s: Blocking depth api is used.", __FUNCTION__);
depth_generator_->SetResultCallback(nullptr);
}
}
is_configured_ = true;
return OK;
}
status_t DepthProcessBlock::GetConfiguredHalStreams(
std::vector<HalStream>* hal_streams) const {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(configure_lock_);
if (hal_streams == nullptr) {
ALOGE("%s: hal_streams is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
if (!is_configured_) {
ALOGE("%s: Not configured yet.", __FUNCTION__);
return NO_INIT;
}
hal_streams->push_back(depth_stream_);
return OK;
}
status_t DepthProcessBlock::SubmitBlockingDepthRequest(
const DepthRequestInfo& request_info) {
ALOGV("%s: [ud] ExecuteProcessRequest for frame %d", __FUNCTION__,
request_info.frame_number);
status_t res = depth_generator_->ExecuteProcessRequest(request_info);
if (res != OK) {
ALOGE("%s: Depth generator fails to process frame %d.", __FUNCTION__,
request_info.frame_number);
return res;
}
res = ProcessDepthResult(DepthResultStatus::kOk, request_info.frame_number);
if (res != OK) {
ALOGE("%s: Failed to process depth result.", __FUNCTION__);
return res;
}
return OK;
}
status_t DepthProcessBlock::SubmitAsyncDepthRequest(
const DepthRequestInfo& request_info) {
std::unique_lock<std::mutex> lock(depth_generator_api_lock_);
ALOGV("%s: [ud] ExecuteProcessRequest for frame %d", __FUNCTION__,
request_info.frame_number);
status_t res = depth_generator_->EnqueueProcessRequest(request_info);
if (res != OK) {
ALOGE("%s: Failed to enqueue depth request.", __FUNCTION__);
return res;
}
return OK;
}
status_t DepthProcessBlock::ProcessDepthResult(DepthResultStatus result_status,
uint32_t frame_number) {
std::unique_lock<std::mutex> lock(depth_generator_api_lock_);
ALOGV("%s: [ud] Depth result for frame %u notified.", __FUNCTION__,
frame_number);
status_t res = UnmapDepthRequestBuffers(frame_number);
if (res != OK) {
ALOGE("%s: Failed to clean up the depth request info.", __FUNCTION__);
return res;
}
auto capture_result = std::make_unique<CaptureResult>();
if (capture_result == nullptr) {
ALOGE("%s: Creating capture_result failed.", __FUNCTION__);
return NO_MEMORY;
}
CaptureRequest request;
{
std::lock_guard<std::mutex> pending_request_lock(pending_requests_mutex_);
if (pending_depth_requests_.find(frame_number) ==
pending_depth_requests_.end()) {
ALOGE("%s: Frame %u does not exist in pending requests list.",
__FUNCTION__, frame_number);
} else {
auto& request = pending_depth_requests_[frame_number].request;
capture_result->frame_number = frame_number;
capture_result->output_buffers = request.output_buffers;
// In case the depth engine fails to process a depth request, mark the
// buffer as in error state.
if (result_status != DepthResultStatus::kOk) {
for (auto& stream_buffer : capture_result->output_buffers) {
if (stream_buffer.stream_id == depth_stream_.id) {
stream_buffer.status = BufferStatus::kError;
}
}
}
capture_result->input_buffers = request.input_buffers;
pending_depth_requests_.erase(frame_number);
}
}
ProcessBlockResult block_result = {.request_id = 0,
.result = std::move(capture_result)};
{
std::lock_guard<std::mutex> lock(result_processor_lock_);
result_processor_->ProcessResult(std::move(block_result));
}
return OK;
}
status_t DepthProcessBlock::ProcessRequests(
const std::vector<ProcessBlockRequest>& process_block_requests,
const CaptureRequest& remaining_session_request) {
ATRACE_CALL();
// TODO(b/128633958): remove this after FLL syncing is verified
if (force_internal_stream_) {
// Nothing to configure if this is force internal mode
ALOGE("%s: Force internal ON, Depth PB should not process request.",
__FUNCTION__);
return UNKNOWN_ERROR;
}
std::lock_guard<std::mutex> lock(configure_lock_);
if (!is_configured_) {
ALOGE("%s: block is not configured.", __FUNCTION__);
return NO_INIT;
}
if (process_block_requests.size() != 1) {
ALOGE("%s: Only a single request is supported but there are %zu",
__FUNCTION__, process_block_requests.size());
return BAD_VALUE;
}
{
std::lock_guard<std::mutex> lock(result_processor_lock_);
if (result_processor_ == nullptr) {
ALOGE("%s: result processor was not set.", __FUNCTION__);
return NO_INIT;
}
status_t res = result_processor_->AddPendingRequests(
process_block_requests, remaining_session_request);
if (res != OK) {
ALOGE("%s: Adding a pending request to result processor failed: %s(%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
}
auto& request = process_block_requests[0].request;
DepthRequestInfo request_info;
request_info.frame_number = request.frame_number;
std::unique_ptr<HalCameraMetadata> metadata = nullptr;
if (request.settings != nullptr) {
metadata = HalCameraMetadata::Clone(request.settings.get());
}
std::unique_ptr<HalCameraMetadata> color_metadata = nullptr;
for (auto& metadata : request.input_buffer_metadata) {
if (metadata != nullptr) {
color_metadata = HalCameraMetadata::Clone(metadata.get());
}
}
ALOGV("%s: [ud] Prepare depth request info for frame %u .", __FUNCTION__,
request.frame_number);
status_t res = PrepareDepthRequestInfo(request, &request_info, metadata.get(),
color_metadata.get());
if (res != OK) {
ALOGE("%s: Failed to perpare the depth request info.", __FUNCTION__);
return res;
}
if (pipelined_depth_engine_enabled_ == true) {
res = SubmitAsyncDepthRequest(request_info);
if (res != OK) {
ALOGE("%s: Failed to submit asynchronized depth request.", __FUNCTION__);
}
} else {
res = SubmitBlockingDepthRequest(request_info);
if (res != OK) {
ALOGE("%s: Failed to submit blocking depth request.", __FUNCTION__);
}
}
return OK;
}
status_t DepthProcessBlock::Flush() {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(configure_lock_);
if (!is_configured_) {
return OK;
}
// TODO(b/127322570): Implement this method.
return OK;
}
status_t DepthProcessBlock::LoadDepthGenerator(
std::unique_ptr<DepthGenerator>* depth_generator) {
ATRACE_CALL();
#if GCH_HWL_USE_DLOPEN
CreateDepthGenerator_t create_depth_generator;
ALOGI("%s: Loading library: %s", __FUNCTION__, kDepthGeneratorLib.c_str());
depth_generator_lib_handle_ =
dlopen(kDepthGeneratorLib.c_str(), RTLD_NOW | RTLD_NODELETE);
if (depth_generator_lib_handle_ == nullptr) {
ALOGE("Depth generator loading %s failed.", kDepthGeneratorLib.c_str());
return NO_INIT;
}
create_depth_generator = (CreateDepthGenerator_t)dlsym(
depth_generator_lib_handle_, "CreateDepthGenerator");
if (create_depth_generator == nullptr) {
ALOGE("%s: dlsym failed (%s).", __FUNCTION__, kDepthGeneratorLib.c_str());
dlclose(depth_generator_lib_handle_);
depth_generator_lib_handle_ = nullptr;
return NO_INIT;
}
*depth_generator = std::unique_ptr<DepthGenerator>(create_depth_generator());
if (*depth_generator == nullptr) {
return NO_INIT;
}
#else
if (CreateDepthGenerator == nullptr) {
return NO_INIT;
}
*depth_generator = std::unique_ptr<DepthGenerator>(CreateDepthGenerator());
#endif
return OK;
}
status_t DepthProcessBlock::MapBuffersForDepthGenerator(
const StreamBuffer& stream_buffer, depth_generator::Buffer* buffer) {
ATRACE_CALL();
buffer_handle_t buffer_handle = stream_buffer.buffer;
ALOGV("%s: Mapping FD=%d to CPU addr.", __FUNCTION__, buffer_handle->data[0]);
int32_t stream_id = stream_buffer.stream_id;
if (stream_buffer_sizes_.find(stream_id) == stream_buffer_sizes_.end() ||
depth_io_streams_.find(stream_id) == depth_io_streams_.end()) {
ALOGE("%s: Stream buffer stream id:%d not found.", __FUNCTION__, stream_id);
return UNKNOWN_ERROR;
}
void* virtual_addr =
mmap(NULL, stream_buffer_sizes_[stream_id], (PROT_READ | PROT_WRITE),
MAP_SHARED, buffer_handle->data[0], 0);
if (virtual_addr == nullptr || virtual_addr == reinterpret_cast<void*>(-1)) {
ALOGE("%s: Failed to map the stream buffer to virtual addr.", __FUNCTION__);
return UNKNOWN_ERROR;
}
auto& stream = depth_io_streams_[stream_id];
buffer->format = stream.format;
buffer->width = stream.width;
buffer->height = stream.height;
depth_generator::BufferPlane buffer_plane = {};
buffer_plane.addr = reinterpret_cast<uint8_t*>(virtual_addr);
// TODO(b/130764929): Use actual gralloc buffer stride instead of stream dim
buffer_plane.stride = stream.width;
buffer_plane.scanline = stream.height;
buffer->planes.push_back(buffer_plane);
return OK;
}
status_t DepthProcessBlock::UnmapBuffersForDepthGenerator(
const StreamBuffer& stream_buffer, uint8_t* addr) {
ATRACE_CALL();
if (addr == nullptr) {
ALOGE("%s: Addr is null.", __FUNCTION__);
return BAD_VALUE;
}
int32_t stream_id = stream_buffer.stream_id;
if (stream_buffer_sizes_.find(stream_id) == stream_buffer_sizes_.end() ||
depth_io_streams_.find(stream_id) == depth_io_streams_.end()) {
ALOGE("%s: Stream buffer stream id:%d not found.", __FUNCTION__, stream_id);
return UNKNOWN_ERROR;
}
munmap(addr, stream_buffer_sizes_[stream_id]);
return OK;
}
status_t DepthProcessBlock::RequestDepthStreamBuffer(
StreamBuffer* incomplete_buffer, uint32_t frame_number) {
if (!buffer_management_supported_) {
return OK;
}
if (request_stream_buffers_ == nullptr) {
ALOGE("%s: request_stream_buffers_ is nullptr", __FUNCTION__);
return UNKNOWN_ERROR;
}
std::vector<StreamBuffer> buffers;
{
status_t res = request_stream_buffers_(
incomplete_buffer->stream_id,
/* request one depth buffer each time */ 1, &buffers, frame_number);
if (res != OK) {
ALOGE("%s: Failed to request stream buffers from camera device session.",
__FUNCTION__);
return UNKNOWN_ERROR;
}
}
*incomplete_buffer = buffers[0];
return OK;
}
status_t DepthProcessBlock::UpdateCropRegion(const CaptureRequest& request,
DepthRequestInfo* depth_request_info,
HalCameraMetadata* metadata) {
if (request.settings != nullptr && metadata != nullptr) {
camera_metadata_ro_entry_t entry_crop_region_user = {};
if (request.settings->Get(ANDROID_SCALER_CROP_REGION,
&entry_crop_region_user) == OK) {
const int32_t* crop_region = entry_crop_region_user.data.i32;
ALOGV("%s: Depth PB crop region[%d %d %d %d]", __FUNCTION__,
crop_region[0], crop_region[1], crop_region[2], crop_region[3]);
int32_t resized_crop_region[4] = {};
// top
resized_crop_region[0] = crop_region[1] / logical_to_ir_ratio_;
if (resized_crop_region[0] < 0) {
resized_crop_region[0] = 0;
}
// left
resized_crop_region[1] = crop_region[0] / logical_to_ir_ratio_;
if (resized_crop_region[1] < 0) {
resized_crop_region[1] = 0;
}
// bottom
resized_crop_region[2] =
(crop_region[3] / logical_to_ir_ratio_) + resized_crop_region[0];
if (resized_crop_region[2] > ir_active_array_height_) {
resized_crop_region[2] = ir_active_array_height_;
}
// right
resized_crop_region[3] =
(crop_region[2] / logical_to_ir_ratio_) + resized_crop_region[1];
if (resized_crop_region[3] > ir_active_array_width_) {
resized_crop_region[3] = ir_active_array_width_;
}
metadata->Set(ANDROID_SCALER_CROP_REGION, resized_crop_region,
sizeof(resized_crop_region) / sizeof(int32_t));
depth_request_info->settings = metadata->GetRawCameraMetadata();
}
}
return OK;
}
status_t DepthProcessBlock::MapDepthRequestBuffers(
const CaptureRequest& request, DepthRequestInfo* depth_request_info) {
status_t res = OK;
depth_request_info->ir_buffer.resize(2);
for (auto& input_buffer : request.input_buffers) {
// If the stream id is invalid. The input buffer is only a place holder
// corresponding to the input buffer metadata for the rgb pipeline.
if (input_buffer.stream_id == kInvalidStreamId) {
ALOGV("%s: Skipping input buffer place holder for frame %u.",
__FUNCTION__, depth_request_info->frame_number);
continue;
}
depth_generator::Buffer buffer = {};
res = MapBuffersForDepthGenerator(input_buffer, &buffer);
if (res != OK) {
ALOGE("%s: Mapping buffer for depth generator failed.", __FUNCTION__);
return UNKNOWN_ERROR;
}
const int32_t stream_id = input_buffer.stream_id;
if (stream_id == rgb_internal_yuv_stream_id_) {
// TODO(b/129910835): Triggering Condition
// Adjust the condition according to how rt_request_processor and
// result_request_processor handles the triggering condition. If they have
// full control of the logic and decide to pass yuv buffer only when
// autocal should be triggered, then the logic here can be as simple as
// this.
depth_request_info->color_buffer.push_back(buffer);
} else if (stream_id == ir1_internal_raw_stream_id_) {
depth_request_info->ir_buffer[0].push_back(buffer);
} else if (stream_id == ir2_internal_raw_stream_id_) {
depth_request_info->ir_buffer[1].push_back(buffer);
}
}
res = MapBuffersForDepthGenerator(request.output_buffers[0],
&depth_request_info->depth_buffer);
if (res != OK) {
ALOGE("%s: Mapping depth buffer for depth generator failed.", __FUNCTION__);
return UNKNOWN_ERROR;
}
return OK;
}
status_t DepthProcessBlock::PrepareDepthRequestInfo(
const CaptureRequest& request, DepthRequestInfo* depth_request_info,
HalCameraMetadata* metadata, const HalCameraMetadata* color_metadata) {
ATRACE_CALL();
if (depth_request_info == nullptr) {
ALOGE("%s: depth_request_info is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
status_t res = UpdateCropRegion(request, depth_request_info, metadata);
if (res != OK) {
ALOGE("%s: Failed to update crop region.", __FUNCTION__);
return UNKNOWN_ERROR;
}
if (color_metadata != nullptr) {
depth_request_info->color_buffer_metadata =
color_metadata->GetRawCameraMetadata();
}
if (request.input_buffers.size() < 2 || request.input_buffers.size() > 3 ||
request.output_buffers.size() != 1) {
ALOGE(
"%s: Cannot prepare request info, input buffer size is not 2 or 3(is"
" %zu) or output buffer size is not 1(is %zu).",
__FUNCTION__, request.input_buffers.size(),
request.output_buffers.size());
return BAD_VALUE;
}
if (buffer_management_supported_) {
res = RequestDepthStreamBuffer(
&(const_cast<CaptureRequest&>(request).output_buffers[0]),
request.frame_number);
if (res != OK) {
ALOGE("%s: Failed to request depth stream buffer.", __FUNCTION__);
return UNKNOWN_ERROR;
}
}
res = MapDepthRequestBuffers(request, depth_request_info);
if (res != OK) {
ALOGE("%s: Failed to map buffers for depth request.", __FUNCTION__);
return UNKNOWN_ERROR;
}
{
uint32_t frame_number = request.frame_number;
std::lock_guard<std::mutex> lock(pending_requests_mutex_);
if (pending_depth_requests_.find(frame_number) !=
pending_depth_requests_.end()) {
ALOGE("%s: Frame %u already exists in pending requests.", __FUNCTION__,
request.frame_number);
return UNKNOWN_ERROR;
} else {
pending_depth_requests_[frame_number] = {};
auto& pending_request = pending_depth_requests_[frame_number].request;
pending_request.frame_number = frame_number;
pending_request.input_buffers = request.input_buffers;
pending_request.output_buffers = request.output_buffers;
auto& pending_depth_request =
pending_depth_requests_[frame_number].depth_request;
pending_depth_request = *depth_request_info;
}
}
return OK;
}
status_t DepthProcessBlock::UnmapDepthRequestBuffers(uint32_t frame_number) {
std::lock_guard<std::mutex> lock(pending_requests_mutex_);
if (pending_depth_requests_.find(frame_number) ==
pending_depth_requests_.end()) {
ALOGE("%s: Can not find frame %u in pending requests list.", __FUNCTION__,
frame_number);
return BAD_VALUE;
}
auto& request = pending_depth_requests_[frame_number].request;
auto& depth_request_info = pending_depth_requests_[frame_number].depth_request;
ATRACE_CALL();
if (request.input_buffers.size() < 2 || request.input_buffers.size() > 3 ||
request.output_buffers.size() != 1) {
ALOGE(
"%s: Cannot prepare request info, input buffer size is not 2 or 3(is "
"%zu) or output buffer size is not 1(is %zu).",
__FUNCTION__, request.input_buffers.size(),
request.output_buffers.size());
return BAD_VALUE;
}
status_t res = OK;
for (auto& input_buffer : request.input_buffers) {
uint8_t* addr = nullptr;
int32_t stream_id = input_buffer.stream_id;
if (stream_id == kInvalidStreamId) {
ALOGV("%s: input buffer place holder found for frame %u", __FUNCTION__,
frame_number);
continue;
}
if (stream_id == rgb_internal_yuv_stream_id_) {
addr = depth_request_info.color_buffer[0].planes[0].addr;
} else if (stream_id == ir1_internal_raw_stream_id_) {
addr = depth_request_info.ir_buffer[0][0].planes[0].addr;
} else if (stream_id == ir2_internal_raw_stream_id_) {
addr = depth_request_info.ir_buffer[1][0].planes[0].addr;
}
res = UnmapBuffersForDepthGenerator(input_buffer, addr);
if (res != OK) {
ALOGE("%s: Unmapping input buffer for depth generator failed.",
__FUNCTION__);
return UNKNOWN_ERROR;
}
}
res = UnmapBuffersForDepthGenerator(
request.output_buffers[0], depth_request_info.depth_buffer.planes[0].addr);
if (res != OK) {
ALOGE("%s: Unmapping depth buffer for depth generator failed.",
__FUNCTION__);
return UNKNOWN_ERROR;
}
return OK;
}
status_t DepthProcessBlock::CalculateActiveArraySizeRatio(
CameraDeviceSessionHwl* device_session_hwl) {
std::unique_ptr<HalCameraMetadata> characteristics;
status_t res = device_session_hwl->GetCameraCharacteristics(&characteristics);
if (res != OK) {
ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
return UNKNOWN_ERROR;
}
uint32_t active_array_width = 0;
uint32_t active_array_height = 0;
camera_metadata_ro_entry entry;
res = characteristics->Get(
ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &entry);
if (res == OK) {
active_array_width = entry.data.i32[2];
active_array_height = entry.data.i32[3];
ALOGI("%s Active size (%d x %d).", __FUNCTION__, active_array_width,
active_array_height);
} else {
ALOGE("%s Get active size failed: %s (%d).", __FUNCTION__, strerror(-res),
res);
return UNKNOWN_ERROR;
}
std::vector<uint32_t> physical_camera_ids =
device_session_hwl->GetPhysicalCameraIds();
if (physical_camera_ids.size() != 3) {
ALOGE("%s: Only support 3 cameras", __FUNCTION__);
return UNKNOWN_ERROR;
}
uint32_t ir_active_array_width = 0;
uint32_t ir_active_array_height = 0;
std::unique_ptr<HalCameraMetadata> ir_characteristics;
for (auto camera_id : physical_camera_ids) {
res = device_session_hwl->GetPhysicalCameraCharacteristics(
camera_id, &ir_characteristics);
if (res != OK) {
ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
return UNKNOWN_ERROR;
}
// assuming both IR camera are of the same size
if (hal_utils::IsIrCamera(ir_characteristics.get())) {
camera_metadata_ro_entry entry;
res = ir_characteristics->Get(
ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &entry);
if (res == OK) {
ir_active_array_width = entry.data.i32[2];
ir_active_array_height = entry.data.i32[3];
ALOGI("%s IR active size (%dx%d).", __FUNCTION__, ir_active_array_width,
ir_active_array_height);
} else {
ALOGE("%s Get ir active size failed: %s (%d).", __FUNCTION__,
strerror(-res), res);
return UNKNOWN_ERROR;
}
break;
}
}
if (active_array_width == 0 || active_array_height == 0 ||
ir_active_array_width == 0 || ir_active_array_height == 0) {
ALOGE(
"%s: One dimension of the logical camera active array size or the "
"IR camera active array size is 0.",
__FUNCTION__);
return INVALID_OPERATION;
}
float logical_aspect_ratio = 1.0;
float ir_aspect_ratio = 1.0;
if (active_array_width > active_array_height) {
logical_aspect_ratio = active_array_width / active_array_height;
ir_aspect_ratio = ir_active_array_width / ir_active_array_height;
} else {
logical_aspect_ratio = active_array_height / active_array_width;
ir_aspect_ratio = ir_active_array_height / ir_active_array_width;
}
ir_active_array_height_ = ir_active_array_height;
ir_active_array_width_ = ir_active_array_width;
float aspect_ratio_diff = logical_aspect_ratio - ir_aspect_ratio;
if (aspect_ratio_diff > kSmallOffset || aspect_ratio_diff < -kSmallOffset) {
ALOGE(
"%s: Logical camera aspect ratio and IR camera aspect ratio are "
"different from each other.",
__FUNCTION__);
return UNKNOWN_ERROR;
}
logical_to_ir_ratio_ = float(active_array_height) / ir_active_array_height;
ALOGI("%s: logical_to_ir_ratio_ = %f", __FUNCTION__, logical_to_ir_ratio_);
return OK;
}
} // namespace google_camera_hal
} // namespace android