blob: 3511886bc288c7c8de044161c080c70e3c621968 [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_DualIrResultRequestProcessor"
#define ATRACE_TAG ATRACE_TAG_CAMERA
#include <log/log.h>
#include <utils/Trace.h>
#include <inttypes.h>
#include "dual_ir_result_request_processor.h"
#include "hal_utils.h"
namespace android {
namespace google_camera_hal {
std::unique_ptr<DualIrResultRequestProcessor>
DualIrResultRequestProcessor::Create(CameraDeviceSessionHwl* device_session_hwl,
const StreamConfiguration& stream_config,
uint32_t lead_camera_id) {
ATRACE_CALL();
if (device_session_hwl == nullptr) {
ALOGE("%s: device_session_hwl is nullptr.", __FUNCTION__);
return nullptr;
}
uint32_t camera_id = device_session_hwl->GetCameraId();
auto result_processor = std::unique_ptr<DualIrResultRequestProcessor>(
new DualIrResultRequestProcessor(stream_config, camera_id,
lead_camera_id));
if (result_processor == nullptr) {
ALOGE("%s: Creating DualIrResultRequestProcessor failed.", __FUNCTION__);
return nullptr;
}
return result_processor;
}
DualIrResultRequestProcessor::DualIrResultRequestProcessor(
const StreamConfiguration& stream_config, uint32_t logical_camera_id,
uint32_t lead_camera_id)
: kLogicalCameraId(logical_camera_id), kLeadCameraId(lead_camera_id) {
ATRACE_CALL();
// Initialize stream ID -> camera ID map based on framework's stream
// configuration.
for (auto& stream : stream_config.streams) {
if (stream.is_physical_camera_stream) {
stream_camera_ids_[stream.id] = stream.physical_camera_id;
} else {
stream_camera_ids_[stream.id] = kLogicalCameraId;
}
}
}
void DualIrResultRequestProcessor::SetResultCallback(
ProcessCaptureResultFunc process_capture_result, NotifyFunc notify) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(callback_lock_);
process_capture_result_ = process_capture_result;
notify_ = notify;
}
bool DualIrResultRequestProcessor::IsFrameworkPhyiscalStream(
int32_t stream_id, uint32_t* physical_camera_id) const {
ATRACE_CALL();
auto camera_id_iter = stream_camera_ids_.find(stream_id);
if (camera_id_iter == stream_camera_ids_.end()) {
ALOGE("%s: Cannot find camera ID for stream %u", __FUNCTION__, stream_id);
return false;
}
uint32_t camera_id = camera_id_iter->second;
if (camera_id == kLogicalCameraId) {
return false;
}
if (physical_camera_id != nullptr) {
*physical_camera_id = camera_id;
}
return true;
}
status_t DualIrResultRequestProcessor::AddPendingPhysicalCameraMetadata(
const ProcessBlockRequest& block_request,
std::map<uint32_t, std::unique_ptr<HalCameraMetadata>>* physical_metadata) {
ATRACE_CALL();
if (physical_metadata == nullptr) {
ALOGE("%s: physical_metadata is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
for (auto& buffer : block_request.request.output_buffers) {
uint32_t physical_camera_id;
if (IsFrameworkPhyiscalStream(buffer.stream_id, &physical_camera_id)) {
// Add physical_camera_id to physical_metadata.
(*physical_metadata)[physical_camera_id] = nullptr;
}
}
return OK;
}
status_t DualIrResultRequestProcessor::AddPendingRequests(
const std::vector<ProcessBlockRequest>& process_block_requests,
const CaptureRequest& remaining_session_request) {
ATRACE_CALL();
// This is the last result processor. Sanity check if requests contains
// all remaining output buffers.
if (!hal_utils::AreAllRemainingBuffersRequested(process_block_requests,
remaining_session_request)) {
ALOGE("%s: Some output buffers will not be completed.", __FUNCTION__);
return BAD_VALUE;
}
// Create new pending result metadata.
PendingResultMetadata pending_result_metadata;
for (auto& block_request : process_block_requests) {
status_t res = AddPendingPhysicalCameraMetadata(
block_request, &pending_result_metadata.physical_metadata);
if (res != OK) {
ALOGE("%s: Failed to fill pending physical camera metadata: %s(%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
}
uint32_t frame_number = process_block_requests[0].request.frame_number;
std::lock_guard<std::mutex> lock(pending_result_metadata_mutex_);
pending_result_metadata_[frame_number] = std::move(pending_result_metadata);
return OK;
}
void DualIrResultRequestProcessor::TrySendingResultMetadataLocked(
uint32_t frame_number) {
ATRACE_CALL();
auto pending_result_metadata_iter =
pending_result_metadata_.find(frame_number);
if (pending_result_metadata_iter == pending_result_metadata_.end()) {
ALOGE("%s: Can't find pending result for frame number %u", __FUNCTION__,
frame_number);
return;
}
// Check if we got result metadata from all cameras for this frame.
auto& pending_result_metadata = pending_result_metadata_iter->second;
if (pending_result_metadata.metadata == nullptr) {
// No metadata for logical camera yet.
return;
}
for (auto& [camera_id, metadata] : pending_result_metadata.physical_metadata) {
if (metadata == nullptr) {
// No metadata for this physical camera yet.
return;
}
}
// Prepare the result.
auto result = std::make_unique<CaptureResult>();
result->frame_number = frame_number;
result->partial_result = 1;
result->result_metadata = std::move(pending_result_metadata.metadata);
for (auto& [camera_id, metadata] : pending_result_metadata.physical_metadata) {
PhysicalCameraMetadata physical_metadata = {
.physical_camera_id = camera_id,
.metadata = std::move(metadata),
};
result->physical_metadata.push_back(std::move(physical_metadata));
}
process_capture_result_(std::move(result));
pending_result_metadata_.erase(pending_result_metadata_iter);
}
status_t DualIrResultRequestProcessor::ProcessResultMetadata(
uint32_t frame_number, uint32_t physical_camera_id,
std::unique_ptr<HalCameraMetadata> result_metadata) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(pending_result_metadata_mutex_);
auto pending_result_metadata_iter =
pending_result_metadata_.find(frame_number);
if (pending_result_metadata_iter == pending_result_metadata_.end()) {
ALOGE("%s: frame number %u is not expected.", __FUNCTION__, frame_number);
return BAD_VALUE;
}
auto& pending_result_metadata = pending_result_metadata_iter->second;
if (physical_camera_id == kLeadCameraId) {
if (pending_result_metadata.metadata != nullptr) {
ALOGE("%s: Already received metadata from camera %u for frame %u",
__FUNCTION__, physical_camera_id, frame_number);
return UNKNOWN_ERROR;
}
// Set lead camera id to multi camera metadata
std::string activePhysicalId = std::to_string(kLeadCameraId);
if (OK != result_metadata->Set(
ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID,
reinterpret_cast<const uint8_t*>(activePhysicalId.c_str()),
static_cast<uint32_t>(activePhysicalId.size() + 1))) {
ALOGE("Failure in setting active physical camera");
}
// Logical camera's result metadata is a clone of the lead camera's
// result metadata.
pending_result_metadata.metadata = std::move(result_metadata);
}
// Add the physical result metadata to pending result metadata if needed.
auto physical_metadata_iter =
pending_result_metadata.physical_metadata.find(physical_camera_id);
if (physical_metadata_iter != pending_result_metadata.physical_metadata.end()) {
// If the pending result metadata have physical metadata for a physical
// camera ID, the physical result metadata is needed.
if (physical_metadata_iter->second != nullptr) {
ALOGE("%s: Already received result metadata for camera %u for frame %u",
__FUNCTION__, physical_camera_id, frame_number);
return UNKNOWN_ERROR;
}
if (physical_camera_id == kLeadCameraId) {
// If this physical camera is the lead camera, clone the result metadata
// from the logical camera's result metadata.
physical_metadata_iter->second =
HalCameraMetadata::Clone(pending_result_metadata.metadata.get());
} else {
physical_metadata_iter->second = std::move(result_metadata);
}
}
TrySendingResultMetadataLocked(frame_number);
return OK;
}
void DualIrResultRequestProcessor::ProcessResult(ProcessBlockResult block_result) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(callback_lock_);
if (block_result.result == nullptr) {
ALOGW("%s: Received a nullptr result.", __FUNCTION__);
return;
}
if (process_capture_result_ == nullptr) {
ALOGE("%s: process_capture_result_ is nullptr. Dropping a result.",
__FUNCTION__);
return;
}
// Request ID is set to camera ID by DualIrRequestProcessor.
uint32_t camera_id = block_result.request_id;
// Process result metadata separately because there could be two result
// metadata (one from each camera).
auto result = std::move(block_result.result);
if (result->result_metadata != nullptr) {
status_t res = ProcessResultMetadata(result->frame_number, camera_id,
std::move(result->result_metadata));
if (res != OK) {
ALOGE("%s: Processing result metadata failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
// Continue processing rest of the result.
}
}
if (result->output_buffers.size() == 0) {
// No buffer to send out.
return;
}
process_capture_result_(std::move(result));
}
void DualIrResultRequestProcessor::Notify(
const ProcessBlockNotifyMessage& block_message) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(callback_lock_);
if (notify_ == nullptr) {
ALOGE("%s: notify_ is nullptr. Dropping a message.", __FUNCTION__);
return;
}
const NotifyMessage& message = block_message.message;
// Request ID is set to camera ID by DualIrRequestProcessor.
uint32_t camera_id = block_message.request_id;
if (message.type == MessageType::kShutter && camera_id != kLeadCameraId) {
// Only send out shutters from the lead camera.
return;
}
// TODO(b/129017376): if there are multiple requests for this frame, wait for
// all notification to arrive before calling process_capture_result_().
notify_(block_message.message);
}
status_t DualIrResultRequestProcessor::ConfigureStreams(
InternalStreamManager* /*internal_stream_manager*/,
const StreamConfiguration& /*stream_config*/,
StreamConfiguration* /*process_block_stream_config*/) {
ATRACE_CALL();
// TODO(b/131618554): Implement this function.
return INVALID_OPERATION;
}
status_t DualIrResultRequestProcessor::SetProcessBlock(
std::unique_ptr<ProcessBlock> /*process_block*/) {
ATRACE_CALL();
// TODO(b/131618554): Implement this function.
return INVALID_OPERATION;
}
status_t DualIrResultRequestProcessor::ProcessRequest(
const CaptureRequest& /*request*/) {
ATRACE_CALL();
// TODO(b/131618554): Implement this function.
return INVALID_OPERATION;
}
status_t DualIrResultRequestProcessor::Flush() {
ATRACE_CALL();
// TODO(b/131618554): Implement this function.
return INVALID_OPERATION;
}
status_t DualIrResultRequestProcessor::FlushPendingRequests() {
ATRACE_CALL();
return OK;
}
} // namespace google_camera_hal
} // namespace android