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