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