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_RgbirdCaptureSession"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include "rgbird_capture_session.h"
21
22 #include <cutils/properties.h>
23 #include <inttypes.h>
24 #include <log/log.h>
25 #include <utils/Trace.h>
26
27 #include <set>
28
29 #include "basic_result_processor.h"
30 #include "depth_process_block.h"
31 #include "hal_utils.h"
32 #include "hdrplus_process_block.h"
33 #include "hdrplus_request_processor.h"
34 #include "hdrplus_result_processor.h"
35 #include "multicam_realtime_process_block.h"
36 #include "rgbird_depth_result_processor.h"
37 #include "rgbird_result_request_processor.h"
38 #include "rgbird_rt_request_processor.h"
39
40 namespace android {
41 namespace google_camera_hal {
42
IsStreamConfigurationSupported(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration &)43 bool RgbirdCaptureSession::IsStreamConfigurationSupported(
44 CameraDeviceSessionHwl* device_session_hwl,
45 const StreamConfiguration& /*stream_config*/) {
46 ATRACE_CALL();
47 if (device_session_hwl == nullptr) {
48 ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
49 return false;
50 }
51
52 std::vector<uint32_t> physical_camera_ids =
53 device_session_hwl->GetPhysicalCameraIds();
54 if (physical_camera_ids.size() != 3) {
55 ALOGD("%s: RgbirdCaptureSession doesn't support %zu physical cameras",
56 __FUNCTION__, physical_camera_ids.size());
57 return false;
58 }
59
60 // Check if this is a logical camera containing two IR cameras.
61 uint32_t num_ir_camera = 0;
62 for (auto id : physical_camera_ids) {
63 std::unique_ptr<HalCameraMetadata> characteristics;
64 status_t res = device_session_hwl->GetPhysicalCameraCharacteristics(
65 id, &characteristics);
66
67 if (res != OK) {
68 ALOGE("%s: Cannot get physical camera characteristics for camera %u",
69 __FUNCTION__, id);
70 return false;
71 }
72
73 // TODO(b/129088371): Work around b/129088371 because current IR camera's
74 // CFA is MONO instead of NIR.
75 if (hal_utils::IsIrCamera(characteristics.get()) ||
76 hal_utils::IsMonoCamera(characteristics.get())) {
77 num_ir_camera++;
78 }
79 }
80
81 if (num_ir_camera != 2) {
82 ALOGD("%s: RgbirdCaptureSession only supports 2 ir cameras", __FUNCTION__);
83 return false;
84 }
85
86 ALOGD("%s: RgbirdCaptureSession supports the stream config", __FUNCTION__);
87 return true;
88 }
89
Create(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,ProcessBatchCaptureResultFunc,NotifyFunc notify,HwlSessionCallback session_callback,std::vector<HalStream> * hal_configured_streams,CameraBufferAllocatorHwl *)90 std::unique_ptr<CaptureSession> RgbirdCaptureSession::Create(
91 CameraDeviceSessionHwl* device_session_hwl,
92 const StreamConfiguration& stream_config,
93 ProcessCaptureResultFunc process_capture_result,
94 ProcessBatchCaptureResultFunc /*process_batch_capture_result*/,
95 NotifyFunc notify, HwlSessionCallback session_callback,
96 std::vector<HalStream>* hal_configured_streams,
97 CameraBufferAllocatorHwl* /*camera_allocator_hwl*/) {
98 ATRACE_CALL();
99 auto session =
100 std::unique_ptr<RgbirdCaptureSession>(new RgbirdCaptureSession());
101 if (session == nullptr) {
102 ALOGE("%s: Creating RgbirdCaptureSession failed.", __FUNCTION__);
103 return nullptr;
104 }
105
106 status_t res = session->Initialize(
107 device_session_hwl, stream_config, process_capture_result, notify,
108 session_callback.request_stream_buffers, hal_configured_streams);
109 if (res != OK) {
110 ALOGE("%s: Initializing RgbirdCaptureSession failed: %s (%d).",
111 __FUNCTION__, strerror(-res), res);
112 return nullptr;
113 }
114
115 return session;
116 }
117
~RgbirdCaptureSession()118 RgbirdCaptureSession::~RgbirdCaptureSession() {
119 if (device_session_hwl_ != nullptr) {
120 device_session_hwl_->DestroyPipelines();
121 }
122
123 rt_request_processor_ = nullptr;
124 hdrplus_request_processor_ = nullptr;
125 result_dispatcher_ = nullptr;
126 }
127
AreAllStreamsConfigured(const StreamConfiguration & stream_config,const StreamConfiguration & process_block_stream_config) const128 bool RgbirdCaptureSession::AreAllStreamsConfigured(
129 const StreamConfiguration& stream_config,
130 const StreamConfiguration& process_block_stream_config) const {
131 ATRACE_CALL();
132 // Check all streams are configured.
133 if (stream_config.streams.size() > process_block_stream_config.streams.size()) {
134 ALOGE("%s: stream_config has %zu streams but only configured %zu streams",
135 __FUNCTION__, stream_config.streams.size(),
136 process_block_stream_config.streams.size());
137 return false;
138 }
139
140 for (auto& stream : stream_config.streams) {
141 bool found = false;
142 for (auto& configured_stream : process_block_stream_config.streams) {
143 if (stream.id == configured_stream.id) {
144 found = true;
145 break;
146 }
147 }
148
149 if (!found) {
150 ALOGE("%s: Cannot find stream %u in configured streams.", __FUNCTION__,
151 stream.id);
152 return false;
153 }
154 }
155
156 return true;
157 }
158
ConfigureStreams(const StreamConfiguration & stream_config,RequestProcessor * request_processor,ProcessBlock * process_block,StreamConfiguration * process_block_stream_config)159 status_t RgbirdCaptureSession::ConfigureStreams(
160 const StreamConfiguration& stream_config,
161 RequestProcessor* request_processor, ProcessBlock* process_block,
162 StreamConfiguration* process_block_stream_config) {
163 ATRACE_CALL();
164 if (request_processor == nullptr || process_block == nullptr ||
165 process_block_stream_config == nullptr) {
166 ALOGE(
167 "%s: request_processor(%p) or process_block(%p) or "
168 "process_block_stream_config(%p) is nullptr",
169 __FUNCTION__, request_processor, process_block,
170 process_block_stream_config);
171 return BAD_VALUE;
172 }
173
174 status_t res = request_processor->ConfigureStreams(
175 internal_stream_manager_.get(), stream_config,
176 process_block_stream_config);
177 if (res != OK) {
178 ALOGE("%s: Configuring stream for RequestProcessor failed: %s(%d)",
179 __FUNCTION__, strerror(-res), res);
180 return res;
181 }
182
183 res = process_block->ConfigureStreams(*process_block_stream_config,
184 stream_config);
185 if (res != OK) {
186 ALOGE("%s: Configuring streams for ProcessBlock failed: %s(%d)",
187 __FUNCTION__, strerror(-res), res);
188 return res;
189 }
190
191 return OK;
192 }
193
SetDepthInternalStreamId(const StreamConfiguration & process_block_stream_config,const StreamConfiguration & stream_config)194 status_t RgbirdCaptureSession::SetDepthInternalStreamId(
195 const StreamConfiguration& process_block_stream_config,
196 const StreamConfiguration& stream_config) {
197 // Assuming there is at most one internal YUV stream configured when this
198 // function is called(i.e. when depth stream is configured).
199 for (auto& configured_stream : process_block_stream_config.streams) {
200 if (configured_stream.format == HAL_PIXEL_FORMAT_YCBCR_420_888) {
201 bool matching_found = false;
202 for (auto& framework_stream : stream_config.streams) {
203 if (configured_stream.id == framework_stream.id) {
204 matching_found = true;
205 break;
206 }
207 }
208 if (!matching_found) {
209 rgb_internal_yuv_stream_id_ = configured_stream.id;
210 }
211 } else if (configured_stream.format == HAL_PIXEL_FORMAT_Y8) {
212 if (configured_stream.physical_camera_id == ir1_camera_id_) {
213 ir1_internal_raw_stream_id_ = configured_stream.id;
214 } else if (configured_stream.physical_camera_id == ir2_camera_id_) {
215 ir2_internal_raw_stream_id_ = configured_stream.id;
216 } else {
217 ALOGV("%s: Y8 stream found from non-IR sensors.", __FUNCTION__);
218 }
219 }
220 }
221
222 if (rgb_internal_yuv_stream_id_ == kInvalidStreamId ||
223 ir1_internal_raw_stream_id_ == kInvalidStreamId ||
224 ir2_internal_raw_stream_id_ == kInvalidStreamId) {
225 ALOGE(
226 "%s: Internal YUV or IR stream not found in "
227 "process_block_stream_config.",
228 __FUNCTION__);
229 return UNKNOWN_ERROR;
230 }
231
232 return OK;
233 }
234
ConfigureHdrplusRawStreamId(const StreamConfiguration & process_block_stream_config)235 status_t RgbirdCaptureSession::ConfigureHdrplusRawStreamId(
236 const StreamConfiguration& process_block_stream_config) {
237 ATRACE_CALL();
238 std::unique_ptr<HalCameraMetadata> characteristics;
239 status_t res = device_session_hwl_->GetCameraCharacteristics(&characteristics);
240 if (res != OK) {
241 ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
242 return BAD_VALUE;
243 }
244
245 uint32_t active_array_width, active_array_height;
246 camera_metadata_ro_entry entry;
247 res = characteristics->Get(
248 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &entry);
249 if (res == OK) {
250 active_array_width = entry.data.i32[2];
251 active_array_height = entry.data.i32[3];
252 ALOGI("%s Active size (%d x %d).", __FUNCTION__, active_array_width,
253 active_array_height);
254 } else {
255 ALOGE("%s Get active size failed: %s (%d).", __FUNCTION__, strerror(-res),
256 res);
257 return UNKNOWN_ERROR;
258 }
259
260 for (auto& configured_stream : process_block_stream_config.streams) {
261 if (configured_stream.format == kHdrplusRawFormat &&
262 configured_stream.width == active_array_width &&
263 configured_stream.height == active_array_height) {
264 rgb_raw_stream_id_ = configured_stream.id;
265 break;
266 }
267 }
268
269 if (rgb_raw_stream_id_ == -1) {
270 ALOGE("%s: Configuring stream fail due to wrong raw_stream_id",
271 __FUNCTION__);
272 return UNKNOWN_ERROR;
273 }
274
275 return OK;
276 }
277
AllocateInternalBuffers(const StreamConfiguration & framework_stream_config,std::vector<HalStream> * hal_configured_streams,ProcessBlock * hdrplus_process_block)278 status_t RgbirdCaptureSession::AllocateInternalBuffers(
279 const StreamConfiguration& framework_stream_config,
280 std::vector<HalStream>* hal_configured_streams,
281 ProcessBlock* hdrplus_process_block) {
282 ATRACE_CALL();
283 status_t res = OK;
284
285 std::set<int32_t> framework_stream_id_set;
286 for (auto& stream : framework_stream_config.streams) {
287 framework_stream_id_set.insert(stream.id);
288 }
289
290 for (uint32_t i = 0; i < hal_configured_streams->size(); i++) {
291 HalStream& hal_stream = hal_configured_streams->at(i);
292
293 if (framework_stream_id_set.find(hal_stream.id) ==
294 framework_stream_id_set.end()) {
295 // hdrplus rgb raw stream buffers is allocated separately
296 if (hal_stream.id == rgb_raw_stream_id_) {
297 continue;
298 }
299
300 uint32_t additional_num_buffers =
301 (hal_stream.max_buffers >= kDefaultInternalBufferCount)
302 ? 0
303 : (kDefaultInternalBufferCount - hal_stream.max_buffers);
304 res = internal_stream_manager_->AllocateBuffers(
305 hal_stream, hal_stream.max_buffers + additional_num_buffers);
306 if (res != OK) {
307 ALOGE("%s: Failed to allocate buffer for internal stream %d: %s(%d)",
308 __FUNCTION__, hal_stream.id, strerror(-res), res);
309 return res;
310 } else {
311 ALOGI("%s: Allocating %d internal buffers for stream %d", __FUNCTION__,
312 additional_num_buffers + hal_stream.max_buffers, hal_stream.id);
313 }
314 }
315 }
316
317 if (is_hdrplus_supported_) {
318 std::vector<HalStream> hdrplus_hal_configured_streams;
319 res = hdrplus_process_block->GetConfiguredHalStreams(
320 &hdrplus_hal_configured_streams);
321 if (res != OK) {
322 ALOGE("%s: Getting HDR+ HAL streams failed: %s(%d)", __FUNCTION__,
323 strerror(-res), res);
324 return res;
325 }
326
327 res = ConfigureHdrplusUsageAndBuffers(hal_configured_streams,
328 &hdrplus_hal_configured_streams);
329 if (res != OK) {
330 ALOGE("%s: ConfigureHdrplusUsageAndBuffer failed: %s(%d)", __FUNCTION__,
331 strerror(-res), res);
332 return res;
333 }
334 }
335 return res;
336 }
337
PurgeHalConfiguredStream(const StreamConfiguration & stream_config,std::vector<HalStream> * hal_configured_streams)338 status_t RgbirdCaptureSession::PurgeHalConfiguredStream(
339 const StreamConfiguration& stream_config,
340 std::vector<HalStream>* hal_configured_streams) {
341 if (hal_configured_streams == nullptr) {
342 ALOGE("%s: HAL configured stream list is null.", __FUNCTION__);
343 return BAD_VALUE;
344 }
345
346 std::set<int32_t> framework_stream_id_set;
347 for (auto& stream : stream_config.streams) {
348 framework_stream_id_set.insert(stream.id);
349 }
350
351 std::vector<HalStream> configured_streams;
352 for (auto& hal_stream : *hal_configured_streams) {
353 if (framework_stream_id_set.find(hal_stream.id) !=
354 framework_stream_id_set.end()) {
355 configured_streams.push_back(hal_stream);
356 }
357 }
358 *hal_configured_streams = configured_streams;
359 return OK;
360 }
361
NeedDepthProcessBlock() const362 bool RgbirdCaptureSession::NeedDepthProcessBlock() const {
363 // TODO(b/128633958): remove force flag after FLL syncing is verified
364 return force_internal_stream_ || has_depth_stream_;
365 }
366
CreateDepthChainSegment(std::unique_ptr<DepthProcessBlock> * depth_process_block,std::unique_ptr<RgbirdDepthResultProcessor> * depth_result_processor,RgbirdResultRequestProcessor * rt_result_processor,const StreamConfiguration & stream_config,const StreamConfiguration & overall_config,StreamConfiguration * depth_block_stream_config)367 status_t RgbirdCaptureSession::CreateDepthChainSegment(
368 std::unique_ptr<DepthProcessBlock>* depth_process_block,
369 std::unique_ptr<RgbirdDepthResultProcessor>* depth_result_processor,
370 RgbirdResultRequestProcessor* rt_result_processor,
371 const StreamConfiguration& stream_config,
372 const StreamConfiguration& overall_config,
373 StreamConfiguration* depth_block_stream_config) {
374 ATRACE_CALL();
375 DepthProcessBlock::DepthProcessBlockCreateData data = {
376 .rgb_internal_yuv_stream_id = rgb_internal_yuv_stream_id_,
377 .ir1_internal_raw_stream_id = ir1_internal_raw_stream_id_,
378 .ir2_internal_raw_stream_id = ir2_internal_raw_stream_id_};
379 auto process_block = DepthProcessBlock::Create(device_session_hwl_,
380 request_stream_buffers_, data);
381 if (process_block == nullptr) {
382 ALOGE("%s: Creating DepthProcessBlock failed.", __FUNCTION__);
383 return UNKNOWN_ERROR;
384 }
385
386 auto result_processor =
387 RgbirdDepthResultProcessor::Create(internal_stream_manager_.get());
388 if (result_processor == nullptr) {
389 ALOGE("%s: Creating RgbirdDepthResultProcessor", __FUNCTION__);
390 return UNKNOWN_ERROR;
391 }
392
393 status_t res = rt_result_processor->ConfigureStreams(
394 internal_stream_manager_.get(), stream_config, depth_block_stream_config);
395 if (res != OK) {
396 ALOGE("%s: Configuring streams for ResultRequestProcessor failed: %s(%d)",
397 __FUNCTION__, strerror(-res), res);
398 return res;
399 }
400
401 res = process_block->ConfigureStreams(*depth_block_stream_config,
402 overall_config);
403 if (res != OK) {
404 ALOGE("%s: Configuring streams for DepthProcessBlock failed: %s(%d)",
405 __FUNCTION__, strerror(-res), res);
406 return res;
407 }
408
409 *depth_process_block = std::move(process_block);
410 *depth_result_processor = std::move(result_processor);
411
412 return OK;
413 }
414
SetupDepthChainSegment(const StreamConfiguration & stream_config,RgbirdResultRequestProcessor * realtime_result_processor,std::unique_ptr<ProcessBlock> * depth_process_block,std::unique_ptr<ResultProcessor> * depth_result_processor,StreamConfiguration * rt_process_block_stream_config)415 status_t RgbirdCaptureSession::SetupDepthChainSegment(
416 const StreamConfiguration& stream_config,
417 RgbirdResultRequestProcessor* realtime_result_processor,
418 std::unique_ptr<ProcessBlock>* depth_process_block,
419 std::unique_ptr<ResultProcessor>* depth_result_processor,
420 StreamConfiguration* rt_process_block_stream_config) {
421 ATRACE_CALL();
422 // Create the depth segment of realtime process chain if need depth processing
423 std::unique_ptr<DepthProcessBlock> d_process_block;
424 std::unique_ptr<RgbirdDepthResultProcessor> d_result_processor;
425 if (NeedDepthProcessBlock()) {
426 StreamConfiguration depth_chain_segment_stream_config;
427 status_t res =
428 MakeDepthStreamConfig(*rt_process_block_stream_config, stream_config,
429 &depth_chain_segment_stream_config);
430 if (res != OK) {
431 ALOGE(
432 "%s: Making depth chain segment stream configuration failed: "
433 "%s(%d).",
434 __FUNCTION__, strerror(-res), res);
435 return res;
436 }
437
438 StreamConfiguration depth_block_stream_config;
439 res = CreateDepthChainSegment(&d_process_block, &d_result_processor,
440 realtime_result_processor,
441 depth_chain_segment_stream_config,
442 stream_config, &depth_block_stream_config);
443 if (res != OK) {
444 ALOGE("%s: Creating depth chain segment failed: %s(%d).", __FUNCTION__,
445 strerror(-res), res);
446 return res;
447 }
448
449 // process_block_stream_config may contain internal streams(some may be
450 // duplicated as both input and output for bridging the rt and depth
451 // segments of the realtime process chain.)
452 rt_process_block_stream_config->streams.insert(
453 rt_process_block_stream_config->streams.end(),
454 depth_block_stream_config.streams.begin(),
455 depth_block_stream_config.streams.end());
456
457 *depth_process_block = std::move(d_process_block);
458 *depth_result_processor = std::move(d_result_processor);
459 }
460
461 return OK;
462 }
463
MakeDepthStreamConfig(const StreamConfiguration & rt_process_block_stream_config,const StreamConfiguration & stream_config,StreamConfiguration * depth_stream_config)464 status_t RgbirdCaptureSession::MakeDepthStreamConfig(
465 const StreamConfiguration& rt_process_block_stream_config,
466 const StreamConfiguration& stream_config,
467 StreamConfiguration* depth_stream_config) {
468 ATRACE_CALL();
469 if (depth_stream_config == nullptr) {
470 ALOGE("%s: depth_stream_config is nullptr", __FUNCTION__);
471 return BAD_VALUE;
472 }
473
474 if (!NeedDepthProcessBlock()) {
475 ALOGE("%s: No need to create depth process chain segment stream config.",
476 __FUNCTION__);
477 return BAD_VALUE;
478 }
479
480 // Assuming all internal streams must be for depth process block as input,
481 // if depth stream is configured by framework.
482 depth_stream_config->operation_mode = stream_config.operation_mode;
483 depth_stream_config->session_params =
484 HalCameraMetadata::Clone(stream_config.session_params.get());
485 depth_stream_config->stream_config_counter =
486 stream_config.stream_config_counter;
487 depth_stream_config->streams = stream_config.streams;
488 for (auto& stream : rt_process_block_stream_config.streams) {
489 bool is_internal_stream = true;
490 for (auto& framework_stream : stream_config.streams) {
491 if (stream.id == framework_stream.id) {
492 is_internal_stream = false;
493 break;
494 }
495 }
496
497 // Change all internal streams to input streams and keep others untouched
498 if (is_internal_stream) {
499 Stream input_stream = stream;
500 input_stream.stream_type = StreamType::kInput;
501 depth_stream_config->streams.push_back(input_stream);
502 }
503 }
504
505 return OK;
506 }
507
SetupRealtimeProcessChain(const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::unique_ptr<ProcessBlock> * realtime_process_block,std::unique_ptr<RgbirdResultRequestProcessor> * realtime_result_processor,std::unique_ptr<ProcessBlock> * depth_process_block,std::unique_ptr<ResultProcessor> * depth_result_processor)508 status_t RgbirdCaptureSession::SetupRealtimeProcessChain(
509 const StreamConfiguration& stream_config,
510 ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
511 std::unique_ptr<ProcessBlock>* realtime_process_block,
512 std::unique_ptr<RgbirdResultRequestProcessor>* realtime_result_processor,
513 std::unique_ptr<ProcessBlock>* depth_process_block,
514 std::unique_ptr<ResultProcessor>* depth_result_processor) {
515 ATRACE_CALL();
516 if (realtime_process_block == nullptr ||
517 realtime_result_processor == nullptr) {
518 ALOGE("%s: realtime_process_block(%p) or realtime_result_processor(%p) or ",
519 __FUNCTION__, realtime_process_block, realtime_result_processor);
520 return BAD_VALUE;
521 }
522
523 auto rt_process_block = MultiCameraRtProcessBlock::Create(device_session_hwl_);
524 if (rt_process_block == nullptr) {
525 ALOGE("%s: Creating RealtimeProcessBlock failed.", __FUNCTION__);
526 return UNKNOWN_ERROR;
527 }
528
529 // TODO(b/128632740): Create and connect depth process block.
530 rt_request_processor_ = RgbirdRtRequestProcessor::Create(
531 device_session_hwl_, is_hdrplus_supported_);
532 if (rt_request_processor_ == nullptr) {
533 ALOGE("%s: Creating RealtimeZslsRequestProcessor failed.", __FUNCTION__);
534 return UNKNOWN_ERROR;
535 }
536
537 StreamConfiguration process_block_stream_config;
538 status_t res =
539 ConfigureStreams(stream_config, rt_request_processor_.get(),
540 rt_process_block.get(), &process_block_stream_config);
541 if (res != OK) {
542 ALOGE("%s: Configuring stream failed: %s(%d)", __FUNCTION__, strerror(-res),
543 res);
544 return res;
545 }
546
547 if (is_hdrplus_supported_) {
548 res = ConfigureHdrplusRawStreamId(process_block_stream_config);
549 if (res != OK) {
550 ALOGE("%s: ConfigureHdrplusRawStreamId failed: %s(%d)", __FUNCTION__,
551 strerror(-res), res);
552 return res;
553 }
554 }
555
556 if (has_depth_stream_) {
557 res = SetDepthInternalStreamId(process_block_stream_config, stream_config);
558 if (res != OK) {
559 ALOGE("%s: ConfigureDepthOnlyRawStreamId failed: %s(%d)", __FUNCTION__,
560 strerror(-res), res);
561 return res;
562 }
563 }
564
565 // Create realtime result processor.
566 RgbirdResultRequestProcessor::RgbirdResultRequestProcessorCreateData data = {
567 .rgb_camera_id = rgb_camera_id_,
568 .ir1_camera_id = ir1_camera_id_,
569 .ir2_camera_id = ir2_camera_id_,
570 .rgb_raw_stream_id = rgb_raw_stream_id_,
571 .is_hdrplus_supported = is_hdrplus_supported_,
572 .rgb_internal_yuv_stream_id = rgb_internal_yuv_stream_id_};
573 auto rt_result_processor = RgbirdResultRequestProcessor::Create(data);
574 if (rt_result_processor == nullptr) {
575 ALOGE("%s: Creating RgbirdResultRequestProcessor failed.", __FUNCTION__);
576 return UNKNOWN_ERROR;
577 }
578 rt_result_processor->SetResultCallback(
579 process_capture_result, notify, /*process_batch_capture_result=*/nullptr);
580
581 if (is_hdrplus_supported_) {
582 res = rt_result_processor->ConfigureStreams(internal_stream_manager_.get(),
583 stream_config,
584 &process_block_stream_config);
585 if (res != OK) {
586 ALOGE("%s: Configuring streams for ResultRequestProcessor failed: %s(%d)",
587 __FUNCTION__, strerror(-res), res);
588 return res;
589 }
590 }
591
592 res = SetupDepthChainSegment(stream_config, rt_result_processor.get(),
593 depth_process_block, depth_result_processor,
594 &process_block_stream_config);
595 if (res != OK) {
596 ALOGE("%s: Failed to setup depth chain segment.", __FUNCTION__);
597 return UNKNOWN_ERROR;
598 }
599
600 // TODO(b/128632740): Remove force internal flag after depth block is in place
601 // and the FLL sync is verified.
602 // This should be done after depth process block stream
603 // configuration.
604 if (!AreAllStreamsConfigured(stream_config, process_block_stream_config) &&
605 !force_internal_stream_) {
606 // TODO(b/127322570): Handle the case where RT request processor configures
607 // internal streams for depth.
608 ALOGE("%s: Not all streams are configured.", __FUNCTION__);
609 return INVALID_OPERATION;
610 }
611
612 *realtime_process_block = std::move(rt_process_block);
613 *realtime_result_processor = std::move(rt_result_processor);
614
615 return OK;
616 }
617
SetupHdrplusProcessChain(const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::unique_ptr<ProcessBlock> * hdrplus_process_block,std::unique_ptr<ResultProcessor> * hdrplus_result_processor)618 status_t RgbirdCaptureSession::SetupHdrplusProcessChain(
619 const StreamConfiguration& stream_config,
620 ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
621 std::unique_ptr<ProcessBlock>* hdrplus_process_block,
622 std::unique_ptr<ResultProcessor>* hdrplus_result_processor) {
623 ATRACE_CALL();
624 if (hdrplus_process_block == nullptr || hdrplus_result_processor == nullptr) {
625 ALOGE(
626 "%s: hdrplus_process_block(%p) or hdrplus_result_processor(%p) is "
627 "nullptr",
628 __FUNCTION__, hdrplus_process_block, hdrplus_result_processor);
629 return BAD_VALUE;
630 }
631
632 // Create hdrplus process block.
633 std::vector<uint32_t> physical_camera_ids =
634 device_session_hwl_->GetPhysicalCameraIds();
635 // TODO: Check the static metadata and determine which one is rgb camera
636 auto process_block =
637 HdrplusProcessBlock::Create(device_session_hwl_, physical_camera_ids[0]);
638 if (process_block == nullptr) {
639 ALOGE("%s: Creating HdrplusProcessBlock failed.", __FUNCTION__);
640 return UNKNOWN_ERROR;
641 }
642
643 // Create hdrplus request processor.
644 hdrplus_request_processor_ = HdrplusRequestProcessor::Create(
645 device_session_hwl_, rgb_raw_stream_id_, physical_camera_ids[0]);
646 if (hdrplus_request_processor_ == nullptr) {
647 ALOGE("%s: Creating HdrplusRequestProcessor failed.", __FUNCTION__);
648 return UNKNOWN_ERROR;
649 }
650
651 // Create hdrplus result processor.
652 auto result_processor = HdrplusResultProcessor::Create(
653 internal_stream_manager_.get(), rgb_raw_stream_id_);
654 if (result_processor == nullptr) {
655 ALOGE("%s: Creating HdrplusResultProcessor failed.", __FUNCTION__);
656 return UNKNOWN_ERROR;
657 }
658 result_processor->SetResultCallback(process_capture_result, notify,
659 /*process_batch_capture_result=*/nullptr);
660
661 StreamConfiguration process_block_stream_config;
662 status_t res =
663 ConfigureStreams(stream_config, hdrplus_request_processor_.get(),
664 process_block.get(), &process_block_stream_config);
665 if (res != OK) {
666 ALOGE("%s: Configuring hdrplus stream failed: %s(%d)", __FUNCTION__,
667 strerror(-res), res);
668 return res;
669 }
670
671 *hdrplus_process_block = std::move(process_block);
672 *hdrplus_result_processor = std::move(result_processor);
673
674 return OK;
675 }
676
CreateProcessChain(const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::vector<HalStream> * hal_configured_streams)677 status_t RgbirdCaptureSession::CreateProcessChain(
678 const StreamConfiguration& stream_config,
679 ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
680 std::vector<HalStream>* hal_configured_streams) {
681 ATRACE_CALL();
682 // Setup realtime process chain
683 std::unique_ptr<ProcessBlock> realtime_process_block;
684 std::unique_ptr<RgbirdResultRequestProcessor> realtime_result_processor;
685 std::unique_ptr<ProcessBlock> depth_process_block;
686 std::unique_ptr<ResultProcessor> depth_result_processor;
687
688 status_t res = SetupRealtimeProcessChain(
689 stream_config, process_capture_result, notify, &realtime_process_block,
690 &realtime_result_processor, &depth_process_block, &depth_result_processor);
691 if (res != OK) {
692 ALOGE("%s: SetupRealtimeProcessChain fail: %s(%d)", __FUNCTION__,
693 strerror(-res), res);
694 return res;
695 }
696
697 // Setup hdrplus process chain
698 std::unique_ptr<ProcessBlock> hdrplus_process_block;
699 std::unique_ptr<ResultProcessor> hdrplus_result_processor;
700 if (is_hdrplus_supported_) {
701 res = SetupHdrplusProcessChain(stream_config, process_capture_result,
702 notify, &hdrplus_process_block,
703 &hdrplus_result_processor);
704 if (res != OK) {
705 ALOGE("%s: SetupHdrplusProcessChain fail: %s(%d)", __FUNCTION__,
706 strerror(-res), res);
707 return res;
708 }
709 }
710 // Realtime and HDR+ streams are configured
711 // Start to build pipleline
712 res = BuildPipelines(stream_config, realtime_process_block.get(),
713 depth_process_block.get(), hdrplus_process_block.get(),
714 hal_configured_streams);
715 if (res != OK) {
716 ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res),
717 res);
718 return res;
719 }
720
721 // Connecting the depth segment of the realtime process chain.
722 if (NeedDepthProcessBlock()) {
723 depth_result_processor->SetResultCallback(
724 process_capture_result, notify,
725 /*process_batch_capture_result=*/nullptr);
726
727 res = ConnectProcessChain(realtime_result_processor.get(),
728 std::move(depth_process_block),
729 std::move(depth_result_processor));
730 if (res != OK) {
731 ALOGE("%s: Connecting depth segment of realtime chain failed: %s(%d)",
732 __FUNCTION__, strerror(-res), res);
733 return res;
734 }
735 }
736
737 // Connect realtime process chain
738 res = ConnectProcessChain(rt_request_processor_.get(),
739 std::move(realtime_process_block),
740 std::move(realtime_result_processor));
741 if (res != OK) {
742 ALOGE("%s: Connecting process chain failed: %s(%d)", __FUNCTION__,
743 strerror(-res), res);
744 return res;
745 }
746
747 if (is_hdrplus_supported_) {
748 // Connect HDR+ process chain
749 res = ConnectProcessChain(hdrplus_request_processor_.get(),
750 std::move(hdrplus_process_block),
751 std::move(hdrplus_result_processor));
752 if (res != OK) {
753 ALOGE("%s: Connecting HDR+ process chain failed: %s(%d)", __FUNCTION__,
754 strerror(-res), res);
755 return res;
756 }
757 }
758 return OK;
759 }
760
ConnectProcessChain(RequestProcessor * request_processor,std::unique_ptr<ProcessBlock> process_block,std::unique_ptr<ResultProcessor> result_processor)761 status_t RgbirdCaptureSession::ConnectProcessChain(
762 RequestProcessor* request_processor,
763 std::unique_ptr<ProcessBlock> process_block,
764 std::unique_ptr<ResultProcessor> result_processor) {
765 ATRACE_CALL();
766 if (request_processor == nullptr) {
767 ALOGE("%s: request_processor is nullptr", __FUNCTION__);
768 return BAD_VALUE;
769 }
770
771 status_t res = process_block->SetResultProcessor(std::move(result_processor));
772 if (res != OK) {
773 ALOGE("%s: Setting result process in process block failed.", __FUNCTION__);
774 return res;
775 }
776
777 res = request_processor->SetProcessBlock(std::move(process_block));
778 if (res != OK) {
779 ALOGE("%s: Setting process block for request processor failed: %s(%d)",
780 __FUNCTION__, strerror(-res), res);
781 return res;
782 }
783
784 return OK;
785 }
786
ConfigureHdrplusUsageAndBuffers(std::vector<HalStream> * hal_configured_streams,std::vector<HalStream> * hdrplus_hal_configured_streams)787 status_t RgbirdCaptureSession::ConfigureHdrplusUsageAndBuffers(
788 std::vector<HalStream>* hal_configured_streams,
789 std::vector<HalStream>* hdrplus_hal_configured_streams) {
790 ATRACE_CALL();
791 if (hal_configured_streams == nullptr ||
792 hdrplus_hal_configured_streams == nullptr) {
793 ALOGE(
794 "%s: hal_configured_streams (%p) or hdrplus_hal_configured_streams "
795 "(%p) is nullptr",
796 __FUNCTION__, hal_configured_streams, hdrplus_hal_configured_streams);
797 return BAD_VALUE;
798 }
799 // Combine realtime and HDR+ hal stream.
800 // Only usage of internal raw stream is different, so combine usage directly
801 uint64_t consumer_usage = 0;
802 for (uint32_t i = 0; i < (*hdrplus_hal_configured_streams).size(); i++) {
803 if (hdrplus_hal_configured_streams->at(i).override_format ==
804 kHdrplusRawFormat &&
805 hdrplus_hal_configured_streams->at(i).id == rgb_raw_stream_id_) {
806 consumer_usage = hdrplus_hal_configured_streams->at(i).consumer_usage;
807 break;
808 }
809 }
810
811 for (uint32_t i = 0; i < hal_configured_streams->size(); i++) {
812 if (hal_configured_streams->at(i).override_format == kHdrplusRawFormat &&
813 hal_configured_streams->at(i).id == rgb_raw_stream_id_) {
814 hal_configured_streams->at(i).consumer_usage = consumer_usage;
815 // Allocate internal raw stream buffers
816 if (hal_configured_streams->at(i).max_buffers < kRgbMinRawBufferCount) {
817 hal_configured_streams->at(i).max_buffers = kRgbMinRawBufferCount;
818 }
819
820 uint32_t additional_num_buffers =
821 (hal_configured_streams->at(i).max_buffers >= kRgbRawBufferCount)
822 ? 0
823 : (kRgbRawBufferCount - hal_configured_streams->at(i).max_buffers);
824 status_t res = internal_stream_manager_->AllocateBuffers(
825 hal_configured_streams->at(i), additional_num_buffers);
826 if (res != OK) {
827 ALOGE("%s: AllocateBuffers failed.", __FUNCTION__);
828 return UNKNOWN_ERROR;
829 }
830 break;
831 }
832 }
833
834 return OK;
835 }
836
BuildPipelines(const StreamConfiguration & stream_config,ProcessBlock * realtime_process_block,ProcessBlock * depth_process_block,ProcessBlock * hdrplus_process_block,std::vector<HalStream> * hal_configured_streams)837 status_t RgbirdCaptureSession::BuildPipelines(
838 const StreamConfiguration& stream_config,
839 ProcessBlock* realtime_process_block, ProcessBlock* depth_process_block,
840 ProcessBlock* hdrplus_process_block,
841 std::vector<HalStream>* hal_configured_streams) {
842 ATRACE_CALL();
843 if (realtime_process_block == nullptr) {
844 ALOGE("%s: realtime_process_block (%p) is nullptr", __FUNCTION__,
845 realtime_process_block);
846 return BAD_VALUE;
847 }
848
849 if (depth_process_block == nullptr && has_depth_stream_) {
850 ALOGE("%s: depth_process_block (%p) is nullptr", __FUNCTION__,
851 depth_process_block);
852 return BAD_VALUE;
853 }
854
855 if (hal_configured_streams == nullptr) {
856 ALOGE("%s: hal_configured_streams (%p) is nullptr", __FUNCTION__,
857 hal_configured_streams);
858 return BAD_VALUE;
859 }
860
861 if (is_hdrplus_supported_ && hdrplus_process_block == nullptr) {
862 ALOGE("%s: hdrplus_process_block is nullptr", __FUNCTION__);
863 return BAD_VALUE;
864 }
865
866 status_t res = device_session_hwl_->BuildPipelines();
867 if (res != OK) {
868 ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res),
869 res);
870 return res;
871 }
872
873 res = realtime_process_block->GetConfiguredHalStreams(hal_configured_streams);
874 if (res != OK) {
875 ALOGE("%s: Getting HAL streams failed: %s(%d)", __FUNCTION__,
876 strerror(-res), res);
877 return res;
878 }
879
880 res = AllocateInternalBuffers(stream_config, hal_configured_streams,
881 hdrplus_process_block);
882
883 // Need to update hal_configured_streams if there is a depth stream
884 std::vector<HalStream> depth_streams;
885 if (has_depth_stream_) {
886 res = depth_process_block->GetConfiguredHalStreams(&depth_streams);
887 if (res != OK) {
888 ALOGE("%s: Failed to get configured hal streams from DepthProcessBlock",
889 __FUNCTION__);
890 return UNKNOWN_ERROR;
891 }
892
893 // Depth Process Block can only configure one depth stream so far
894 if (depth_streams.size() != 1) {
895 ALOGE("%s: DepthProcessBlock configured more than one stream.",
896 __FUNCTION__);
897 return UNKNOWN_ERROR;
898 }
899
900 hal_configured_streams->push_back(depth_streams[0]);
901 }
902
903 if (res != OK) {
904 ALOGE("%s: Allocating buffer for internal stream managers failed: %s(%d)",
905 __FUNCTION__, strerror(-res), res);
906 return res;
907 }
908
909 hal_utils::DumpHalConfiguredStreams(*hal_configured_streams,
910 "hal_configured_streams BEFORE purge");
911
912 // TODO(b/128633958): cover the streams Depth PB processes
913 res = PurgeHalConfiguredStream(stream_config, hal_configured_streams);
914 if (res != OK) {
915 ALOGE("%s: Removing internal streams from configured stream failed: %s(%d)",
916 __FUNCTION__, strerror(-res), res);
917 return res;
918 }
919
920 hal_utils::DumpHalConfiguredStreams(*hal_configured_streams,
921 "hal_configured_streams AFTER purge");
922
923 return OK;
924 }
925
InitializeCameraIds(CameraDeviceSessionHwl * device_session_hwl)926 status_t RgbirdCaptureSession::InitializeCameraIds(
927 CameraDeviceSessionHwl* device_session_hwl) {
928 ATRACE_CALL();
929 if (device_session_hwl == nullptr) {
930 ALOGE("%s: Device session hwl is null.", __FUNCTION__);
931 return BAD_VALUE;
932 }
933
934 std::vector<uint32_t> physical_camera_ids =
935 device_session_hwl->GetPhysicalCameraIds();
936 if (physical_camera_ids.size() != 3) {
937 ALOGE("%s: Failed to initialize camera ids. Only support 3 cameras",
938 __FUNCTION__);
939 return UNKNOWN_ERROR;
940 }
941
942 // TODO(b/127322570): Figure out physical camera IDs from static metadata.
943 rgb_camera_id_ = physical_camera_ids[0];
944 ir1_camera_id_ = physical_camera_ids[1];
945 ir2_camera_id_ = physical_camera_ids[2];
946 return OK;
947 }
948
Initialize(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,HwlRequestBuffersFunc request_stream_buffers,std::vector<HalStream> * hal_configured_streams)949 status_t RgbirdCaptureSession::Initialize(
950 CameraDeviceSessionHwl* device_session_hwl,
951 const StreamConfiguration& stream_config,
952 ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
953 HwlRequestBuffersFunc request_stream_buffers,
954 std::vector<HalStream>* hal_configured_streams) {
955 ATRACE_CALL();
956 if (!IsStreamConfigurationSupported(device_session_hwl, stream_config)) {
957 ALOGE("%s: stream configuration is not supported.", __FUNCTION__);
958 return BAD_VALUE;
959 }
960
961 // TODO(b/128633958): remove this after FLL syncing is verified
962 force_internal_stream_ =
963 property_get_bool("persist.vendor.camera.rgbird.forceinternal", false);
964 if (force_internal_stream_) {
965 ALOGI("%s: Force creating internal streams for IR pipelines", __FUNCTION__);
966 }
967
968 device_session_hwl_ = device_session_hwl;
969 internal_stream_manager_ = InternalStreamManager::Create();
970 if (internal_stream_manager_ == nullptr) {
971 ALOGE("%s: Cannot create internal stream manager.", __FUNCTION__);
972 return UNKNOWN_ERROR;
973 }
974
975 std::unique_ptr<HalCameraMetadata> characteristics;
976 status_t res = device_session_hwl->GetCameraCharacteristics(&characteristics);
977 if (res != OK) {
978 ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
979 return BAD_VALUE;
980 }
981
982 is_hdrplus_supported_ = hal_utils::IsStreamHdrplusCompatible(
983 stream_config, characteristics.get());
984
985 if (is_hdrplus_supported_) {
986 for (auto stream : stream_config.streams) {
987 if (utils::IsPreviewStream(stream)) {
988 hal_preview_stream_id_ = stream.id;
989 break;
990 }
991 }
992 }
993
994 // Create result dispatcher
995 result_dispatcher_ =
996 ResultDispatcher::Create(kPartialResult, process_capture_result,
997 /*process_batch_capture_result=*/nullptr, notify,
998 stream_config, "RgbirdDispatcher");
999 if (result_dispatcher_ == nullptr) {
1000 ALOGE("%s: Cannot create result dispatcher.", __FUNCTION__);
1001 return UNKNOWN_ERROR;
1002 }
1003
1004 // Reroute callback functions
1005 device_session_notify_ = notify;
1006 process_capture_result_ =
1007 ProcessCaptureResultFunc([this](std::unique_ptr<CaptureResult> result) {
1008 ProcessCaptureResult(std::move(result));
1009 });
1010 notify_ = NotifyFunc(
1011 [this](const NotifyMessage& message) { NotifyHalMessage(message); });
1012 request_stream_buffers_ = request_stream_buffers;
1013
1014 // Initialize physical camera ids
1015 res = InitializeCameraIds(device_session_hwl_);
1016 if (res != OK) {
1017 ALOGE("%s: Initializing camera ids failed: %s(%d)", __FUNCTION__,
1018 strerror(-res), res);
1019 return res;
1020 }
1021
1022 for (auto& stream : stream_config.streams) {
1023 if (utils::IsDepthStream(stream)) {
1024 ALOGI("%s: Depth stream exists in the stream config.", __FUNCTION__);
1025 has_depth_stream_ = true;
1026 }
1027 }
1028
1029 // Finally create the process chains
1030 res = CreateProcessChain(stream_config, process_capture_result_, notify_,
1031 hal_configured_streams);
1032 if (res != OK) {
1033 ALOGE("%s: Creating the process chain failed: %s(%d)", __FUNCTION__,
1034 strerror(-res), res);
1035 return res;
1036 }
1037
1038 return OK;
1039 }
1040
ProcessRequest(const CaptureRequest & request)1041 status_t RgbirdCaptureSession::ProcessRequest(const CaptureRequest& request) {
1042 ATRACE_CALL();
1043 bool is_hdrplus_request = false;
1044 if (is_hdrplus_supported_) {
1045 is_hdrplus_request =
1046 hal_utils::IsRequestHdrplusCompatible(request, hal_preview_stream_id_);
1047 // TODO: Check if request is HDR+ request when contains a depth buffer
1048 }
1049
1050 status_t res = result_dispatcher_->AddPendingRequest(request);
1051 if (res != OK) {
1052 ALOGE("%s: frame(%d) fail to AddPendingRequest", __FUNCTION__,
1053 request.frame_number);
1054 return BAD_VALUE;
1055 }
1056
1057 if (is_hdrplus_request) {
1058 ALOGI("%s: hdrplus snapshot (%d), output stream size:%zu", __FUNCTION__,
1059 request.frame_number, request.output_buffers.size());
1060 res = hdrplus_request_processor_->ProcessRequest(request);
1061 if (res != OK) {
1062 ALOGI("%s: hdrplus snapshot frame(%d) request to realtime process",
1063 __FUNCTION__, request.frame_number);
1064 res = rt_request_processor_->ProcessRequest(request);
1065 }
1066 } else {
1067 res = rt_request_processor_->ProcessRequest(request);
1068 }
1069
1070 if (res != OK) {
1071 ALOGE("%s: ProcessRequest (%d) fail and remove pending request",
1072 __FUNCTION__, request.frame_number);
1073 result_dispatcher_->RemovePendingRequest(request.frame_number);
1074 }
1075 return res;
1076 }
1077
Flush()1078 status_t RgbirdCaptureSession::Flush() {
1079 ATRACE_CALL();
1080 return rt_request_processor_->Flush();
1081 }
1082
ProcessCaptureResult(std::unique_ptr<CaptureResult> result)1083 void RgbirdCaptureSession::ProcessCaptureResult(
1084 std::unique_ptr<CaptureResult> result) {
1085 ATRACE_CALL();
1086 std::lock_guard<std::mutex> lock(callback_lock_);
1087 status_t res = result_dispatcher_->AddResult(std::move(result));
1088 if (res != OK) {
1089 ALOGE("%s: fail to AddResult", __FUNCTION__);
1090 return;
1091 }
1092 }
1093
NotifyHalMessage(const NotifyMessage & message)1094 void RgbirdCaptureSession::NotifyHalMessage(const NotifyMessage& message) {
1095 ATRACE_CALL();
1096 std::lock_guard<std::mutex> lock(callback_lock_);
1097 if (device_session_notify_ == nullptr) {
1098 ALOGE("%s: device_session_notify_ is nullptr. Dropping a message.",
1099 __FUNCTION__);
1100 return;
1101 }
1102
1103 if (message.type == MessageType::kShutter) {
1104 status_t res = result_dispatcher_->AddShutter(
1105 message.message.shutter.frame_number,
1106 message.message.shutter.timestamp_ns,
1107 message.message.shutter.readout_timestamp_ns);
1108 if (res != OK) {
1109 ALOGE("%s: frame(%d) fail to AddShutter", __FUNCTION__,
1110 message.message.shutter.frame_number);
1111 return;
1112 }
1113 } else if (message.type == MessageType::kError) {
1114 // drop the error notifications for the internal streams
1115 auto error_stream_id = message.message.error.error_stream_id;
1116 if (has_depth_stream_ &&
1117 message.message.error.error_code == ErrorCode::kErrorBuffer &&
1118 error_stream_id != kInvalidStreamId &&
1119 (error_stream_id == rgb_internal_yuv_stream_id_ ||
1120 error_stream_id == ir1_internal_raw_stream_id_ ||
1121 error_stream_id == ir2_internal_raw_stream_id_)) {
1122 return;
1123 }
1124
1125 status_t res = result_dispatcher_->AddError(message.message.error);
1126 if (res != OK) {
1127 ALOGE("%s: AddError for frame %u failed: %s (%d).", __FUNCTION__,
1128 message.message.error.frame_number, strerror(-res), res);
1129 return;
1130 }
1131 } else {
1132 ALOGW("%s: Unsupported message type: %u", __FUNCTION__, message.type);
1133 device_session_notify_(message);
1134 }
1135 }
1136 } // namespace google_camera_hal
1137 } // namespace android
1138