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