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