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