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