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