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 error.error_code == ErrorCode::kErrorRequest) {
278 pending_shutters_.erase(frame_number);
279 }
280 // No need to deliver the result metadata on a result metadata error
281 if (error.error_code == ErrorCode::kErrorResult ||
282 error.error_code == ErrorCode::kErrorRequest) {
283 pending_final_metadata_.erase(frame_number);
284 }
285
286 NotifyMessage message = {.type = MessageType::kError, .message.error = error};
287 ALOGV("%s: Notify error %u for frame %u stream %d", __FUNCTION__,
288 error.error_code, frame_number, error.error_stream_id);
289 notify_(message);
290
291 return OK;
292 }
293
NotifyResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> metadata,std::vector<PhysicalCameraMetadata> physical_metadata,uint32_t partial_result)294 void ResultDispatcher::NotifyResultMetadata(
295 uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
296 std::vector<PhysicalCameraMetadata> physical_metadata,
297 uint32_t partial_result) {
298 ATRACE_CALL();
299 auto result = std::make_unique<CaptureResult>(CaptureResult({}));
300 result->frame_number = frame_number;
301 result->result_metadata = std::move(metadata);
302 result->physical_metadata = std::move(physical_metadata);
303 result->partial_result = partial_result;
304
305 std::lock_guard<std::mutex> lock(process_capture_result_lock_);
306 process_capture_result_(std::move(result));
307 }
308
AddFinalResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> final_metadata,std::vector<PhysicalCameraMetadata> physical_metadata)309 status_t ResultDispatcher::AddFinalResultMetadata(
310 uint32_t frame_number, std::unique_ptr<HalCameraMetadata> final_metadata,
311 std::vector<PhysicalCameraMetadata> physical_metadata) {
312 ATRACE_CALL();
313 std::lock_guard<std::mutex> lock(result_lock_);
314
315 auto metadata_it = pending_final_metadata_.find(frame_number);
316 if (metadata_it == pending_final_metadata_.end()) {
317 ALOGE("%s: Cannot find the pending result metadata for frame %u",
318 __FUNCTION__, frame_number);
319 return NAME_NOT_FOUND;
320 }
321
322 if (metadata_it->second.ready) {
323 ALOGE("%s: Already received final result metadata for frame %u.",
324 __FUNCTION__, frame_number);
325 return ALREADY_EXISTS;
326 }
327
328 metadata_it->second.metadata = std::move(final_metadata);
329 metadata_it->second.physical_metadata = std::move(physical_metadata);
330 metadata_it->second.ready = true;
331 return OK;
332 }
333
AddResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> metadata,std::vector<PhysicalCameraMetadata> physical_metadata,uint32_t partial_result)334 status_t ResultDispatcher::AddResultMetadata(
335 uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
336 std::vector<PhysicalCameraMetadata> physical_metadata,
337 uint32_t partial_result) {
338 ATRACE_CALL();
339 if (metadata == nullptr) {
340 ALOGE("%s: metadata is nullptr.", __FUNCTION__);
341 return BAD_VALUE;
342 }
343
344 if (partial_result > kPartialResultCount) {
345 ALOGE("%s: partial_result %u cannot be larger than partial result count %u",
346 __FUNCTION__, partial_result, kPartialResultCount);
347 return BAD_VALUE;
348 }
349
350 if (partial_result < kPartialResultCount) {
351 // Send out partial results immediately.
352 NotifyResultMetadata(frame_number, std::move(metadata),
353 std::move(physical_metadata), partial_result);
354 return OK;
355 }
356
357 return AddFinalResultMetadata(frame_number, std::move(metadata),
358 std::move(physical_metadata));
359 }
360
AddBuffer(uint32_t frame_number,StreamBuffer buffer)361 status_t ResultDispatcher::AddBuffer(uint32_t frame_number,
362 StreamBuffer buffer) {
363 ATRACE_CALL();
364 std::lock_guard<std::mutex> lock(result_lock_);
365
366 uint32_t stream_id = buffer.stream_id;
367 auto pending_buffers_it = stream_pending_buffers_map_.find(stream_id);
368 if (pending_buffers_it == stream_pending_buffers_map_.end()) {
369 ALOGE("%s: Cannot find the pending buffer for stream %u", __FUNCTION__,
370 stream_id);
371 return NAME_NOT_FOUND;
372 }
373
374 auto pending_buffer_it = pending_buffers_it->second.find(frame_number);
375 if (pending_buffer_it == pending_buffers_it->second.end()) {
376 ALOGE("%s: Cannot find the pending buffer for stream %u for frame %u",
377 __FUNCTION__, stream_id, frame_number);
378 return NAME_NOT_FOUND;
379 }
380
381 if (pending_buffer_it->second.ready) {
382 ALOGE("%s: Already received a buffer for stream %u for frame %u",
383 __FUNCTION__, stream_id, frame_number);
384 return ALREADY_EXISTS;
385 }
386
387 pending_buffer_it->second.buffer = std::move(buffer);
388 pending_buffer_it->second.ready = true;
389
390 return OK;
391 }
392
NotifyCallbackThreadLoop()393 void ResultDispatcher::NotifyCallbackThreadLoop() {
394 // max thread name len = 16
395 pthread_setname_np(pthread_self(), "ResDispatcher");
396
397 while (1) {
398 NotifyShutters();
399 NotifyFinalResultMetadata();
400 NotifyBuffers();
401
402 std::unique_lock<std::mutex> lock(notify_callback_lock_);
403 if (notify_callback_thread_exiting_) {
404 ALOGV("%s: NotifyCallbackThreadLoop exits.", __FUNCTION__);
405 return;
406 }
407 if (!is_result_shutter_updated_) {
408 if (notify_callback_condition_.wait_for(
409 lock, std::chrono::milliseconds(kCallbackThreadTimeoutMs)) ==
410 std::cv_status::timeout) {
411 PrintTimeoutMessages();
412 }
413 }
414 is_result_shutter_updated_ = false;
415 }
416 }
417
PrintTimeoutMessages()418 void ResultDispatcher::PrintTimeoutMessages() {
419 std::lock_guard<std::mutex> lock(result_lock_);
420 for (auto& [frame_number, shutter] : pending_shutters_) {
421 ALOGW("%s: pending shutter for frame %u ready %d", __FUNCTION__,
422 frame_number, shutter.ready);
423 }
424
425 for (auto& [frame_number, final_metadata] : pending_final_metadata_) {
426 ALOGW("%s: pending final result metadaata for frame %u ready %d",
427 __FUNCTION__, frame_number, final_metadata.ready);
428 }
429
430 for (auto& [stream_id, pending_buffers] : stream_pending_buffers_map_) {
431 for (auto& [frame_number, pending_buffer] : pending_buffers) {
432 ALOGW("%s: pending buffer of stream %d for frame %u ready %d",
433 __FUNCTION__, stream_id, frame_number, pending_buffer.ready);
434 }
435 }
436 }
437
GetReadyShutterMessage(NotifyMessage * message)438 status_t ResultDispatcher::GetReadyShutterMessage(NotifyMessage* message) {
439 ATRACE_CALL();
440 if (message == nullptr) {
441 ALOGE("%s: message is nullptr", __FUNCTION__);
442 return BAD_VALUE;
443 }
444
445 auto shutter_it = pending_shutters_.begin();
446 if (shutter_it == pending_shutters_.end() || !shutter_it->second.ready) {
447 // The first pending shutter is not ready.
448 return NAME_NOT_FOUND;
449 }
450
451 message->type = MessageType::kShutter;
452 message->message.shutter.frame_number = shutter_it->first;
453 message->message.shutter.timestamp_ns = shutter_it->second.timestamp_ns;
454 pending_shutters_.erase(shutter_it);
455
456 return OK;
457 }
458
NotifyShutters()459 void ResultDispatcher::NotifyShutters() {
460 ATRACE_CALL();
461 NotifyMessage message = {};
462 while (true) {
463 std::lock_guard<std::mutex> lock(result_lock_);
464 if (GetReadyShutterMessage(&message) != OK) {
465 break;
466 }
467 ALOGV("%s: Notify shutter for frame %u timestamp %" PRIu64, __FUNCTION__,
468 message.message.shutter.frame_number,
469 message.message.shutter.timestamp_ns);
470 notify_(message);
471 }
472 }
473
GetReadyFinalMetadata(uint32_t * frame_number,std::unique_ptr<HalCameraMetadata> * final_metadata,std::vector<PhysicalCameraMetadata> * physical_metadata)474 status_t ResultDispatcher::GetReadyFinalMetadata(
475 uint32_t* frame_number, std::unique_ptr<HalCameraMetadata>* final_metadata,
476 std::vector<PhysicalCameraMetadata>* physical_metadata) {
477 ATRACE_CALL();
478 if (final_metadata == nullptr || frame_number == nullptr) {
479 ALOGE("%s: final_metadata (%p) or frame_number (%p) is nullptr",
480 __FUNCTION__, final_metadata, frame_number);
481 return BAD_VALUE;
482 }
483
484 std::lock_guard<std::mutex> lock(result_lock_);
485
486 auto final_metadata_it = pending_final_metadata_.begin();
487 if (final_metadata_it == pending_final_metadata_.end() ||
488 !final_metadata_it->second.ready) {
489 // The first pending final metadata is not ready.
490 return NAME_NOT_FOUND;
491 }
492
493 *frame_number = final_metadata_it->first;
494 *final_metadata = std::move(final_metadata_it->second.metadata);
495 *physical_metadata = std::move(final_metadata_it->second.physical_metadata);
496 pending_final_metadata_.erase(final_metadata_it);
497
498 return OK;
499 }
500
NotifyFinalResultMetadata()501 void ResultDispatcher::NotifyFinalResultMetadata() {
502 ATRACE_CALL();
503 uint32_t frame_number;
504 std::unique_ptr<HalCameraMetadata> final_metadata;
505 std::vector<PhysicalCameraMetadata> physical_metadata;
506
507 while (GetReadyFinalMetadata(&frame_number, &final_metadata,
508 &physical_metadata) == OK) {
509 ALOGV("%s: Notify final metadata for frame %u", __FUNCTION__, frame_number);
510 NotifyResultMetadata(frame_number, std::move(final_metadata),
511 std::move(physical_metadata), kPartialResultCount);
512 }
513 }
514
GetReadyBufferResult(std::unique_ptr<CaptureResult> * result)515 status_t ResultDispatcher::GetReadyBufferResult(
516 std::unique_ptr<CaptureResult>* result) {
517 ATRACE_CALL();
518 std::lock_guard<std::mutex> lock(result_lock_);
519 if (result == nullptr) {
520 ALOGE("%s: result is nullptr.", __FUNCTION__);
521 return BAD_VALUE;
522 }
523
524 *result = nullptr;
525
526 for (auto& pending_buffers : stream_pending_buffers_map_) {
527 auto buffer_it = pending_buffers.second.begin();
528 while (buffer_it != pending_buffers.second.end()) {
529 if (!buffer_it->second.ready) {
530 // No more buffer ready.
531 break;
532 }
533
534 auto buffer_result = std::make_unique<CaptureResult>(CaptureResult({}));
535
536 buffer_result->frame_number = buffer_it->first;
537 if (buffer_it->second.is_input) {
538 buffer_result->input_buffers.push_back(buffer_it->second.buffer);
539 } else {
540 buffer_result->output_buffers.push_back(buffer_it->second.buffer);
541 }
542
543 pending_buffers.second.erase(buffer_it);
544 *result = std::move(buffer_result);
545 return OK;
546 }
547 }
548
549 return NAME_NOT_FOUND;
550 }
551
NotifyBuffers()552 void ResultDispatcher::NotifyBuffers() {
553 ATRACE_CALL();
554 std::unique_ptr<CaptureResult> result;
555
556 while (GetReadyBufferResult(&result) == OK) {
557 if (result == nullptr) {
558 ALOGE("%s: result is nullptr", __FUNCTION__);
559 return;
560 }
561 std::lock_guard<std::mutex> lock(process_capture_result_lock_);
562 process_capture_result_(std::move(result));
563 }
564 }
565
566 } // namespace google_camera_hal
567 } // namespace android
568