1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // #define LOG_NDEBUG 0
18 #define LOG_TAG "GCH_RealtimeProcessBlock"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include "realtime_process_block.h"
21 
22 #include <log/log.h>
23 #include <utils/Trace.h>
24 
25 #include "hal_utils.h"
26 #include "result_processor.h"
27 
28 namespace android {
29 namespace google_camera_hal {
30 
Create(CameraDeviceSessionHwl * device_session_hwl)31 std::unique_ptr<RealtimeProcessBlock> RealtimeProcessBlock::Create(
32     CameraDeviceSessionHwl* device_session_hwl) {
33   ATRACE_CALL();
34   if (!IsSupported(device_session_hwl)) {
35     ALOGE("%s: Not supported.", __FUNCTION__);
36     return nullptr;
37   }
38 
39   auto block = std::unique_ptr<RealtimeProcessBlock>(
40       new RealtimeProcessBlock(device_session_hwl));
41   if (block == nullptr) {
42     ALOGE("%s: Creating RealtimeProcessBlock failed.", __FUNCTION__);
43     return nullptr;
44   }
45 
46   return block;
47 }
48 
IsSupported(CameraDeviceSessionHwl * device_session_hwl)49 bool RealtimeProcessBlock::IsSupported(
50     CameraDeviceSessionHwl* device_session_hwl) {
51   if (device_session_hwl == nullptr) {
52     ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
53     return false;
54   }
55 
56   return true;
57 }
58 
RealtimeProcessBlock(CameraDeviceSessionHwl * device_session_hwl)59 RealtimeProcessBlock::RealtimeProcessBlock(
60     CameraDeviceSessionHwl* device_session_hwl)
61     : kCameraId(device_session_hwl->GetCameraId()),
62       device_session_hwl_(device_session_hwl) {
63   hwl_pipeline_callback_.process_pipeline_result = HwlProcessPipelineResultFunc(
64       [this](std::unique_ptr<HwlPipelineResult> result) {
65         NotifyHwlPipelineResult(std::move(result));
66       });
67 
68   hwl_pipeline_callback_.process_pipeline_batch_result =
69       HwlProcessPipelineBatchResultFunc(
70           [this](std::vector<std::unique_ptr<HwlPipelineResult>> results) {
71             NotifyHwlPipelineBatchResult(std::move(results));
72           });
73 
74   hwl_pipeline_callback_.notify = NotifyHwlPipelineMessageFunc(
75       [this](uint32_t pipeline_id, const NotifyMessage& message) {
76         NotifyHwlPipelineMessage(pipeline_id, message);
77       });
78 }
79 
SetResultProcessor(std::unique_ptr<ResultProcessor> result_processor)80 status_t RealtimeProcessBlock::SetResultProcessor(
81     std::unique_ptr<ResultProcessor> result_processor) {
82   ATRACE_CALL();
83   if (result_processor == nullptr) {
84     ALOGE("%s: result_processor is nullptr", __FUNCTION__);
85     return BAD_VALUE;
86   }
87 
88   std::lock_guard<std::mutex> lock(result_processor_lock_);
89   if (result_processor_ != nullptr) {
90     ALOGE("%s: result_processor_ was already set.", __FUNCTION__);
91     return ALREADY_EXISTS;
92   }
93 
94   result_processor_ = std::move(result_processor);
95   return OK;
96 }
97 
ConfigureStreams(const StreamConfiguration & stream_config,const StreamConfiguration & overall_config)98 status_t RealtimeProcessBlock::ConfigureStreams(
99     const StreamConfiguration& stream_config,
100     const StreamConfiguration& overall_config) {
101   ATRACE_CALL();
102   std::lock_guard lock(configure_shared_mutex_);
103   if (is_configured_) {
104     ALOGE("%s: Already configured.", __FUNCTION__);
105     return ALREADY_EXISTS;
106   }
107 
108   status_t res = device_session_hwl_->ConfigurePipeline(
109       kCameraId, hwl_pipeline_callback_, stream_config, overall_config,
110       &pipeline_id_);
111   if (res != OK) {
112     ALOGE("%s: Configuring a pipeline failed: %s(%d)", __FUNCTION__,
113           strerror(-res), res);
114     return res;
115   }
116 
117   is_configured_ = true;
118   return OK;
119 }
120 
GetConfiguredHalStreams(std::vector<HalStream> * hal_streams) const121 status_t RealtimeProcessBlock::GetConfiguredHalStreams(
122     std::vector<HalStream>* hal_streams) const {
123   ATRACE_CALL();
124   std::lock_guard lock(configure_shared_mutex_);
125   if (hal_streams == nullptr) {
126     ALOGE("%s: hal_streams is nullptr.", __FUNCTION__);
127     return BAD_VALUE;
128   }
129 
130   if (!is_configured_) {
131     ALOGE("%s: Not configured yet.", __FUNCTION__);
132     return NO_INIT;
133   }
134 
135   return device_session_hwl_->GetConfiguredHalStream(pipeline_id_, hal_streams);
136 }
137 
ProcessRequests(const std::vector<ProcessBlockRequest> & process_block_requests,const CaptureRequest & remaining_session_request)138 status_t RealtimeProcessBlock::ProcessRequests(
139     const std::vector<ProcessBlockRequest>& process_block_requests,
140     const CaptureRequest& remaining_session_request) {
141   ATRACE_CALL();
142   if (process_block_requests.size() != 1) {
143     ALOGE("%s: Only a single request is supported but there are %zu",
144           __FUNCTION__, process_block_requests.size());
145     return BAD_VALUE;
146   }
147 
148   {
149     std::lock_guard<std::mutex> lock(result_processor_lock_);
150     if (result_processor_ == nullptr) {
151       ALOGE("%s: result processor was not set.", __FUNCTION__);
152       return NO_INIT;
153     }
154 
155     status_t res = result_processor_->AddPendingRequests(
156         process_block_requests, remaining_session_request);
157     if (res != OK) {
158       ALOGE("%s: Adding a pending request to result processor failed: %s(%d)",
159             __FUNCTION__, strerror(-res), res);
160       return res;
161     }
162   }
163 
164   std::shared_lock lock(configure_shared_mutex_);
165   if (!is_configured_) {
166     ALOGE("%s: block is not configured.", __FUNCTION__);
167     return NO_INIT;
168   }
169 
170   std::vector<HwlPipelineRequest> hwl_requests(1);
171   status_t res = hal_utils::CreateHwlPipelineRequest(
172       &hwl_requests[0], pipeline_id_, process_block_requests[0].request);
173   if (res != OK) {
174     ALOGE("%s: Creating HWL pipeline request failed: %s(%d)", __FUNCTION__,
175           strerror(-res), res);
176     return res;
177   }
178 
179   return device_session_hwl_->SubmitRequests(
180       process_block_requests[0].request.frame_number, hwl_requests);
181 }
182 
Flush()183 status_t RealtimeProcessBlock::Flush() {
184   ATRACE_CALL();
185   std::shared_lock lock(configure_shared_mutex_);
186   if (!is_configured_) {
187     return OK;
188   }
189 
190   return device_session_hwl_->Flush();
191 }
192 
NotifyHwlPipelineResult(std::unique_ptr<HwlPipelineResult> hwl_result)193 void RealtimeProcessBlock::NotifyHwlPipelineResult(
194     std::unique_ptr<HwlPipelineResult> hwl_result) {
195   ATRACE_CALL();
196   std::lock_guard<std::mutex> lock(result_processor_lock_);
197   if (result_processor_ == nullptr) {
198     ALOGE("%s: result processor is nullptr. Dropping a result", __FUNCTION__);
199     return;
200   }
201 
202   auto capture_result = hal_utils::ConvertToCaptureResult(std::move(hwl_result));
203   if (capture_result == nullptr) {
204     ALOGE("%s: Converting to capture result failed.", __FUNCTION__);
205     return;
206   }
207 
208   ProcessBlockResult result = {.result = std::move(capture_result)};
209   result_processor_->ProcessResult(std::move(result));
210 }
211 
NotifyHwlPipelineBatchResult(std::vector<std::unique_ptr<HwlPipelineResult>> hwl_results)212 void RealtimeProcessBlock::NotifyHwlPipelineBatchResult(
213     std::vector<std::unique_ptr<HwlPipelineResult>> hwl_results) {
214   ATRACE_CALL();
215   std::lock_guard<std::mutex> lock(result_processor_lock_);
216   if (result_processor_ == nullptr) {
217     ALOGE("%s: result processor is nullptr. Dropping a result", __FUNCTION__);
218     return;
219   }
220 
221   std::vector<ProcessBlockResult> block_results;
222   block_results.reserve(hwl_results.size());
223   for (auto& hwl_result : hwl_results) {
224     auto capture_result =
225         hal_utils::ConvertToCaptureResult(std::move(hwl_result));
226     if (capture_result == nullptr) {
227       ALOGE("%s: Converting to capture result failed.", __FUNCTION__);
228       return;
229     }
230 
231     block_results.push_back(
232         ProcessBlockResult{.result = std::move(capture_result)});
233   }
234   result_processor_->ProcessBatchResult(std::move(block_results));
235 }
236 
NotifyHwlPipelineMessage(uint32_t,const NotifyMessage & message)237 void RealtimeProcessBlock::NotifyHwlPipelineMessage(
238     uint32_t /*pipeline_id*/, const NotifyMessage& message) {
239   ATRACE_CALL();
240   std::lock_guard<std::mutex> lock(result_processor_lock_);
241   if (result_processor_ == nullptr) {
242     ALOGE("%s: result processor is nullptr. Dropping a message", __FUNCTION__);
243     return;
244   }
245 
246   ProcessBlockNotifyMessage block_message = {.message = message};
247   result_processor_->Notify(block_message);
248 }
249 
250 }  // namespace google_camera_hal
251 }  // namespace android
252