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_DualIrCaptureSession"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include <log/log.h>
21 #include <utils/Trace.h>
22 
23 #include <set>
24 #include <vector>
25 
26 #include "dual_ir_capture_session.h"
27 #include "dual_ir_request_processor.h"
28 #include "dual_ir_result_request_processor.h"
29 #include "hal_utils.h"
30 #include "multicam_realtime_process_block.h"
31 
32 namespace android {
33 namespace google_camera_hal {
34 
IsStreamConfigurationSupported(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config)35 bool DualIrCaptureSession::IsStreamConfigurationSupported(
36     CameraDeviceSessionHwl* device_session_hwl,
37     const StreamConfiguration& stream_config) {
38   ATRACE_CALL();
39   if (device_session_hwl == nullptr) {
40     ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
41     return false;
42   }
43 
44   std::vector<uint32_t> physical_camera_ids =
45       device_session_hwl->GetPhysicalCameraIds();
46   if (physical_camera_ids.size() != 2) {
47     ALOGD("%s: Only support two IR cameras but there are %zu cameras.",
48           __FUNCTION__, physical_camera_ids.size());
49     return false;
50   }
51 
52   // Check the two physical cameras are IR cameras.
53   for (auto id : physical_camera_ids) {
54     std::unique_ptr<HalCameraMetadata> characteristics;
55     status_t res = device_session_hwl->GetPhysicalCameraCharacteristics(
56         id, &characteristics);
57     if (res != OK) {
58       ALOGE("%s: Cannot get physical camera characteristics for camera %u",
59             __FUNCTION__, id);
60       return false;
61     }
62 
63     // TODO(b/129088371): Work around b/129088371 because current IR camera's
64     // CFA is MONO instead of NIR.
65     if (!hal_utils::IsIrCamera(characteristics.get()) &&
66         !hal_utils::IsMonoCamera(characteristics.get())) {
67       ALOGD("%s: camera %u is not an IR or MONO camera", __FUNCTION__, id);
68       return false;
69     }
70   }
71 
72   uint32_t physical_stream_number = 0;
73   uint32_t logical_stream_number = 0;
74   for (auto& stream : stream_config.streams) {
75     if (stream.is_physical_camera_stream) {
76       physical_stream_number++;
77     } else {
78       logical_stream_number++;
79     }
80   }
81   if (logical_stream_number > 0 && physical_stream_number > 0) {
82     ALOGD("%s: can't support mixed logical and physical stream", __FUNCTION__);
83     return false;
84   }
85 
86   ALOGD("%s: DualIrCaptureSession supports the stream config", __FUNCTION__);
87   return true;
88 }
89 
Create(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,HwlRequestBuffersFunc,std::vector<HalStream> * hal_configured_streams,CameraBufferAllocatorHwl *)90 std::unique_ptr<CaptureSession> DualIrCaptureSession::Create(
91     CameraDeviceSessionHwl* device_session_hwl,
92     const StreamConfiguration& stream_config,
93     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
94     HwlRequestBuffersFunc /*request_stream_buffers*/,
95     std::vector<HalStream>* hal_configured_streams,
96     CameraBufferAllocatorHwl* /*camera_allocator_hwl*/) {
97   ATRACE_CALL();
98   if (!IsStreamConfigurationSupported(device_session_hwl, stream_config)) {
99     ALOGE("%s: stream configuration is not supported.", __FUNCTION__);
100     return nullptr;
101   }
102 
103   // TODO(b/129707250): Assume the first physical camera is the lead until
104   // it's available in the static metadata.
105   std::vector<uint32_t> physical_camera_ids =
106       device_session_hwl->GetPhysicalCameraIds();
107   uint32_t lead_camera_id = physical_camera_ids[0];
108 
109   // If stream configuration only contains follower physical streams, set
110   // follower as lead.
111   bool has_lead_camera_config = false;
112   for (auto& stream : stream_config.streams) {
113     if (!stream.is_physical_camera_stream ||
114         (stream.is_physical_camera_stream &&
115          stream.physical_camera_id == physical_camera_ids[0])) {
116       has_lead_camera_config = true;
117       break;
118     }
119   }
120   if (!has_lead_camera_config) {
121     lead_camera_id = physical_camera_ids[1];
122   }
123 
124   auto session = std::unique_ptr<DualIrCaptureSession>(
125       new DualIrCaptureSession(lead_camera_id));
126   if (session == nullptr) {
127     ALOGE("%s: Creating DualIrCaptureSession failed.", __FUNCTION__);
128     return nullptr;
129   }
130 
131   status_t res = session->Initialize(device_session_hwl, stream_config,
132                                      process_capture_result, notify,
133                                      hal_configured_streams);
134   if (res != OK) {
135     ALOGE("%s: Initializing DualIrCaptureSession failed: %s (%d).",
136           __FUNCTION__, strerror(-res), res);
137     return nullptr;
138   }
139 
140   ALOGI("%s: Created a DualIrCaptureSession", __FUNCTION__);
141   return session;
142 }
143 
DualIrCaptureSession(uint32_t lead_camera_id)144 DualIrCaptureSession::DualIrCaptureSession(uint32_t lead_camera_id)
145     : kLeadCameraId(lead_camera_id) {
146 }
147 
~DualIrCaptureSession()148 DualIrCaptureSession::~DualIrCaptureSession() {
149   ATRACE_CALL();
150   if (device_session_hwl_ != nullptr) {
151     device_session_hwl_->DestroyPipelines();
152   }
153 }
154 
AreAllStreamsConfigured(const StreamConfiguration & stream_config,const StreamConfiguration & process_block_stream_config) const155 bool DualIrCaptureSession::AreAllStreamsConfigured(
156     const StreamConfiguration& stream_config,
157     const StreamConfiguration& process_block_stream_config) const {
158   ATRACE_CALL();
159   // Check all streams are configured.
160   if (stream_config.streams.size() !=
161       process_block_stream_config.streams.size()) {
162     ALOGE("%s: stream_config has %zu streams but only configured %zu streams",
163           __FUNCTION__, stream_config.streams.size(),
164           process_block_stream_config.streams.size());
165     return false;
166   }
167 
168   for (auto& stream : stream_config.streams) {
169     bool found = false;
170     for (auto& configured_stream : process_block_stream_config.streams) {
171       if (stream.id == configured_stream.id) {
172         found = true;
173         break;
174       }
175     }
176 
177     if (!found) {
178       ALOGE("%s: Cannot find stream %u in configured streams.", __FUNCTION__,
179             stream.id);
180       return false;
181     }
182   }
183 
184   return true;
185 }
186 
ConfigureStreams(RequestProcessor * request_processor,ProcessBlock * process_block,const StreamConfiguration & overall_config,const StreamConfiguration & stream_config,StreamConfiguration * process_block_stream_config)187 status_t DualIrCaptureSession::ConfigureStreams(
188     RequestProcessor* request_processor, ProcessBlock* process_block,
189     const StreamConfiguration& overall_config,
190     const StreamConfiguration& stream_config,
191     StreamConfiguration* process_block_stream_config) {
192   ATRACE_CALL();
193   if (request_processor == nullptr || process_block == nullptr) {
194     ALOGE("%s: request_processor(%p) or process_block(%p) is nullptr",
195           __FUNCTION__, request_processor, process_block);
196     return BAD_VALUE;
197   }
198 
199   status_t res = request_processor->ConfigureStreams(
200       internal_stream_manager_.get(), stream_config,
201       process_block_stream_config);
202   if (res != OK) {
203     ALOGE("%s: Configuring stream for RequestProcessor failed: %s(%d)",
204           __FUNCTION__, strerror(-res), res);
205     return res;
206   }
207 
208   res = process_block->ConfigureStreams(*process_block_stream_config,
209                                         overall_config);
210   if (res != OK) {
211     ALOGE("%s: Configuring streams for ProcessBlock failed: %s(%d)",
212           __FUNCTION__, strerror(-res), res);
213     return res;
214   }
215 
216   return OK;
217 }
218 
ConnectProcessChain(RequestProcessor * request_processor,std::unique_ptr<ProcessBlock> process_block,std::unique_ptr<ResultProcessor> result_processor)219 status_t DualIrCaptureSession::ConnectProcessChain(
220     RequestProcessor* request_processor,
221     std::unique_ptr<ProcessBlock> process_block,
222     std::unique_ptr<ResultProcessor> result_processor) {
223   ATRACE_CALL();
224   if (request_processor == nullptr) {
225     ALOGE("%s: request_processor is nullptr", __FUNCTION__);
226     return BAD_VALUE;
227   }
228 
229   status_t res = process_block->SetResultProcessor(std::move(result_processor));
230   if (res != OK) {
231     ALOGE("%s: Setting result process in process block failed.", __FUNCTION__);
232     return res;
233   }
234 
235   res = request_processor->SetProcessBlock(std::move(process_block));
236   if (res != OK) {
237     ALOGE("%s: Setting process block for request processor failed: %s(%d)",
238           __FUNCTION__, strerror(-res), res);
239     return res;
240   }
241 
242   return OK;
243 }
244 
PurgeHalConfiguredStream(const StreamConfiguration & stream_config,std::vector<HalStream> * hal_configured_streams)245 status_t DualIrCaptureSession::PurgeHalConfiguredStream(
246     const StreamConfiguration& stream_config,
247     std::vector<HalStream>* hal_configured_streams) {
248   if (hal_configured_streams == nullptr) {
249     ALOGE("%s: HAL configured stream list is null.", __FUNCTION__);
250     return BAD_VALUE;
251   }
252 
253   std::set<int32_t> framework_stream_id_set;
254   for (auto& stream : stream_config.streams) {
255     framework_stream_id_set.insert(stream.id);
256   }
257 
258   std::vector<HalStream> configured_streams;
259   for (auto& hal_stream : *hal_configured_streams) {
260     if (framework_stream_id_set.find(hal_stream.id) !=
261         framework_stream_id_set.end()) {
262       configured_streams.push_back(hal_stream);
263     }
264   }
265   *hal_configured_streams = configured_streams;
266   return OK;
267 }
268 
MakeDepthChainSegmentStreamConfig(const StreamConfiguration &,StreamConfiguration * rt_process_block_stream_config,StreamConfiguration * depth_chain_segment_stream_config)269 status_t DualIrCaptureSession::MakeDepthChainSegmentStreamConfig(
270     const StreamConfiguration& /*stream_config*/,
271     StreamConfiguration* rt_process_block_stream_config,
272     StreamConfiguration* depth_chain_segment_stream_config) {
273   if (depth_chain_segment_stream_config == nullptr ||
274       rt_process_block_stream_config == nullptr) {
275     ALOGE(
276         "%s: depth_chain_segment_stream_config is nullptr or "
277         "rt_process_block_stream_config is nullptr.",
278         __FUNCTION__);
279     return BAD_VALUE;
280   }
281   // TODO(b/131618554):
282   // Actually implement this function to form a depth chain segment stream
283   // config from the overall stream config and the streams mutli-camera realtime
284   // process block configured.
285   // This function signature may need to be changed.
286 
287   return OK;
288 }
289 
SetupRealtimeSegment(const StreamConfiguration & stream_config,StreamConfiguration * process_block_stream_config,std::unique_ptr<MultiCameraRtProcessBlock> * rt_process_block,std::unique_ptr<DualIrResultRequestProcessor> * rt_result_request_processor)290 status_t DualIrCaptureSession::SetupRealtimeSegment(
291     const StreamConfiguration& stream_config,
292     StreamConfiguration* process_block_stream_config,
293     std::unique_ptr<MultiCameraRtProcessBlock>* rt_process_block,
294     std::unique_ptr<DualIrResultRequestProcessor>* rt_result_request_processor) {
295   request_processor_ =
296       DualIrRequestProcessor::Create(device_session_hwl_, kLeadCameraId);
297   if (request_processor_ == nullptr) {
298     ALOGE("%s: Creating DualIrRtRequestProcessor failed.", __FUNCTION__);
299     return UNKNOWN_ERROR;
300   }
301 
302   auto process_block = MultiCameraRtProcessBlock::Create(device_session_hwl_);
303   if (process_block == nullptr) {
304     ALOGE("%s: Creating MultiCameraRtProcessBlock failed.", __FUNCTION__);
305     return UNKNOWN_ERROR;
306   }
307 
308   auto result_request_processor = DualIrResultRequestProcessor::Create(
309       device_session_hwl_, stream_config, kLeadCameraId);
310   if (result_request_processor == nullptr) {
311     ALOGE("%s: Creating DualIrResultRequestProcessor failed.", __FUNCTION__);
312     return UNKNOWN_ERROR;
313   }
314 
315   status_t res = ConfigureStreams(request_processor_.get(), process_block.get(),
316                                   stream_config, stream_config,
317                                   process_block_stream_config);
318   if (res != OK) {
319     ALOGE("%s: Configuring streams failed: %s(%d).", __FUNCTION__,
320           strerror(-res), res);
321     return res;
322   }
323 
324   *rt_process_block = std::move(process_block);
325   *rt_result_request_processor = std::move(result_request_processor);
326   return OK;
327 }
328 
SetupDepthSegment(const StreamConfiguration & stream_config,StreamConfiguration * process_block_stream_config,DualIrResultRequestProcessor * rt_result_request_processor,std::unique_ptr<DepthProcessBlock> * depth_process_block,std::unique_ptr<DualIrDepthResultProcessor> * depth_result_processor)329 status_t DualIrCaptureSession::SetupDepthSegment(
330     const StreamConfiguration& stream_config,
331     StreamConfiguration* process_block_stream_config,
332     DualIrResultRequestProcessor* rt_result_request_processor,
333     std::unique_ptr<DepthProcessBlock>* depth_process_block,
334     std::unique_ptr<DualIrDepthResultProcessor>* depth_result_processor) {
335   DepthProcessBlock::DepthProcessBlockCreateData data = {};
336   auto process_block =
337       DepthProcessBlock::Create(device_session_hwl_, nullptr, data);
338   if (process_block == nullptr) {
339     ALOGE("%s: Creating DepthProcessBlock failed.", __FUNCTION__);
340     return UNKNOWN_ERROR;
341   }
342 
343   auto result_processor =
344       DualIrDepthResultProcessor::Create(internal_stream_manager_.get());
345   if (result_processor == nullptr) {
346     ALOGE("%s: Creating DualIrDepthResultProcessor failed.", __FUNCTION__);
347     return UNKNOWN_ERROR;
348   }
349 
350   StreamConfiguration depth_pb_stream_config;
351   StreamConfiguration depth_chain_segment_stream_config;
352   status_t res = MakeDepthChainSegmentStreamConfig(
353       stream_config, process_block_stream_config,
354       &depth_chain_segment_stream_config);
355   if (res != OK) {
356     ALOGE("%s: Failed to make depth chain segment stream configuration: %s(%d)",
357           __FUNCTION__, strerror(-res), res);
358     return res;
359   }
360 
361   res = ConfigureStreams(rt_result_request_processor, process_block.get(),
362                          stream_config, depth_chain_segment_stream_config,
363                          &depth_pb_stream_config);
364   if (res != OK) {
365     ALOGE("%s: Failed to configure streams for the depth segment.",
366           __FUNCTION__);
367     return res;
368   }
369 
370   // Append the streams configured by depth process block. So
371   // process_block_stream_config contains all streams configured by both
372   // realtime and depth process blocks
373   process_block_stream_config->streams.insert(
374       process_block_stream_config->streams.end(),
375       depth_pb_stream_config.streams.begin(),
376       depth_pb_stream_config.streams.end());
377 
378   *depth_process_block = std::move(process_block);
379   *depth_result_processor = std::move(result_processor);
380 
381   return OK;
382 }
383 
BuildPipelines(const StreamConfiguration & stream_config,std::vector<HalStream> * hal_configured_streams,MultiCameraRtProcessBlock * rt_process_block,DepthProcessBlock * depth_process_block)384 status_t DualIrCaptureSession::BuildPipelines(
385     const StreamConfiguration& stream_config,
386     std::vector<HalStream>* hal_configured_streams,
387     MultiCameraRtProcessBlock* rt_process_block,
388     DepthProcessBlock* depth_process_block) {
389   status_t res = device_session_hwl_->BuildPipelines();
390   if (res != OK) {
391     ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res),
392           res);
393     return res;
394   }
395 
396   res = rt_process_block->GetConfiguredHalStreams(hal_configured_streams);
397   if (res != OK) {
398     ALOGE("%s: Getting HAL streams failed: %s(%d)", __FUNCTION__,
399           strerror(-res), res);
400     return res;
401   }
402 
403   if (has_depth_stream_) {
404     std::vector<HalStream> depth_pb_configured_streams;
405     res = depth_process_block->GetConfiguredHalStreams(
406         &depth_pb_configured_streams);
407     if (res != OK) {
408       ALOGE("%s: Failed to get configured hal streams from DepthProcessBlock",
409             __FUNCTION__);
410       return UNKNOWN_ERROR;
411     }
412     // Depth Process Block can only configure one depth stream so far
413     if (depth_pb_configured_streams.size() != 1) {
414       ALOGE("%s: DepthProcessBlock configured more than one stream.",
415             __FUNCTION__);
416       return UNKNOWN_ERROR;
417     }
418     hal_configured_streams->push_back(depth_pb_configured_streams[0]);
419   }
420 
421   res = PurgeHalConfiguredStream(stream_config, hal_configured_streams);
422   if (res != OK) {
423     ALOGE("%s: Removing internal streams from configured stream failed: %s(%d)",
424           __FUNCTION__, strerror(-res), res);
425     return res;
426   }
427 
428   return OK;
429 }
430 
CreateProcessChain(const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::vector<HalStream> * hal_configured_streams)431 status_t DualIrCaptureSession::CreateProcessChain(
432     const StreamConfiguration& stream_config,
433     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
434     std::vector<HalStream>* hal_configured_streams) {
435   ATRACE_CALL();
436 
437   // process_block_stream_config is used to collect all streams configured by
438   // both realtime and the depth process blocks. This is used to verify if all
439   // framework streams have been configured.
440   StreamConfiguration process_block_stream_config;
441 
442   std::unique_ptr<MultiCameraRtProcessBlock> rt_process_block;
443   std::unique_ptr<DualIrResultRequestProcessor> rt_result_request_processor;
444   status_t res =
445       SetupRealtimeSegment(stream_config, &process_block_stream_config,
446                            &rt_process_block, &rt_result_request_processor);
447   if (res != OK) {
448     ALOGE("%s: Failed to setup the realtime segment of the process chain.",
449           __FUNCTION__);
450     return res;
451   }
452 
453   // Create process block and result processor for Depth Process Chain Segment
454   std::unique_ptr<DepthProcessBlock> depth_process_block;
455   std::unique_ptr<DualIrDepthResultProcessor> depth_result_processor;
456   if (has_depth_stream_) {
457     status_t res =
458         SetupDepthSegment(stream_config, &process_block_stream_config,
459                           rt_result_request_processor.get(),
460                           &depth_process_block, &depth_result_processor);
461     if (res != OK) {
462       ALOGE("%s: Failed to setup the depth segment of the process chain.",
463             __FUNCTION__);
464       return res;
465     }
466   }
467 
468   if (!AreAllStreamsConfigured(stream_config, process_block_stream_config)) {
469     ALOGE("%s: Not all streams are configured!", __FUNCTION__);
470     return INVALID_OPERATION;
471   }
472 
473   res = BuildPipelines(stream_config, hal_configured_streams,
474                        rt_process_block.get(), depth_process_block.get());
475   if (res != OK) {
476     ALOGE("%s: Failed to build pipelines.", __FUNCTION__);
477     return res;
478   }
479 
480   // Only connect the depth segment of the realtime process chain when depth
481   // stream is configured
482   if (has_depth_stream_) {
483     depth_result_processor->SetResultCallback(process_capture_result, notify);
484     res = ConnectProcessChain(rt_result_request_processor.get(),
485                               std::move(depth_process_block),
486                               std::move(depth_result_processor));
487     if (res != OK) {
488       ALOGE("%s: Connecting depth segment of realtime chain failed: %s(%d)",
489             __FUNCTION__, strerror(-res), res);
490       return res;
491     }
492   }
493 
494   rt_result_request_processor->SetResultCallback(process_capture_result, notify);
495   res =
496       ConnectProcessChain(request_processor_.get(), std::move(rt_process_block),
497                           std::move(rt_result_request_processor));
498   if (res != OK) {
499     ALOGE("%s: Connecting process chain failed: %s(%d)", __FUNCTION__,
500           strerror(-res), res);
501     return res;
502   }
503 
504   return OK;
505 }
506 
Initialize(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::vector<HalStream> * hal_configured_streams)507 status_t DualIrCaptureSession::Initialize(
508     CameraDeviceSessionHwl* device_session_hwl,
509     const StreamConfiguration& stream_config,
510     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
511     std::vector<HalStream>* hal_configured_streams) {
512   ATRACE_CALL();
513   device_session_hwl_ = device_session_hwl;
514 
515   internal_stream_manager_ = InternalStreamManager::Create();
516   if (internal_stream_manager_ == nullptr) {
517     ALOGE("%s: Cannot create internal stream manager.", __FUNCTION__);
518     return UNKNOWN_ERROR;
519   }
520 
521   for (auto& stream : stream_config.streams) {
522     if (utils::IsDepthStream(stream)) {
523       ALOGI("%s: Depth stream found in the stream config.", __FUNCTION__);
524       has_depth_stream_ = true;
525     }
526   }
527 
528   status_t res = CreateProcessChain(stream_config, process_capture_result,
529                                     notify, hal_configured_streams);
530   if (res != OK) {
531     ALOGE("%s: Creating the process  chain failed: %s(%d)", __FUNCTION__,
532           strerror(-res), res);
533     return res;
534   }
535 
536   return OK;
537 }
538 
ProcessRequest(const CaptureRequest & request)539 status_t DualIrCaptureSession::ProcessRequest(const CaptureRequest& request) {
540   ATRACE_CALL();
541   return request_processor_->ProcessRequest(request);
542 }
543 
Flush()544 status_t DualIrCaptureSession::Flush() {
545   ATRACE_CALL();
546   return request_processor_->Flush();
547 }
548 
549 }  // namespace google_camera_hal
550 }  // namespace android
551