| /* |
| * 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_RgbirdResultRequestProcessor" |
| #define ATRACE_TAG ATRACE_TAG_CAMERA |
| #include <cutils/properties.h> |
| #include <log/log.h> |
| #include <sync/sync.h> |
| #include <utils/Trace.h> |
| |
| #include <cutils/native_handle.h> |
| #include <inttypes.h> |
| |
| #include "hal_utils.h" |
| #include "rgbird_result_request_processor.h" |
| |
| namespace android { |
| namespace google_camera_hal { |
| |
| std::unique_ptr<RgbirdResultRequestProcessor> RgbirdResultRequestProcessor::Create( |
| const RgbirdResultRequestProcessorCreateData& create_data) { |
| ATRACE_CALL(); |
| auto result_processor = std::unique_ptr<RgbirdResultRequestProcessor>( |
| new RgbirdResultRequestProcessor(create_data)); |
| if (result_processor == nullptr) { |
| ALOGE("%s: Creating RgbirdResultRequestProcessor failed.", __FUNCTION__); |
| return nullptr; |
| } |
| |
| // TODO(b/128633958): remove this after FLL syncing is verified |
| result_processor->force_internal_stream_ = |
| property_get_bool("persist.vendor.camera.rgbird.forceinternal", false); |
| if (result_processor->force_internal_stream_) { |
| ALOGI("%s: Force creating internal streams for IR pipelines", __FUNCTION__); |
| } |
| |
| // TODO(b/129910835): Change the controlling prop into some deterministic |
| // logic that controls when the front depth autocal will be triggered. |
| result_processor->rgb_ir_auto_cal_enabled_ = |
| property_get_bool("vendor.camera.frontdepth.enableautocal", true); |
| if (result_processor->rgb_ir_auto_cal_enabled_) { |
| ALOGI("%s: autocal is enabled.", __FUNCTION__); |
| } |
| |
| return result_processor; |
| } |
| |
| RgbirdResultRequestProcessor::RgbirdResultRequestProcessor( |
| const RgbirdResultRequestProcessorCreateData& create_data) |
| : kRgbCameraId(create_data.rgb_camera_id), |
| kIr1CameraId(create_data.ir1_camera_id), |
| kIr2CameraId(create_data.ir2_camera_id), |
| rgb_raw_stream_id_(create_data.rgb_raw_stream_id), |
| is_hdrplus_supported_(create_data.is_hdrplus_supported), |
| rgb_internal_yuv_stream_id_(create_data.rgb_internal_yuv_stream_id) { |
| } |
| |
| void RgbirdResultRequestProcessor::SetResultCallback( |
| ProcessCaptureResultFunc process_capture_result, NotifyFunc notify) { |
| std::lock_guard<std::mutex> lock(callback_lock_); |
| process_capture_result_ = process_capture_result; |
| notify_ = notify; |
| } |
| |
| void RgbirdResultRequestProcessor::SaveFdForHdrplus( |
| const CaptureRequest& request) { |
| // Enable face detect mode for internal use |
| if (request.settings != nullptr) { |
| uint8_t fd_mode; |
| status_t res = hal_utils::GetFdMode(request, &fd_mode); |
| if (res == OK) { |
| current_face_detect_mode_ = fd_mode; |
| } |
| } |
| |
| { |
| std::lock_guard<std::mutex> lock(face_detect_lock_); |
| requested_face_detect_modes_.emplace(request.frame_number, |
| current_face_detect_mode_); |
| } |
| } |
| |
| void RgbirdResultRequestProcessor::SaveLsForHdrplus( |
| const CaptureRequest& request) { |
| if (request.settings != nullptr) { |
| uint8_t lens_shading_map_mode; |
| status_t res = |
| hal_utils::GetLensShadingMapMode(request, &lens_shading_map_mode); |
| if (res == OK) { |
| current_lens_shading_map_mode_ = lens_shading_map_mode; |
| } |
| } |
| |
| { |
| std::lock_guard<std::mutex> lock(lens_shading_lock_); |
| requested_lens_shading_map_modes_.emplace(request.frame_number, |
| current_lens_shading_map_mode_); |
| } |
| } |
| |
| status_t RgbirdResultRequestProcessor::HandleLsResultForHdrplus( |
| uint32_t frameNumber, HalCameraMetadata* metadata) { |
| if (metadata == nullptr) { |
| ALOGE("%s: metadata is nullptr", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| std::lock_guard<std::mutex> lock(lens_shading_lock_); |
| auto iter = requested_lens_shading_map_modes_.find(frameNumber); |
| if (iter == requested_lens_shading_map_modes_.end()) { |
| ALOGW("%s: can't find frame (%d)", __FUNCTION__, frameNumber); |
| return OK; |
| } |
| |
| if (iter->second == ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF) { |
| status_t res = hal_utils::RemoveLsInfoFromResult(metadata); |
| if (res != OK) { |
| ALOGW("%s: RemoveLsInfoFromResult fail", __FUNCTION__); |
| } |
| } |
| requested_lens_shading_map_modes_.erase(iter); |
| |
| return OK; |
| } |
| |
| bool RgbirdResultRequestProcessor::IsAutocalRequest(uint32_t frame_number) const { |
| // TODO(b/129910835): Use the proper logic to control when internal yuv buffer |
| // needs to be passed to the depth process block. Even if the auto cal is |
| // enabled, there is no need to pass the internal yuv buffer for every |
| // request, not even every device session. This is also related to how the |
| // buffer is added into the request. Similar logic exists in realtime request |
| // processor. However, this logic can further filter and determine which |
| // requests contain the internal yuv stream buffers and send them to the depth |
| // process block. Current implementation only treat the kAutocalFrameNumber |
| // request as autocal request. This must be consistent with that of the |
| // rt_request_processor. |
| if (!rgb_ir_auto_cal_enabled_) { |
| return false; |
| } |
| |
| return frame_number == kAutocalFrameNumber; |
| } |
| |
| void RgbirdResultRequestProcessor::TryReturnInternalBufferForDepth( |
| CaptureResult* result, bool* has_internal) { |
| ATRACE_CALL(); |
| if (result == nullptr || has_internal == nullptr) { |
| ALOGE("%s: result or has_rgb_raw_output is nullptr", __FUNCTION__); |
| return; |
| } |
| |
| if (internal_stream_manager_ == nullptr) { |
| ALOGE("%s: internal_stream_manager_ nullptr", __FUNCTION__); |
| return; |
| } |
| |
| std::vector<StreamBuffer> modified_output_buffers; |
| for (uint32_t i = 0; i < result->output_buffers.size(); i++) { |
| if (rgb_internal_yuv_stream_id_ == result->output_buffers[i].stream_id && |
| !IsAutocalRequest(result->frame_number)) { |
| *has_internal = true; |
| status_t res = internal_stream_manager_->ReturnStreamBuffer( |
| result->output_buffers[i]); |
| if (res != OK) { |
| ALOGW("%s: Failed to return RGB internal raw buffer for frame %d", |
| __FUNCTION__, result->frame_number); |
| } |
| } else { |
| modified_output_buffers.push_back(result->output_buffers[i]); |
| } |
| } |
| |
| if (!result->output_buffers.empty()) { |
| result->output_buffers = modified_output_buffers; |
| } |
| } |
| |
| status_t RgbirdResultRequestProcessor::HandleFdResultForHdrplus( |
| uint32_t frameNumber, HalCameraMetadata* metadata) { |
| if (metadata == nullptr) { |
| ALOGE("%s: metadata is nullptr", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| std::lock_guard<std::mutex> lock(face_detect_lock_); |
| auto iter = requested_face_detect_modes_.find(frameNumber); |
| if (iter == requested_face_detect_modes_.end()) { |
| ALOGW("%s: can't find frame (%d)", __FUNCTION__, frameNumber); |
| return OK; |
| } |
| |
| if (iter->second == ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) { |
| status_t res = hal_utils::RemoveFdInfoFromResult(metadata); |
| if (res != OK) { |
| ALOGW("%s: RestoreFdMetadataForHdrplus fail", __FUNCTION__); |
| } |
| } |
| requested_face_detect_modes_.erase(iter); |
| |
| return OK; |
| } |
| |
| status_t RgbirdResultRequestProcessor::AddPendingRequests( |
| const std::vector<ProcessBlockRequest>& /*process_block_requests*/, |
| const CaptureRequest& remaining_session_request) { |
| ATRACE_CALL(); |
| std::lock_guard<std::mutex> lock(depth_requests_mutex_); |
| for (auto stream_buffer : remaining_session_request.output_buffers) { |
| if (stream_buffer.acquire_fence != nullptr) { |
| stream_buffer.acquire_fence = |
| native_handle_clone(stream_buffer.acquire_fence); |
| if (stream_buffer.acquire_fence == nullptr) { |
| ALOGE("%s: Cloning acquire_fence of buffer failed", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| } |
| if (depth_stream_id_ == stream_buffer.stream_id) { |
| ALOGV("%s: request %d has a depth buffer", __FUNCTION__, |
| remaining_session_request.frame_number); |
| auto capture_request = std::make_unique<CaptureRequest>(); |
| capture_request->frame_number = remaining_session_request.frame_number; |
| if (remaining_session_request.settings != nullptr) { |
| capture_request->settings = |
| HalCameraMetadata::Clone(remaining_session_request.settings.get()); |
| } |
| capture_request->input_buffers.clear(); |
| capture_request->output_buffers.push_back(stream_buffer); |
| depth_requests_.emplace(remaining_session_request.frame_number, |
| std::move(capture_request)); |
| break; |
| } |
| } |
| |
| if (is_hdrplus_supported_) { |
| SaveFdForHdrplus(remaining_session_request); |
| SaveLsForHdrplus(remaining_session_request); |
| } |
| return OK; |
| } |
| |
| void RgbirdResultRequestProcessor::ProcessResultForHdrplus(CaptureResult* result, |
| bool* rgb_raw_output) { |
| ATRACE_CALL(); |
| if (result == nullptr || rgb_raw_output == nullptr) { |
| ALOGE("%s: result or rgb_raw_output is nullptr", __FUNCTION__); |
| return; |
| } |
| |
| if (internal_stream_manager_ == nullptr) { |
| ALOGE("%s: internal_stream_manager_ nullptr", __FUNCTION__); |
| return; |
| } |
| |
| // Return filled raw buffer to internal stream manager |
| // And remove raw buffer from result |
| status_t res; |
| std::vector<StreamBuffer> modified_output_buffers; |
| for (uint32_t i = 0; i < result->output_buffers.size(); i++) { |
| if (rgb_raw_stream_id_ == result->output_buffers[i].stream_id) { |
| *rgb_raw_output = true; |
| res = internal_stream_manager_->ReturnFilledBuffer( |
| result->frame_number, result->output_buffers[i]); |
| if (res != OK) { |
| ALOGW("%s: (%d)ReturnStreamBuffer fail", __FUNCTION__, |
| result->frame_number); |
| } |
| } else { |
| modified_output_buffers.push_back(result->output_buffers[i]); |
| } |
| } |
| |
| if (result->output_buffers.size() > 0) { |
| result->output_buffers = modified_output_buffers; |
| } |
| |
| if (result->result_metadata) { |
| res = internal_stream_manager_->ReturnMetadata( |
| rgb_raw_stream_id_, result->frame_number, result->result_metadata.get()); |
| if (res != OK) { |
| ALOGW("%s: (%d)ReturnMetadata fail", __FUNCTION__, result->frame_number); |
| } |
| |
| res = HandleFdResultForHdrplus(result->frame_number, |
| result->result_metadata.get()); |
| if (res != OK) { |
| ALOGE("%s: HandleFdResultForHdrplus(%d) fail", __FUNCTION__, |
| result->frame_number); |
| return; |
| } |
| |
| res = HandleLsResultForHdrplus(result->frame_number, |
| result->result_metadata.get()); |
| if (res != OK) { |
| ALOGE("%s: HandleLsResultForHdrplus(%d) fail", __FUNCTION__, |
| result->frame_number); |
| return; |
| } |
| } |
| } |
| |
| status_t RgbirdResultRequestProcessor::ReturnInternalStreams( |
| CaptureResult* result) { |
| ATRACE_CALL(); |
| if (result == nullptr) { |
| ALOGE("%s: block_result is null.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| std::vector<StreamBuffer> modified_output_buffers; |
| for (auto& stream_buffer : result->output_buffers) { |
| if (framework_stream_id_set_.find(stream_buffer.stream_id) == |
| framework_stream_id_set_.end()) { |
| status_t res = internal_stream_manager_->ReturnStreamBuffer(stream_buffer); |
| if (res != OK) { |
| ALOGE("%s: Failed to return stream buffer.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| } else { |
| modified_output_buffers.push_back(stream_buffer); |
| } |
| } |
| result->output_buffers = modified_output_buffers; |
| return OK; |
| } |
| |
| status_t RgbirdResultRequestProcessor::CheckFenceStatus(CaptureRequest* request) { |
| int fence_status = 0; |
| |
| if (request == nullptr) { |
| ALOGE("%s: request is null.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| for (uint32_t i = 0; i < request->output_buffers.size(); i++) { |
| if (request->output_buffers[i].acquire_fence != nullptr) { |
| auto fence = |
| const_cast<native_handle_t*>(request->output_buffers[i].acquire_fence); |
| if (fence->numFds == 1) { |
| fence_status = sync_wait(fence->data[0], kSyncWaitTime); |
| } |
| if (0 != fence_status) { |
| ALOGE("%s: Fence check failed.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| native_handle_close(fence); |
| native_handle_delete(fence); |
| request->output_buffers[i].acquire_fence = nullptr; |
| } |
| } |
| |
| return OK; |
| } |
| |
| bool RgbirdResultRequestProcessor::IsAutocalMetadataReadyLocked( |
| const HalCameraMetadata& metadata) { |
| camera_metadata_ro_entry entry = {}; |
| if (metadata.Get(VendorTagIds::kNonWarpedCropRegion, &entry) != OK) { |
| ALOGV("%s Get kNonWarpedCropRegion, tag fail.", __FUNCTION__); |
| return false; |
| } |
| |
| uint8_t fd_mode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; |
| if (metadata.Get(ANDROID_STATISTICS_FACE_DETECT_MODE, &entry) != OK) { |
| ALOGV("%s Get ANDROID_STATISTICS_FACE_DETECT_MODE tag fail.", __FUNCTION__); |
| return false; |
| } else { |
| fd_mode = *entry.data.u8; |
| } |
| |
| // If FD mode is off, don't need to check FD related metadata. |
| if (fd_mode != ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) { |
| if (metadata.Get(ANDROID_STATISTICS_FACE_RECTANGLES, &entry) != OK) { |
| ALOGV("%s Get ANDROID_STATISTICS_FACE_RECTANGLES tag fail.", __FUNCTION__); |
| return false; |
| } |
| if (metadata.Get(ANDROID_STATISTICS_FACE_SCORES, &entry) != OK) { |
| ALOGV("%s Get ANDROID_STATISTICS_FACE_SCORES tag fail.", __FUNCTION__); |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| status_t RgbirdResultRequestProcessor::VerifyAndSubmitDepthRequest( |
| uint32_t frame_number) { |
| std::lock_guard<std::mutex> lock(depth_requests_mutex_); |
| if (depth_requests_.find(frame_number) == depth_requests_.end()) { |
| ALOGW("%s: Can not find depth request with frame number %u", __FUNCTION__, |
| frame_number); |
| return NAME_NOT_FOUND; |
| } |
| |
| uint32_t valid_input_buffer_num = 0; |
| auto& depth_request = depth_requests_[frame_number]; |
| for (auto& input_buffer : depth_request->input_buffers) { |
| if (input_buffer.stream_id != kInvalidStreamId) { |
| valid_input_buffer_num++; |
| } |
| } |
| |
| if (IsAutocalRequest(frame_number)) { |
| if (valid_input_buffer_num != /*rgb+ir1+ir2*/ 3) { |
| // not all input buffers are ready, early return properly |
| ALOGV("%s: Not all input buffers are ready for frame %u", __FUNCTION__, |
| frame_number); |
| return OK; |
| } |
| } else { |
| // The input buffer for RGB pipeline could be a place holder to be |
| // consistent with the input buffer metadata. |
| if (valid_input_buffer_num != /*ir1+ir2*/ 2) { |
| // not all input buffers are ready, early return properly |
| ALOGV("%s: Not all input buffers are ready for frame %u", __FUNCTION__, |
| frame_number); |
| return OK; |
| } |
| } |
| |
| if (depth_request->input_buffer_metadata.empty()) { |
| // input buffer metadata is not ready(cloned) yet, early return properly |
| ALOGV("%s: Input buffer metadata is not ready for frame %u", __FUNCTION__, |
| frame_number); |
| return OK; |
| } |
| |
| // Check against all metadata needed before move on e.g. check against |
| // cropping info, FD result for internal YUV stream |
| status_t res = OK; |
| if (IsAutocalRequest(frame_number)) { |
| bool is_ready = false; |
| for (auto& metadata : depth_request->input_buffer_metadata) { |
| if (metadata != nullptr) { |
| is_ready = IsAutocalMetadataReadyLocked(*(metadata.get())); |
| } |
| } |
| if (!is_ready) { |
| ALOGV("%s: Not all AutoCal Metadata is ready for frame %u.", __FUNCTION__, |
| frame_number); |
| return OK; |
| } |
| } |
| |
| res = CheckFenceStatus(depth_request.get()); |
| if (res != OK) { |
| ALOGE("%s:Fence status wait failed.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| res = ProcessRequest(*depth_request.get()); |
| if (res != OK) { |
| ALOGE("%s: Failed to submit process request to depth process block.", |
| __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| depth_requests_.erase(frame_number); |
| return OK; |
| } |
| |
| status_t RgbirdResultRequestProcessor::TrySubmitDepthProcessBlockRequest( |
| const ProcessBlockResult& block_result) { |
| ATRACE_CALL(); |
| uint32_t request_id = block_result.request_id; |
| CaptureResult* result = block_result.result.get(); |
| uint32_t frame_number = result->frame_number; |
| |
| bool pending_request_updated = false; |
| for (auto& output_buffer : result->output_buffers) { |
| if (request_id == kIr1CameraId || request_id == kIr2CameraId || |
| (request_id == kRgbCameraId && |
| rgb_internal_yuv_stream_id_ == output_buffer.stream_id && |
| IsAutocalRequest(frame_number))) { |
| std::lock_guard<std::mutex> lock(depth_requests_mutex_); |
| |
| // In case depth request is flushed |
| if (depth_requests_.find(frame_number) == depth_requests_.end()) { |
| ALOGV("%s: Can not find depth request with frame number %u", |
| __FUNCTION__, frame_number); |
| status_t res = |
| internal_stream_manager_->ReturnStreamBuffer(output_buffer); |
| if (res != OK) { |
| ALOGW( |
| "%s: Failed to return internal buffer for flushed depth request" |
| " %u", |
| __FUNCTION__, frame_number); |
| } |
| continue; |
| } |
| |
| // If input_buffer_metadata is not empty, the RGB pipeline result metadata |
| // must have been cloned(other entries for IRs set to nullptr). The |
| // yuv_internal_stream buffer has to be inserted into the corresponding |
| // entry in input_buffers. Or if this is not a AutoCal request, the stream |
| // id for the place holder of the RGB input buffer must be invalid. Refer |
| // the logic below for result metadata handling. |
| const auto& metadata_list = |
| depth_requests_[frame_number]->input_buffer_metadata; |
| auto& input_buffers = depth_requests_[frame_number]->input_buffers; |
| if (!metadata_list.empty()) { |
| uint32_t rgb_metadata_index = 0; |
| for (; rgb_metadata_index < metadata_list.size(); rgb_metadata_index++) { |
| // Only the RGB pipeline result metadata is needed and cloned |
| if (metadata_list[rgb_metadata_index] != nullptr) { |
| break; |
| } |
| } |
| |
| if (rgb_metadata_index == metadata_list.size()) { |
| ALOGE("%s: RGB result metadata not found. rgb_metadata_index %u", |
| __FUNCTION__, rgb_metadata_index); |
| return UNKNOWN_ERROR; |
| } |
| |
| if (input_buffers.size() < kNumOfAutoCalInputBuffers) { |
| input_buffers.resize(kNumOfAutoCalInputBuffers); |
| } |
| |
| if (request_id == kRgbCameraId) { |
| if (input_buffers[rgb_metadata_index].stream_id != kInvalidStreamId) { |
| ALOGE("%s: YUV buffer already exists.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| input_buffers[rgb_metadata_index] = output_buffer; |
| } else { |
| for (uint32_t i_buffer = 0; i_buffer < input_buffers.size(); |
| i_buffer++) { |
| if (input_buffers[i_buffer].stream_id == kInvalidStreamId && |
| rgb_metadata_index != i_buffer) { |
| input_buffers[i_buffer] = output_buffer; |
| break; |
| } |
| } |
| } |
| } else { |
| input_buffers.push_back(output_buffer); |
| } |
| pending_request_updated = true; |
| } |
| } |
| |
| if (result->result_metadata != nullptr && request_id == kRgbCameraId) { |
| std::lock_guard<std::mutex> lock(depth_requests_mutex_); |
| |
| // In case a depth request is flushed |
| if (depth_requests_.find(frame_number) == depth_requests_.end()) { |
| ALOGV("%s No depth request for Autocal", __FUNCTION__); |
| return OK; |
| } |
| |
| // If YUV buffer exists in the input_buffers, the RGB pipeline metadata |
| // needs to be inserted into the corresponding entry in |
| // input_buffer_metadata. Otherwise, insert the RGB pipeline metadata into |
| // the entry that is not reserved for any existing IR input buffer. Refer |
| // above logic for input buffer preparation. |
| auto& input_buffers = depth_requests_[frame_number]->input_buffers; |
| auto& metadata_list = depth_requests_[frame_number]->input_buffer_metadata; |
| metadata_list.resize(kNumOfAutoCalInputBuffers); |
| uint32_t yuv_buffer_index = 0; |
| for (; yuv_buffer_index < input_buffers.size(); yuv_buffer_index++) { |
| if (input_buffers[yuv_buffer_index].stream_id == |
| rgb_internal_yuv_stream_id_) { |
| break; |
| } |
| } |
| |
| if (yuv_buffer_index >= kNumOfAutoCalInputBuffers) { |
| ALOGE("%s: input_buffers is full and YUV buffer not found.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| metadata_list[yuv_buffer_index] = |
| HalCameraMetadata::Clone(result->result_metadata.get()); |
| if (metadata_list[yuv_buffer_index] == nullptr) { |
| ALOGE("%s: clone RGB pipeline result metadata failed.", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| pending_request_updated = true; |
| |
| // If metadata arrives after all IR buffers and there is not RGB buffer |
| if (input_buffers.size() < kNumOfAutoCalInputBuffers) { |
| input_buffers.resize(kNumOfAutoCalInputBuffers); |
| } |
| } |
| |
| if (pending_request_updated) { |
| status_t res = VerifyAndSubmitDepthRequest(frame_number); |
| if (res != OK) { |
| ALOGE("%s: Failed to verify and submit depth request.", __FUNCTION__); |
| return res; |
| } |
| } |
| |
| return OK; |
| } |
| |
| void RgbirdResultRequestProcessor::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; |
| } |
| |
| CaptureResult* result = block_result.result.get(); |
| |
| bool has_internal_stream_buffer = false; |
| if (is_hdrplus_supported_) { |
| ProcessResultForHdrplus(result, &has_internal_stream_buffer); |
| } else if (depth_stream_id_ != -1) { |
| TryReturnInternalBufferForDepth(result, &has_internal_stream_buffer); |
| } |
| |
| status_t res = OK; |
| if (result->result_metadata) { |
| res = hal_utils::SetEnableZslMetadata(result->result_metadata.get(), false); |
| if (res != OK) { |
| ALOGW("%s: SetEnableZslMetadata (%d) fail", __FUNCTION__, |
| result->frame_number); |
| } |
| } |
| |
| // Don't send result to framework if only internal raw callback |
| if (has_internal_stream_buffer && result->result_metadata == nullptr && |
| result->output_buffers.size() == 0 && result->input_buffers.size() == 0) { |
| return; |
| } |
| |
| // TODO(b/128633958): remove the following once FLL syncing is verified |
| { |
| std::lock_guard<std::mutex> lock(depth_requests_mutex_); |
| if (((force_internal_stream_) || |
| (depth_requests_.find(result->frame_number) == depth_requests_.end())) && |
| (depth_stream_id_ != -1)) { |
| res = ReturnInternalStreams(result); |
| if (res != OK) { |
| ALOGE("%s: Failed to return internal buffers.", __FUNCTION__); |
| return; |
| } |
| } |
| } |
| |
| // Save necessary data for depth process block request |
| res = TrySubmitDepthProcessBlockRequest(block_result); |
| if (res != OK) { |
| ALOGE("%s: Failed to submit depth process block request.", __FUNCTION__); |
| return; |
| } |
| |
| if (block_result.request_id != kRgbCameraId) { |
| return; |
| } |
| |
| // If internal yuv stream remains in the result output buffer list, it must |
| // be used by some other purposes and will be returned separately. It should |
| // not be returned through the process_capture_result_. So we remove them here. |
| if (!result->output_buffers.empty()) { |
| auto iter = result->output_buffers.begin(); |
| while (iter != result->output_buffers.end()) { |
| if (iter->stream_id == rgb_internal_yuv_stream_id_) { |
| result->output_buffers.erase(iter); |
| break; |
| } |
| iter++; |
| } |
| } |
| |
| process_capture_result_(std::move(block_result.result)); |
| } |
| |
| void RgbirdResultRequestProcessor::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 RgbirdRtRequestProcessor. |
| uint32_t camera_id = block_message.request_id; |
| if (message.type == MessageType::kShutter && camera_id != kRgbCameraId) { |
| // Only send out shutters from the lead camera. |
| return; |
| } |
| |
| notify_(block_message.message); |
| } |
| |
| status_t RgbirdResultRequestProcessor::ConfigureStreams( |
| InternalStreamManager* internal_stream_manager, |
| const StreamConfiguration& stream_config, |
| StreamConfiguration* process_block_stream_config) { |
| ATRACE_CALL(); |
| if (process_block_stream_config == nullptr) { |
| ALOGE("%s: process_block_stream_config is null.", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| if (internal_stream_manager == nullptr) { |
| ALOGE("%s: internal_stream_manager is null.", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| internal_stream_manager_ = internal_stream_manager; |
| |
| if (is_hdrplus_supported_) { |
| return OK; |
| } |
| |
| process_block_stream_config->streams.clear(); |
| Stream depth_stream = {}; |
| for (auto& stream : stream_config.streams) { |
| // stream_config passed to this ConfigureStreams must contain only framework |
| // output and internal input streams |
| if (stream.stream_type == StreamType::kOutput) { |
| if (utils::IsDepthStream(stream)) { |
| ALOGI("%s: Depth stream id: %u observed by RgbirdResReqProcessor.", |
| __FUNCTION__, stream.id); |
| depth_stream_id_ = stream.id; |
| depth_stream = stream; |
| } |
| // record all framework output, save depth only for depth process block |
| framework_stream_id_set_.insert(stream.id); |
| } else if (stream.stream_type == StreamType::kInput) { |
| process_block_stream_config->streams.push_back(stream); |
| } |
| } |
| |
| // TODO(b/128633958): remove force flag after FLL syncing is verified |
| if (force_internal_stream_ || depth_stream_id_ != -1) { |
| process_block_stream_config->streams.push_back(depth_stream); |
| process_block_stream_config->operation_mode = stream_config.operation_mode; |
| process_block_stream_config->session_params = |
| HalCameraMetadata::Clone(stream_config.session_params.get()); |
| process_block_stream_config->stream_config_counter = |
| stream_config.stream_config_counter; |
| } |
| |
| return OK; |
| } |
| |
| status_t RgbirdResultRequestProcessor::SetProcessBlock( |
| std::unique_ptr<ProcessBlock> process_block) { |
| ATRACE_CALL(); |
| if (process_block == nullptr) { |
| ALOGE("%s: process_block is nullptr", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| std::lock_guard<std::mutex> lock(depth_process_block_lock_); |
| if (depth_process_block_ != nullptr) { |
| ALOGE("%s: Already configured.", __FUNCTION__); |
| return ALREADY_EXISTS; |
| } |
| |
| depth_process_block_ = std::move(process_block); |
| return OK; |
| } |
| |
| status_t RgbirdResultRequestProcessor::ProcessRequest( |
| const CaptureRequest& request) { |
| ATRACE_CALL(); |
| std::lock_guard<std::mutex> lock(depth_process_block_lock_); |
| if (depth_process_block_ == nullptr) { |
| ALOGE("%s: depth_process_block_ is null.", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| // Depth Process Block only handles one process block request each time |
| std::vector<ProcessBlockRequest> process_block_requests(1); |
| auto& block_request = process_block_requests[0]; |
| block_request.request_id = 0; |
| CaptureRequest& physical_request = block_request.request; |
| physical_request.frame_number = request.frame_number; |
| physical_request.settings = HalCameraMetadata::Clone(request.settings.get()); |
| for (auto& metadata : request.input_buffer_metadata) { |
| physical_request.input_buffer_metadata.emplace_back( |
| HalCameraMetadata::Clone(metadata.get())); |
| } |
| physical_request.input_buffers = request.input_buffers; |
| physical_request.output_buffers = request.output_buffers; |
| |
| return depth_process_block_->ProcessRequests(process_block_requests, request); |
| } |
| |
| status_t RgbirdResultRequestProcessor::Flush() { |
| ATRACE_CALL(); |
| |
| std::lock_guard<std::mutex> lock(depth_process_block_lock_); |
| if (depth_process_block_ == nullptr) { |
| ALOGW("%s: depth_process_block_ is null.", __FUNCTION__); |
| return OK; |
| } |
| |
| return depth_process_block_->Flush(); |
| } |
| |
| status_t RgbirdResultRequestProcessor::FlushPendingRequests() { |
| ATRACE_CALL(); |
| |
| std::lock_guard<std::mutex> lock(callback_lock_); |
| if (notify_ == nullptr) { |
| ALOGE("%s: notify_ is nullptr. Dropping a message.", __FUNCTION__); |
| return OK; |
| } |
| |
| if (process_capture_result_ == nullptr) { |
| ALOGE("%s: process_capture_result_ is nullptr. Dropping a result.", |
| __FUNCTION__); |
| return OK; |
| } |
| |
| std::lock_guard<std::mutex> requests_lock(depth_requests_mutex_); |
| for (auto& [frame_number, capture_request] : depth_requests_) { |
| // Returns all internal stream buffers |
| for (auto& input_buffer : capture_request->input_buffers) { |
| if (input_buffer.stream_id != kInvalidStreamId) { |
| status_t res = |
| internal_stream_manager_->ReturnStreamBuffer(input_buffer); |
| if (res != OK) { |
| ALOGW("%s: Failed to return internal buffer for depth request %d", |
| __FUNCTION__, frame_number); |
| } |
| } |
| } |
| |
| // Notify buffer error for the depth stream output buffer |
| const NotifyMessage message = { |
| .type = MessageType::kError, |
| .message.error = {.frame_number = frame_number, |
| .error_stream_id = depth_stream_id_, |
| .error_code = ErrorCode::kErrorBuffer}}; |
| notify_(message); |
| |
| // Return output buffer for the depth stream |
| auto result = std::make_unique<CaptureResult>(); |
| result->frame_number = frame_number; |
| for (auto& output_buffer : capture_request->output_buffers) { |
| if (output_buffer.stream_id == depth_stream_id_) { |
| result->output_buffers.push_back(output_buffer); |
| auto& buffer = result->output_buffers.back(); |
| buffer.status = BufferStatus::kError; |
| buffer.acquire_fence = nullptr; |
| buffer.release_fence = nullptr; |
| break; |
| } |
| } |
| process_capture_result_(std::move(result)); |
| } |
| depth_requests_.clear(); |
| ALOGI("%s: Flushing depth requests done. ", __FUNCTION__); |
| return OK; |
| } |
| |
| } // namespace google_camera_hal |
| } // namespace android |