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_ResultDispatcher"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include "result_dispatcher.h"
21
22 #include <inttypes.h>
23 #include <log/log.h>
24 #include <sys/resource.h>
25 #include <utils/Trace.h>
26
27 #include <string>
28 #include <string_view>
29
30 #include "utils.h"
31
32 namespace android {
33 namespace google_camera_hal {
34
Create(uint32_t partial_result_count,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,const StreamConfiguration & stream_config,std::string_view name)35 std::unique_ptr<ResultDispatcher> ResultDispatcher::Create(
36 uint32_t partial_result_count,
37 ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
38 const StreamConfiguration& stream_config, std::string_view name) {
39 ATRACE_CALL();
40 auto dispatcher = std::unique_ptr<ResultDispatcher>(
41 new ResultDispatcher(partial_result_count, process_capture_result, notify,
42 stream_config, name));
43 if (dispatcher == nullptr) {
44 ALOGE("[%s] %s: Creating ResultDispatcher failed.",
45 std::string(name).c_str(), __FUNCTION__);
46 return nullptr;
47 }
48
49 return dispatcher;
50 }
51
ResultDispatcher(uint32_t partial_result_count,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,const StreamConfiguration & stream_config,std::string_view name)52 ResultDispatcher::ResultDispatcher(
53 uint32_t partial_result_count,
54 ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
55 const StreamConfiguration& stream_config, std::string_view name)
56 : kPartialResultCount(partial_result_count),
57 name_(name),
58 process_capture_result_(process_capture_result),
59 notify_(notify) {
60 ATRACE_CALL();
61 notify_callback_thread_ =
62 std::thread([this] { this->NotifyCallbackThreadLoop(); });
63
64 // Assign higher priority to reduce the preemption when CPU usage is high
65 //
66 // As from b/295977499, we need to make it realtime for priority inheritance
67 // to avoid CameraServer thread being the bottleneck
68 status_t res =
69 utils::SetRealtimeThread(notify_callback_thread_.native_handle());
70 if (res != OK) {
71 ALOGE("[%s] %s: SetRealtimeThread fail", name_.c_str(), __FUNCTION__);
72 } else {
73 ALOGI("[%s] %s: SetRealtimeThread OK", name_.c_str(), __FUNCTION__);
74 }
75 InitializeGroupStreamIdsMap(stream_config);
76 }
77
~ResultDispatcher()78 ResultDispatcher::~ResultDispatcher() {
79 ATRACE_CALL();
80 {
81 std::unique_lock<std::mutex> lock(notify_callback_lock_);
82 notify_callback_thread_exiting_ = true;
83 }
84
85 notify_callback_condition_.notify_one();
86 notify_callback_thread_.join();
87 }
88
RemovePendingRequest(uint32_t frame_number)89 void ResultDispatcher::RemovePendingRequest(uint32_t frame_number) {
90 ATRACE_CALL();
91 std::lock_guard<std::mutex> lock(result_lock_);
92 RemovePendingRequestLocked(frame_number);
93 }
94
AddPendingRequest(const CaptureRequest & pending_request)95 status_t ResultDispatcher::AddPendingRequest(
96 const CaptureRequest& pending_request) {
97 ATRACE_CALL();
98 std::lock_guard<std::mutex> lock(result_lock_);
99
100 status_t res = AddPendingRequestLocked(pending_request);
101 if (res != OK) {
102 ALOGE("[%s] %s: Adding a pending request failed: %s(%d).", name_.c_str(),
103 __FUNCTION__, strerror(-res), res);
104 RemovePendingRequestLocked(pending_request.frame_number);
105 return res;
106 }
107
108 return OK;
109 }
110
AddPendingRequestLocked(const CaptureRequest & pending_request)111 status_t ResultDispatcher::AddPendingRequestLocked(
112 const CaptureRequest& pending_request) {
113 ATRACE_CALL();
114 uint32_t frame_number = pending_request.frame_number;
115
116 status_t res = AddPendingShutterLocked(frame_number);
117 if (res != OK) {
118 ALOGE("[%s] %s: Adding pending shutter for frame %u failed: %s(%d)",
119 name_.c_str(), __FUNCTION__, frame_number, strerror(-res), res);
120 return res;
121 }
122
123 res = AddPendingFinalResultMetadataLocked(frame_number);
124 if (res != OK) {
125 ALOGE("[%s] %s: Adding pending result metadata for frame %u failed: %s(%d)",
126 name_.c_str(), __FUNCTION__, frame_number, strerror(-res), res);
127 return res;
128 }
129
130 for (auto& buffer : pending_request.input_buffers) {
131 res = AddPendingBufferLocked(frame_number, buffer, /*is_input=*/true);
132 if (res != OK) {
133 ALOGE("[%s] %s: Adding pending input buffer for frame %u failed: %s(%d)",
134 name_.c_str(), __FUNCTION__, frame_number, strerror(-res), res);
135 return res;
136 }
137 }
138
139 for (auto& buffer : pending_request.output_buffers) {
140 res = AddPendingBufferLocked(frame_number, buffer, /*is_input=*/false);
141 if (res != OK) {
142 ALOGE("[%s] %s: Adding pending output buffer for frame %u failed: %s(%d)",
143 name_.c_str(), __FUNCTION__, frame_number, strerror(-res), res);
144 return res;
145 }
146 }
147
148 return OK;
149 }
150
AddPendingShutterLocked(uint32_t frame_number)151 status_t ResultDispatcher::AddPendingShutterLocked(uint32_t frame_number) {
152 ATRACE_CALL();
153 if (pending_shutters_.find(frame_number) != pending_shutters_.end()) {
154 ALOGE("[%s] %s: Pending shutter for frame %u already exists.",
155 name_.c_str(), __FUNCTION__, frame_number);
156 return ALREADY_EXISTS;
157 }
158
159 pending_shutters_[frame_number] = PendingShutter();
160 return OK;
161 }
162
AddPendingFinalResultMetadataLocked(uint32_t frame_number)163 status_t ResultDispatcher::AddPendingFinalResultMetadataLocked(
164 uint32_t frame_number) {
165 ATRACE_CALL();
166 if (pending_final_metadata_.find(frame_number) !=
167 pending_final_metadata_.end()) {
168 ALOGE("[%s] %s: Pending final result metadata for frame %u already exists.",
169 name_.c_str(), __FUNCTION__, frame_number);
170 return ALREADY_EXISTS;
171 }
172
173 pending_final_metadata_[frame_number] = PendingFinalResultMetadata();
174 return OK;
175 }
176
AddPendingBufferLocked(uint32_t frame_number,const StreamBuffer & buffer,bool is_input)177 status_t ResultDispatcher::AddPendingBufferLocked(uint32_t frame_number,
178 const StreamBuffer& buffer,
179 bool is_input) {
180 ATRACE_CALL();
181 StreamKey stream_key = CreateStreamKey(buffer.stream_id);
182 if (stream_pending_buffers_map_.find(stream_key) ==
183 stream_pending_buffers_map_.end()) {
184 stream_pending_buffers_map_[stream_key] =
185 std::map<uint32_t, PendingBuffer>();
186 }
187
188 if (stream_pending_buffers_map_[stream_key].find(frame_number) !=
189 stream_pending_buffers_map_[stream_key].end()) {
190 ALOGE("[%s] %s: Pending buffer of stream %s for frame %u already exists.",
191 name_.c_str(), __FUNCTION__, DumpStreamKey(stream_key).c_str(),
192 frame_number);
193 return ALREADY_EXISTS;
194 }
195
196 PendingBuffer pending_buffer = {.is_input = is_input};
197 stream_pending_buffers_map_[stream_key][frame_number] = pending_buffer;
198 return OK;
199 }
200
RemovePendingRequestLocked(uint32_t frame_number)201 void ResultDispatcher::RemovePendingRequestLocked(uint32_t frame_number) {
202 ATRACE_CALL();
203 pending_shutters_.erase(frame_number);
204 pending_final_metadata_.erase(frame_number);
205
206 for (auto& pending_buffers : stream_pending_buffers_map_) {
207 pending_buffers.second.erase(frame_number);
208 }
209 }
210
AddResult(std::unique_ptr<CaptureResult> result)211 status_t ResultDispatcher::AddResult(std::unique_ptr<CaptureResult> result) {
212 ATRACE_CALL();
213 status_t res;
214 bool failed = false;
215 uint32_t frame_number = result->frame_number;
216
217 if (result->result_metadata != nullptr) {
218 res = AddResultMetadata(frame_number, std::move(result->result_metadata),
219 std::move(result->physical_metadata),
220 result->partial_result);
221 if (res != OK) {
222 ALOGE("[%s] %s: Adding result metadata failed: %s (%d)", name_.c_str(),
223 __FUNCTION__, strerror(-res), res);
224 failed = true;
225 }
226 }
227
228 for (auto& buffer : result->output_buffers) {
229 res = AddBuffer(frame_number, buffer);
230 if (res != OK) {
231 ALOGE("[%s] %s: Adding an output buffer failed: %s (%d)", name_.c_str(),
232 __FUNCTION__, strerror(-res), res);
233 failed = true;
234 }
235 }
236
237 for (auto& buffer : result->input_buffers) {
238 res = AddBuffer(frame_number, buffer);
239 if (res != OK) {
240 ALOGE("[%s] %s: Adding an input buffer failed: %s (%d)", name_.c_str(),
241 __FUNCTION__, strerror(-res), res);
242 failed = true;
243 }
244 }
245 {
246 std::unique_lock<std::mutex> lock(notify_callback_lock_);
247 is_result_shutter_updated_ = true;
248 notify_callback_condition_.notify_one();
249 }
250 return failed ? UNKNOWN_ERROR : OK;
251 }
252
AddShutter(uint32_t frame_number,int64_t timestamp_ns,int64_t readout_timestamp_ns)253 status_t ResultDispatcher::AddShutter(uint32_t frame_number,
254 int64_t timestamp_ns,
255 int64_t readout_timestamp_ns) {
256 ATRACE_CALL();
257 {
258 std::lock_guard<std::mutex> lock(result_lock_);
259
260 auto shutter_it = pending_shutters_.find(frame_number);
261 if (shutter_it == pending_shutters_.end()) {
262 ALOGE("[%s] %s: Cannot find the pending shutter for frame %u",
263 name_.c_str(), __FUNCTION__, frame_number);
264 return NAME_NOT_FOUND;
265 }
266
267 if (shutter_it->second.ready) {
268 ALOGE("[%s] %s: Already received shutter (%" PRId64
269 ") for frame %u. New timestamp %" PRId64,
270 name_.c_str(), __FUNCTION__, shutter_it->second.timestamp_ns,
271 frame_number, timestamp_ns);
272 return ALREADY_EXISTS;
273 }
274
275 shutter_it->second.timestamp_ns = timestamp_ns;
276 shutter_it->second.readout_timestamp_ns = readout_timestamp_ns;
277 shutter_it->second.ready = true;
278 }
279 {
280 std::unique_lock<std::mutex> lock(notify_callback_lock_);
281 is_result_shutter_updated_ = true;
282 notify_callback_condition_.notify_one();
283 }
284 return OK;
285 }
286
AddError(const ErrorMessage & error)287 status_t ResultDispatcher::AddError(const ErrorMessage& error) {
288 ATRACE_CALL();
289 std::lock_guard<std::mutex> lock(result_lock_);
290 uint32_t frame_number = error.frame_number;
291 // No need to deliver the shutter message on an error
292 if (error.error_code == ErrorCode::kErrorDevice ||
293 error.error_code == ErrorCode::kErrorResult ||
294 error.error_code == ErrorCode::kErrorRequest) {
295 pending_shutters_.erase(frame_number);
296 }
297 // No need to deliver the result metadata on a result metadata error
298 if (error.error_code == ErrorCode::kErrorResult ||
299 error.error_code == ErrorCode::kErrorRequest) {
300 pending_final_metadata_.erase(frame_number);
301 }
302
303 NotifyMessage message = {.type = MessageType::kError, .message.error = error};
304 ALOGV("[%s] %s: Notify error %u for frame %u stream %d", name_.c_str(),
305 __FUNCTION__, error.error_code, frame_number, error.error_stream_id);
306 notify_(message);
307
308 return OK;
309 }
310
NotifyResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> metadata,std::vector<PhysicalCameraMetadata> physical_metadata,uint32_t partial_result)311 void ResultDispatcher::NotifyResultMetadata(
312 uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
313 std::vector<PhysicalCameraMetadata> physical_metadata,
314 uint32_t partial_result) {
315 ATRACE_CALL();
316 auto result = std::make_unique<CaptureResult>(CaptureResult({}));
317 result->frame_number = frame_number;
318 result->result_metadata = std::move(metadata);
319 result->physical_metadata = std::move(physical_metadata);
320 result->partial_result = partial_result;
321
322 std::lock_guard<std::mutex> lock(process_capture_result_lock_);
323 process_capture_result_(std::move(result));
324 }
325
AddFinalResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> final_metadata,std::vector<PhysicalCameraMetadata> physical_metadata)326 status_t ResultDispatcher::AddFinalResultMetadata(
327 uint32_t frame_number, std::unique_ptr<HalCameraMetadata> final_metadata,
328 std::vector<PhysicalCameraMetadata> physical_metadata) {
329 ATRACE_CALL();
330 std::lock_guard<std::mutex> lock(result_lock_);
331
332 auto metadata_it = pending_final_metadata_.find(frame_number);
333 if (metadata_it == pending_final_metadata_.end()) {
334 ALOGE("[%s] %s: Cannot find the pending result metadata for frame %u",
335 name_.c_str(), __FUNCTION__, frame_number);
336 return NAME_NOT_FOUND;
337 }
338
339 if (metadata_it->second.ready) {
340 ALOGE("[%s] %s: Already received final result metadata for frame %u.",
341 name_.c_str(), __FUNCTION__, frame_number);
342 return ALREADY_EXISTS;
343 }
344
345 metadata_it->second.metadata = std::move(final_metadata);
346 metadata_it->second.physical_metadata = std::move(physical_metadata);
347 metadata_it->second.ready = true;
348 return OK;
349 }
350
AddResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> metadata,std::vector<PhysicalCameraMetadata> physical_metadata,uint32_t partial_result)351 status_t ResultDispatcher::AddResultMetadata(
352 uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
353 std::vector<PhysicalCameraMetadata> physical_metadata,
354 uint32_t partial_result) {
355 ATRACE_CALL();
356 if (metadata == nullptr) {
357 ALOGE("[%s] %s: metadata is nullptr.", name_.c_str(), __FUNCTION__);
358 return BAD_VALUE;
359 }
360
361 if (partial_result > kPartialResultCount) {
362 ALOGE(
363 "[%s] %s: partial_result %u cannot be larger than partial result count "
364 "%u",
365 name_.c_str(), __FUNCTION__, partial_result, kPartialResultCount);
366 return BAD_VALUE;
367 }
368
369 if (partial_result < kPartialResultCount) {
370 // Send out partial results immediately.
371 NotifyResultMetadata(frame_number, std::move(metadata),
372 std::move(physical_metadata), partial_result);
373 return OK;
374 }
375
376 return AddFinalResultMetadata(frame_number, std::move(metadata),
377 std::move(physical_metadata));
378 }
379
AddBuffer(uint32_t frame_number,StreamBuffer buffer)380 status_t ResultDispatcher::AddBuffer(uint32_t frame_number,
381 StreamBuffer buffer) {
382 ATRACE_CALL();
383 std::lock_guard<std::mutex> lock(result_lock_);
384
385 StreamKey stream_key = CreateStreamKey(buffer.stream_id);
386 auto pending_buffers_it = stream_pending_buffers_map_.find(stream_key);
387 if (pending_buffers_it == stream_pending_buffers_map_.end()) {
388 ALOGE("[%s] %s: Cannot find the pending buffer for stream %s",
389 name_.c_str(), __FUNCTION__, DumpStreamKey(stream_key).c_str());
390 return NAME_NOT_FOUND;
391 }
392
393 auto pending_buffer_it = pending_buffers_it->second.find(frame_number);
394 if (pending_buffer_it == pending_buffers_it->second.end()) {
395 ALOGE("[%s] %s: Cannot find the pending buffer for stream %s for frame %u",
396 name_.c_str(), __FUNCTION__, DumpStreamKey(stream_key).c_str(),
397 frame_number);
398 return NAME_NOT_FOUND;
399 }
400
401 if (pending_buffer_it->second.ready) {
402 ALOGE("[%s] %s: Already received a buffer for stream %s for frame %u",
403 name_.c_str(), __FUNCTION__, DumpStreamKey(stream_key).c_str(),
404 frame_number);
405 return ALREADY_EXISTS;
406 }
407
408 pending_buffer_it->second.buffer = std::move(buffer);
409 pending_buffer_it->second.ready = true;
410
411 return OK;
412 }
413
NotifyCallbackThreadLoop()414 void ResultDispatcher::NotifyCallbackThreadLoop() {
415 // '\0' counts toward the 16-character restriction.
416 constexpr int kPthreadNameLenMinusOne = 16 - 1;
417 pthread_setname_np(
418 pthread_self(),
419 name_.substr(/*pos=*/0, /*count=*/kPthreadNameLenMinusOne).c_str());
420
421 while (1) {
422 NotifyShutters();
423 NotifyFinalResultMetadata();
424 NotifyBuffers();
425
426 std::unique_lock<std::mutex> lock(notify_callback_lock_);
427 if (notify_callback_thread_exiting_) {
428 ALOGV("[%s] %s: NotifyCallbackThreadLoop exits.", name_.c_str(),
429 __FUNCTION__);
430 return;
431 }
432 if (!is_result_shutter_updated_) {
433 if (notify_callback_condition_.wait_for(
434 lock, std::chrono::milliseconds(kCallbackThreadTimeoutMs)) ==
435 std::cv_status::timeout) {
436 PrintTimeoutMessages();
437 }
438 }
439 is_result_shutter_updated_ = false;
440 }
441 }
442
PrintTimeoutMessages()443 void ResultDispatcher::PrintTimeoutMessages() {
444 std::lock_guard<std::mutex> lock(result_lock_);
445 for (auto& [frame_number, shutter] : pending_shutters_) {
446 ALOGW("[%s] %s: pending shutter for frame %u ready %d", name_.c_str(),
447 __FUNCTION__, frame_number, shutter.ready);
448 }
449
450 for (auto& [frame_number, final_metadata] : pending_final_metadata_) {
451 ALOGW("[%s] %s: pending final result metadaata for frame %u ready %d",
452 name_.c_str(), __FUNCTION__, frame_number, final_metadata.ready);
453 }
454
455 for (auto& [stream_key, pending_buffers] : stream_pending_buffers_map_) {
456 for (auto& [frame_number, pending_buffer] : pending_buffers) {
457 ALOGW("[%s] %s: pending buffer of stream %s for frame %u ready %d",
458 name_.c_str(), __FUNCTION__, DumpStreamKey(stream_key).c_str(),
459 frame_number, pending_buffer.ready);
460 }
461 }
462 }
463
InitializeGroupStreamIdsMap(const StreamConfiguration & stream_config)464 void ResultDispatcher::InitializeGroupStreamIdsMap(
465 const StreamConfiguration& stream_config) {
466 std::lock_guard<std::mutex> lock(result_lock_);
467 for (const auto& stream : stream_config.streams) {
468 if (stream.group_id != -1) {
469 group_stream_map_[stream.id] = stream.group_id;
470 }
471 }
472 }
473
CreateStreamKey(int32_t stream_id) const474 ResultDispatcher::StreamKey ResultDispatcher::CreateStreamKey(
475 int32_t stream_id) const {
476 if (group_stream_map_.count(stream_id) == 0) {
477 return StreamKey(stream_id, StreamKeyType::kSingleStream);
478 } else {
479 return StreamKey(group_stream_map_.at(stream_id),
480 StreamKeyType::kGroupStream);
481 }
482 }
483
DumpStreamKey(const StreamKey & stream_key) const484 std::string ResultDispatcher::DumpStreamKey(const StreamKey& stream_key) const {
485 switch (stream_key.second) {
486 case StreamKeyType::kSingleStream:
487 return std::to_string(stream_key.first);
488 case StreamKeyType::kGroupStream:
489 return "group " + std::to_string(stream_key.first);
490 default:
491 return "Invalid stream key type";
492 }
493 }
494
GetReadyShutterMessage(NotifyMessage * message)495 status_t ResultDispatcher::GetReadyShutterMessage(NotifyMessage* message) {
496 ATRACE_CALL();
497 if (message == nullptr) {
498 ALOGE("[%s] %s: message is nullptr", name_.c_str(), __FUNCTION__);
499 return BAD_VALUE;
500 }
501
502 auto shutter_it = pending_shutters_.begin();
503 if (shutter_it == pending_shutters_.end() || !shutter_it->second.ready) {
504 // The first pending shutter is not ready.
505 return NAME_NOT_FOUND;
506 }
507
508 message->type = MessageType::kShutter;
509 message->message.shutter.frame_number = shutter_it->first;
510 message->message.shutter.timestamp_ns = shutter_it->second.timestamp_ns;
511 message->message.shutter.readout_timestamp_ns =
512 shutter_it->second.readout_timestamp_ns;
513 pending_shutters_.erase(shutter_it);
514
515 return OK;
516 }
517
NotifyShutters()518 void ResultDispatcher::NotifyShutters() {
519 ATRACE_CALL();
520 NotifyMessage message = {};
521 while (true) {
522 std::lock_guard<std::mutex> lock(result_lock_);
523 if (GetReadyShutterMessage(&message) != OK) {
524 break;
525 }
526 ALOGV("[%s] %s: Notify shutter for frame %u timestamp %" PRIu64
527 " readout_timestamp %" PRIu64,
528 name_.c_str(), __FUNCTION__, message.message.shutter.frame_number,
529 message.message.shutter.timestamp_ns,
530 message.message.shutter.readout_timestamp_ns);
531 notify_(message);
532 }
533 }
534
GetReadyFinalMetadata(uint32_t * frame_number,std::unique_ptr<HalCameraMetadata> * final_metadata,std::vector<PhysicalCameraMetadata> * physical_metadata)535 status_t ResultDispatcher::GetReadyFinalMetadata(
536 uint32_t* frame_number, std::unique_ptr<HalCameraMetadata>* final_metadata,
537 std::vector<PhysicalCameraMetadata>* physical_metadata) {
538 ATRACE_CALL();
539 if (final_metadata == nullptr || frame_number == nullptr) {
540 ALOGE("[%s] %s: final_metadata (%p) or frame_number (%p) is nullptr",
541 name_.c_str(), __FUNCTION__, final_metadata, frame_number);
542 return BAD_VALUE;
543 }
544
545 std::lock_guard<std::mutex> lock(result_lock_);
546
547 auto final_metadata_it = pending_final_metadata_.begin();
548 if (final_metadata_it == pending_final_metadata_.end() ||
549 !final_metadata_it->second.ready) {
550 // The first pending final metadata is not ready.
551 return NAME_NOT_FOUND;
552 }
553
554 *frame_number = final_metadata_it->first;
555 *final_metadata = std::move(final_metadata_it->second.metadata);
556 *physical_metadata = std::move(final_metadata_it->second.physical_metadata);
557 pending_final_metadata_.erase(final_metadata_it);
558
559 return OK;
560 }
561
NotifyFinalResultMetadata()562 void ResultDispatcher::NotifyFinalResultMetadata() {
563 ATRACE_CALL();
564 uint32_t frame_number;
565 std::unique_ptr<HalCameraMetadata> final_metadata;
566 std::vector<PhysicalCameraMetadata> physical_metadata;
567
568 while (GetReadyFinalMetadata(&frame_number, &final_metadata,
569 &physical_metadata) == OK) {
570 ALOGV("[%s] %s: Notify final metadata for frame %u", name_.c_str(),
571 __FUNCTION__, frame_number);
572 NotifyResultMetadata(frame_number, std::move(final_metadata),
573 std::move(physical_metadata), kPartialResultCount);
574 }
575 }
576
GetReadyBufferResult(std::unique_ptr<CaptureResult> * result)577 status_t ResultDispatcher::GetReadyBufferResult(
578 std::unique_ptr<CaptureResult>* result) {
579 ATRACE_CALL();
580 std::lock_guard<std::mutex> lock(result_lock_);
581 if (result == nullptr) {
582 ALOGE("[%s] %s: result is nullptr.", name_.c_str(), __FUNCTION__);
583 return BAD_VALUE;
584 }
585
586 *result = nullptr;
587
588 for (auto& pending_buffers : stream_pending_buffers_map_) {
589 auto buffer_it = pending_buffers.second.begin();
590 while (buffer_it != pending_buffers.second.end()) {
591 if (!buffer_it->second.ready) {
592 // No more buffer ready.
593 break;
594 }
595
596 auto buffer_result = std::make_unique<CaptureResult>(CaptureResult({}));
597
598 buffer_result->frame_number = buffer_it->first;
599 if (buffer_it->second.is_input) {
600 buffer_result->input_buffers.push_back(buffer_it->second.buffer);
601 } else {
602 buffer_result->output_buffers.push_back(buffer_it->second.buffer);
603 }
604
605 pending_buffers.second.erase(buffer_it);
606 *result = std::move(buffer_result);
607 return OK;
608 }
609 }
610
611 return NAME_NOT_FOUND;
612 }
613
NotifyBuffers()614 void ResultDispatcher::NotifyBuffers() {
615 ATRACE_CALL();
616 std::unique_ptr<CaptureResult> result;
617
618 while (GetReadyBufferResult(&result) == OK) {
619 if (result == nullptr) {
620 ALOGE("[%s] %s: result is nullptr", name_.c_str(), __FUNCTION__);
621 return;
622 }
623 std::lock_guard<std::mutex> lock(process_capture_result_lock_);
624 process_capture_result_(std::move(result));
625 }
626 }
627
628 } // namespace google_camera_hal
629 } // namespace android
630