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