/* * 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_BasicCaptureSession" #define ATRACE_TAG ATRACE_TAG_CAMERA #include "basic_capture_session.h" #include #include #include "basic_request_processor.h" #include "basic_result_processor.h" #include "hal_types.h" #include "realtime_process_block.h" namespace android { namespace google_camera_hal { bool BasicCaptureSession::IsStreamConfigurationSupported( CameraDeviceSessionHwl* device_session_hwl, const StreamConfiguration& /*stream_config*/) { ATRACE_CALL(); if (device_session_hwl == nullptr) { ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__); return false; } ALOGD("%s: BasicCaptureSession supports the stream config", __FUNCTION__); return true; } std::unique_ptr BasicCaptureSession::Create( CameraDeviceSessionHwl* device_session_hwl, const StreamConfiguration& stream_config, ProcessCaptureResultFunc process_capture_result, ProcessBatchCaptureResultFunc process_batch_capture_result, NotifyFunc notify, HwlSessionCallback /*session_callback*/, std::vector* hal_configured_streams, CameraBufferAllocatorHwl* /*camera_allocator_hwl*/) { ATRACE_CALL(); auto session = std::unique_ptr(new BasicCaptureSession()); if (session == nullptr) { ALOGE("%s: Creating BasicCaptureSession failed.", __FUNCTION__); return nullptr; } status_t res = session->Initialize( device_session_hwl, stream_config, process_capture_result, process_batch_capture_result, notify, hal_configured_streams); if (res != OK) { ALOGE("%s: Initializing BasicCaptureSession failed: %s (%d).", __FUNCTION__, strerror(-res), res); return nullptr; } return session; } BasicCaptureSession::~BasicCaptureSession() { if (device_session_hwl_ != nullptr) { device_session_hwl_->DestroyPipelines(); } } status_t BasicCaptureSession::ConfigureStreams( const StreamConfiguration& stream_config, RequestProcessor* request_processor, ProcessBlock* process_block) { ATRACE_CALL(); if (request_processor == nullptr || process_block == nullptr) { ALOGE("%s: request_processor (%p) or process_block (%p) is nullptr", __FUNCTION__, request_processor, process_block); return BAD_VALUE; } // Configure streams for request processor StreamConfiguration process_block_stream_config; status_t res = request_processor->ConfigureStreams( internal_stream_manager_.get(), stream_config, &process_block_stream_config); if (res != OK) { ALOGE("%s: Configuring stream for request processor failed.", __FUNCTION__); return res; } // Check all streams are configured. if (stream_config.streams.size() != process_block_stream_config.streams.size()) { ALOGE("%s: stream_config has %zu streams but only configured %zu streams", __FUNCTION__, stream_config.streams.size(), process_block_stream_config.streams.size()); return UNKNOWN_ERROR; } for (auto& stream : stream_config.streams) { bool found = false; for (auto& configured_stream : process_block_stream_config.streams) { if (stream.id == configured_stream.id) { found = true; break; } } if (!found) { ALOGE("%s: Cannot find stream %u in configured streams.", __FUNCTION__, stream.id); return UNKNOWN_ERROR; } } // Configure streams for process block. res = process_block->ConfigureStreams(process_block_stream_config, stream_config); if (res != OK) { ALOGE("%s: Configuring stream for process block failed.", __FUNCTION__); return res; } return OK; } status_t BasicCaptureSession::BuildPipelines( ProcessBlock* process_block, std::vector* hal_configured_streams) { ATRACE_CALL(); if (process_block == nullptr || hal_configured_streams == nullptr) { ALOGE("%s: process_block (%p) or hal_configured_streams (%p) is nullptr", __FUNCTION__, process_block, hal_configured_streams); return BAD_VALUE; } status_t res = device_session_hwl_->BuildPipelines(); if (res != OK) { ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } res = process_block->GetConfiguredHalStreams(hal_configured_streams); if (res != OK) { ALOGE("%s: Getting HAL streams failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } return OK; } status_t BasicCaptureSession::ConnectProcessChain( RequestProcessor* request_processor, std::unique_ptr process_block, std::unique_ptr result_processor) { ATRACE_CALL(); if (request_processor == nullptr) { ALOGE("%s: request_processor is nullptr", __FUNCTION__); return BAD_VALUE; } status_t res = process_block->SetResultProcessor(std::move(result_processor)); if (res != OK) { ALOGE("%s: Setting result process in process block failed.", __FUNCTION__); return res; } res = request_processor->SetProcessBlock(std::move(process_block)); if (res != OK) { ALOGE("%s: Setting process block for BasicRequestProcessor failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } return OK; } status_t BasicCaptureSession::Initialize( CameraDeviceSessionHwl* device_session_hwl, const StreamConfiguration& stream_config, ProcessCaptureResultFunc process_capture_result, ProcessBatchCaptureResultFunc process_batch_capture_result, NotifyFunc notify, std::vector* hal_configured_streams) { ATRACE_CALL(); if (!IsStreamConfigurationSupported(device_session_hwl, stream_config)) { ALOGE("%s: stream configuration is not supported.", __FUNCTION__); return BAD_VALUE; } device_session_hwl_ = device_session_hwl; internal_stream_manager_ = InternalStreamManager::Create(); if (internal_stream_manager_ == nullptr) { ALOGE("%s: Cannot create internal stream manager.", __FUNCTION__); return UNKNOWN_ERROR; } std::unique_ptr characteristics; uint32_t partial_result_count = 1; status_t res = device_session_hwl->GetCameraCharacteristics(&characteristics); if (res != OK) { ALOGE("GetCameraCharacteristics failed"); return BAD_VALUE; } camera_metadata_ro_entry partial_result_entry; res = characteristics->Get(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partial_result_entry); if (res == OK) { partial_result_count = partial_result_entry.data.i32[0]; } // Create result dispatcher. std::string result_dispatcher_name = "Cam" + std::to_string(device_session_hwl_->GetCameraId()) + "_ResultDispatcher"; result_dispatcher_ = ResultDispatcher::Create(partial_result_count, process_capture_result, process_batch_capture_result, notify, stream_config, result_dispatcher_name); if (result_dispatcher_ == nullptr) { ALOGE("Creating ResultDispatcher failed"); return UNKNOWN_ERROR; } // Create result processor. auto result_processor = BasicResultProcessor::Create(); if (result_processor == nullptr) { ALOGE("%s: Creating BasicResultProcessor failed.", __FUNCTION__); return UNKNOWN_ERROR; } auto process_capture_result_cb = [this](std::unique_ptr result) { ProcessCaptureResult(std::move(result)); }; auto notify_cb = [this](const NotifyMessage& message) { Notify(message); }; auto process_batch_capture_result_cb = [this](std::vector> results) { ProcessBatchCaptureResult(std::move(results)); }; result_processor->SetResultCallback(process_capture_result_cb, notify_cb, process_batch_capture_result_cb); // Create process block. auto process_block = RealtimeProcessBlock::Create(device_session_hwl_); if (process_block == nullptr) { ALOGE("%s: Creating RealtimeProcessBlock failed.", __FUNCTION__); return UNKNOWN_ERROR; } // Create request processor. request_processor_ = BasicRequestProcessor::Create(device_session_hwl_); if (request_processor_ == nullptr) { ALOGE("%s: Creating BasicRequestProcessor failed.", __FUNCTION__); return UNKNOWN_ERROR; } res = ConfigureStreams(stream_config, request_processor_.get(), process_block.get()); if (res != OK) { ALOGE("%s: Configuring stream failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } res = BuildPipelines(process_block.get(), hal_configured_streams); if (res != OK) { ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } res = ConnectProcessChain(request_processor_.get(), std::move(process_block), std::move(result_processor)); if (res != OK) { ALOGE("%s: Connecting process chain failed: %s(%d)", __FUNCTION__, strerror(-res), res); return res; } return OK; } status_t BasicCaptureSession::ProcessRequest(const CaptureRequest& request) { ATRACE_CALL(); result_dispatcher_->AddPendingRequest(request); return request_processor_->ProcessRequest(request); } status_t BasicCaptureSession::Flush() { ATRACE_CALL(); return request_processor_->Flush(); } void BasicCaptureSession::ProcessCaptureResult( std::unique_ptr result) { result_dispatcher_->AddResult(std::move(result)); } void BasicCaptureSession::Notify(const NotifyMessage& message) { if (message.type == MessageType::kShutter) { result_dispatcher_->AddShutter(message.message.shutter.frame_number, message.message.shutter.timestamp_ns, message.message.shutter.readout_timestamp_ns); } else { result_dispatcher_->AddError(message.message.error); } } void BasicCaptureSession::ProcessBatchCaptureResult( std::vector> results) { result_dispatcher_->AddBatchResult(std::move(results)); } } // namespace google_camera_hal } // namespace android