/* * 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 #include #include #include "dual_ir_result_request_processor.h" #include "hal_utils.h" namespace android { namespace google_camera_hal { std::unique_ptr 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( 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 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>* 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& 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 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(); 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 result_metadata) { ATRACE_CALL(); std::lock_guard 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(activePhysicalId.c_str()), static_cast(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 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 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 /*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