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_RealtimeZslResultRequestProcessor"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20
21 #include "realtime_zsl_result_request_processor.h"
22
23 #include <inttypes.h>
24 #include <log/log.h>
25 #include <utils/Trace.h>
26
27 #include <memory>
28
29 #include "hal_types.h"
30 #include "hal_utils.h"
31 #include "realtime_zsl_result_processor.h"
32
33 namespace android {
34 namespace google_camera_hal {
35
AllDataCollected(const RequestEntry & request_entry) const36 bool RealtimeZslResultRequestProcessor::AllDataCollected(
37 const RequestEntry& request_entry) const {
38 return request_entry.zsl_buffer_received &&
39 request_entry.framework_buffer_count ==
40 static_cast<int>(
41 request_entry.capture_request->output_buffers.size()) &&
42 request_entry.partial_results_received == partial_result_count_;
43 }
44
45 std::unique_ptr<RealtimeZslResultRequestProcessor>
Create(InternalStreamManager * internal_stream_manager,int32_t stream_id,android_pixel_format_t pixel_format,uint32_t partial_result_count)46 RealtimeZslResultRequestProcessor::Create(
47 InternalStreamManager* internal_stream_manager, int32_t stream_id,
48 android_pixel_format_t pixel_format, uint32_t partial_result_count) {
49 ATRACE_CALL();
50 if (internal_stream_manager == nullptr) {
51 ALOGE("%s: internal_stream_manager is nullptr.", __FUNCTION__);
52 return nullptr;
53 }
54 if (pixel_format != android_pixel_format_t::HAL_PIXEL_FORMAT_YCBCR_420_888) {
55 ALOGE("%s: only YCBCR_420_888 is supported for YUV ZSL", __FUNCTION__);
56 return nullptr;
57 }
58
59 auto result_processor = std::unique_ptr<RealtimeZslResultRequestProcessor>(
60 new RealtimeZslResultRequestProcessor(internal_stream_manager, stream_id,
61 partial_result_count));
62 if (result_processor == nullptr) {
63 ALOGE("%s: Creating RealtimeZslResultRequestProcessor failed.",
64 __FUNCTION__);
65 return nullptr;
66 }
67
68 return result_processor;
69 }
70
RealtimeZslResultRequestProcessor(InternalStreamManager * internal_stream_manager,int32_t stream_id,uint32_t partial_result_count)71 RealtimeZslResultRequestProcessor::RealtimeZslResultRequestProcessor(
72 InternalStreamManager* internal_stream_manager, int32_t stream_id,
73 uint32_t partial_result_count)
74 : RealtimeZslResultProcessor(internal_stream_manager, stream_id,
75 partial_result_count) {
76 }
77
UpdateOutputBufferCount(int32_t frame_number,int output_buffer_count,bool is_preview_intent)78 void RealtimeZslResultRequestProcessor::UpdateOutputBufferCount(
79 int32_t frame_number, int output_buffer_count, bool is_preview_intent) {
80 ATRACE_CALL();
81 std::lock_guard<std::mutex> lock(callback_lock_);
82 // Cache the CaptureRequest in a queue as the metadata and buffers may not
83 // come together.
84 RequestEntry request_entry = {
85 .capture_request = std::make_unique<CaptureRequest>(),
86 .framework_buffer_count = output_buffer_count};
87 request_entry.capture_request->frame_number = frame_number;
88 if (!is_preview_intent) {
89 // If no preview intent is provided, RealtimeZslRequestProcessor will not
90 // add an internal buffer to the request so there is no ZSL buffer to wait
91 // for in that case.
92 request_entry.zsl_buffer_received = true;
93 }
94
95 pending_frame_number_to_requests_[frame_number] = std::move(request_entry);
96 }
97
ProcessResult(ProcessBlockResult block_result)98 void RealtimeZslResultRequestProcessor::ProcessResult(
99 ProcessBlockResult block_result) {
100 ATRACE_CALL();
101 std::lock_guard<std::mutex> lock(callback_lock_);
102 std::unique_ptr<CaptureResult> result = std::move(block_result.result);
103 if (result == nullptr) {
104 ALOGW("%s: Received a nullptr result.", __FUNCTION__);
105 return;
106 }
107
108 // May change to ALOGD for per-frame results.
109 ALOGV(
110 "%s: Received result at frame: %d, has metadata (%s), output buffer "
111 "counts: %zu, input buffer counts: %zu",
112 __FUNCTION__, result->frame_number,
113 (result->result_metadata ? "yes" : "no"), result->output_buffers.size(),
114 result->input_buffers.size());
115
116 // Pending request should always exist
117 RequestEntry& pending_request =
118 pending_frame_number_to_requests_[result->frame_number];
119 if (pending_request.capture_request == nullptr) {
120 pending_request.capture_request = std::make_unique<CaptureRequest>();
121 pending_request.capture_request->frame_number = result->frame_number;
122 }
123
124 // Return filled buffer to internal stream manager
125 // And remove buffer from result
126 status_t res;
127 std::vector<StreamBuffer> modified_output_buffers;
128 for (uint32_t i = 0; i < result->output_buffers.size(); i++) {
129 if (stream_id_ == result->output_buffers[i].stream_id) {
130 pending_request.has_returned_output_to_internal_stream_manager = true;
131 res = internal_stream_manager_->ReturnFilledBuffer(
132 result->frame_number, result->output_buffers[i]);
133 if (res != OK) {
134 ALOGW("%s: (%d)ReturnStreamBuffer fail", __FUNCTION__,
135 result->frame_number);
136 }
137 pending_request.zsl_buffer_received = true;
138 } else {
139 modified_output_buffers.push_back(result->output_buffers[i]);
140 }
141 }
142
143 if (result->output_buffers.size() > 0) {
144 result->output_buffers.clear();
145 result->output_buffers = modified_output_buffers;
146 }
147
148 if (result->result_metadata) {
149 result->result_metadata->Erase(ANDROID_CONTROL_ENABLE_ZSL);
150
151 res = internal_stream_manager_->ReturnMetadata(
152 stream_id_, result->frame_number, result->result_metadata.get(),
153 result->partial_result);
154 if (res != OK) {
155 ALOGW("%s: (%d)ReturnMetadata fail", __FUNCTION__, result->frame_number);
156 }
157
158 if (result->partial_result == partial_result_count_) {
159 res =
160 hal_utils::SetEnableZslMetadata(result->result_metadata.get(), false);
161 if (res != OK) {
162 ALOGW("%s: SetEnableZslMetadata (%d) fail", __FUNCTION__,
163 result->frame_number);
164 }
165 }
166 }
167
168 // Return directly for frames with errors.
169 if (pending_error_frames_.find(result->frame_number) !=
170 pending_error_frames_.end()) {
171 RequestEntry& error_entry = pending_error_frames_[result->frame_number];
172 return ReturnResultDirectlyForFramesWithErrorsLocked(
173 error_entry, pending_request, std::move(result));
174 }
175
176 // Fill in final result metadata
177 if (result->result_metadata != nullptr) {
178 pending_request.partial_results_received++;
179 if (result->partial_result < partial_result_count_) {
180 // Early result, clone it
181 pending_request.capture_request->settings =
182 HalCameraMetadata::Clone(result->result_metadata.get());
183 } else {
184 // Final result, early result may or may not exist
185 if (pending_request.capture_request->settings == nullptr) {
186 // No early result, i.e. partial results disabled. Clone final result
187 pending_request.capture_request->settings =
188 HalCameraMetadata::Clone(result->result_metadata.get());
189 } else {
190 // Append early result to final result
191 pending_request.capture_request->settings->Append(
192 result->result_metadata->GetRawCameraMetadata());
193 }
194 }
195 }
196
197 // Fill in output buffers
198 if (!result->output_buffers.empty()) {
199 auto& output_buffers = pending_request.capture_request->output_buffers;
200 output_buffers.insert(output_buffers.begin(), result->output_buffers.begin(),
201 result->output_buffers.end());
202 }
203
204 // Fill in input buffers
205 if (!result->input_buffers.empty()) {
206 auto& input_buffers = pending_request.capture_request->input_buffers;
207 input_buffers.insert(input_buffers.begin(), result->input_buffers.begin(),
208 result->input_buffers.end());
209 }
210
211 // Submit the request and remove the request from the cache when all data is collected.
212 if (AllDataCollected(pending_request)) {
213 res = ProcessRequest(*pending_request.capture_request);
214 pending_frame_number_to_requests_.erase(result->frame_number);
215 if (res != OK) {
216 ALOGE("%s: ProcessRequest fail", __FUNCTION__);
217 return;
218 }
219 }
220 }
221
ConfigureStreams(InternalStreamManager *,const StreamConfiguration & stream_config,StreamConfiguration * process_block_stream_config)222 status_t RealtimeZslResultRequestProcessor::ConfigureStreams(
223 InternalStreamManager* /*internal_stream_manager*/,
224 const StreamConfiguration& stream_config,
225 StreamConfiguration* process_block_stream_config) {
226 ATRACE_CALL();
227 if (process_block_stream_config == nullptr) {
228 ALOGE("%s: process_block_stream_config is nullptr", __FUNCTION__);
229 return BAD_VALUE;
230 }
231
232 process_block_stream_config->streams = stream_config.streams;
233 process_block_stream_config->operation_mode = stream_config.operation_mode;
234 process_block_stream_config->session_params =
235 HalCameraMetadata::Clone(stream_config.session_params.get());
236 process_block_stream_config->stream_config_counter =
237 stream_config.stream_config_counter;
238 process_block_stream_config->multi_resolution_input_image =
239 stream_config.multi_resolution_input_image;
240 process_block_stream_config->log_id = stream_config.log_id;
241
242 return OK;
243 }
244
SetProcessBlock(std::unique_ptr<ProcessBlock> process_block)245 status_t RealtimeZslResultRequestProcessor::SetProcessBlock(
246 std::unique_ptr<ProcessBlock> process_block) {
247 ATRACE_CALL();
248 if (process_block == nullptr) {
249 ALOGE("%s: process_block is nullptr", __FUNCTION__);
250 return BAD_VALUE;
251 }
252
253 std::lock_guard lock(process_block_shared_lock_);
254 if (process_block_ != nullptr) {
255 ALOGE("%s: Already configured.", __FUNCTION__);
256 return ALREADY_EXISTS;
257 }
258
259 process_block_ = std::move(process_block);
260 return OK;
261 }
262
ProcessRequest(const CaptureRequest & request)263 status_t RealtimeZslResultRequestProcessor::ProcessRequest(
264 const CaptureRequest& request) {
265 ATRACE_CALL();
266 std::shared_lock lock(process_block_shared_lock_);
267 if (process_block_ == nullptr) {
268 ALOGE("%s: Not configured yet.", __FUNCTION__);
269 return NO_INIT;
270 }
271
272 CaptureRequest block_request;
273 block_request.frame_number = request.frame_number;
274 block_request.settings = HalCameraMetadata::Clone(request.settings.get());
275 block_request.input_buffers = request.input_buffers;
276 block_request.input_width = request.input_width;
277 block_request.input_height = request.input_height;
278
279 for (auto& metadata : request.input_buffer_metadata) {
280 block_request.input_buffer_metadata.push_back(
281 HalCameraMetadata::Clone(metadata.get()));
282 }
283
284 block_request.output_buffers = request.output_buffers;
285 for (auto& [camera_id, physical_metadata] : request.physical_camera_settings) {
286 block_request.physical_camera_settings[camera_id] =
287 HalCameraMetadata::Clone(physical_metadata.get());
288 }
289
290 std::vector<ProcessBlockRequest> block_requests(1);
291 block_requests[0].request = std::move(block_request);
292
293 return process_block_->ProcessRequests(block_requests, request);
294 }
295
Flush()296 status_t RealtimeZslResultRequestProcessor::Flush() {
297 ATRACE_CALL();
298 std::shared_lock lock(process_block_shared_lock_);
299 if (process_block_ == nullptr) {
300 return OK;
301 }
302
303 return process_block_->Flush();
304 }
305
RepeatingRequestEnd(int32_t frame_number,const std::vector<int32_t> & stream_ids)306 void RealtimeZslResultRequestProcessor::RepeatingRequestEnd(
307 int32_t frame_number, const std::vector<int32_t>& stream_ids) {
308 ATRACE_CALL();
309 std::shared_lock lock(process_block_shared_lock_);
310 if (process_block_ != nullptr) {
311 process_block_->RepeatingRequestEnd(frame_number, stream_ids);
312 }
313 }
314
Notify(const ProcessBlockNotifyMessage & block_message)315 void RealtimeZslResultRequestProcessor::Notify(
316 const ProcessBlockNotifyMessage& block_message) {
317 ATRACE_CALL();
318 std::lock_guard<std::mutex> lock(callback_lock_);
319 const NotifyMessage& message = block_message.message;
320 if (notify_ == nullptr) {
321 ALOGE("%s: notify_ is nullptr. Dropping a message.", __FUNCTION__);
322 return;
323 }
324
325 // Will return buffer for kErrorRequest and kErrorBuffer.
326 if (message.type == MessageType::kError) {
327 // May change to ALOGD for per-frame error messages.
328 ALOGV("%s: Received error message at frame: %d, error code (%d)",
329 __FUNCTION__, message.message.error.frame_number,
330 static_cast<int>(message.message.error.error_code));
331 if (message.message.error.error_code == ErrorCode::kErrorRequest ||
332 message.message.error.error_code == ErrorCode::kErrorBuffer) {
333 pending_error_frames_.try_emplace(
334 message.message.error.frame_number,
335 RequestEntry{.capture_request = std::make_unique<CaptureRequest>()});
336 if (message.message.error.error_code == ErrorCode::kErrorRequest) {
337 // ProcessCaptureResult is not called in the case of metadata error.
338 // Therefore, treat it as if a metadata callback arrived so that we can
339 // know when the request is complete.
340 pending_error_frames_[message.message.error.frame_number]
341 .partial_results_received++;
342 }
343 }
344 // Gives latched results (those that have arrived but are waiting for
345 // AllDataCollected()) a chance to return their valid buffer.
346 uint32_t frame_number = message.message.error.frame_number;
347 auto result = std::make_unique<CaptureResult>();
348 result->frame_number = frame_number;
349 if (pending_frame_number_to_requests_.find(frame_number) !=
350 pending_frame_number_to_requests_.end()) {
351 RequestEntry& pending_request =
352 pending_frame_number_to_requests_[frame_number];
353 if (pending_request.zsl_buffer_received) {
354 ReturnResultDirectlyForFramesWithErrorsLocked(
355 pending_error_frames_[frame_number], pending_request,
356 std::move(result));
357 }
358 }
359 } else {
360 // May change to ALOGD for per-frame shutter messages.
361 ALOGV("%s: Received shutter message for frame %d, timestamp_ns: %" PRId64
362 ", readout_timestamp_ns: %" PRId64,
363 __FUNCTION__, message.message.shutter.frame_number,
364 message.message.shutter.timestamp_ns,
365 message.message.shutter.readout_timestamp_ns);
366 }
367
368 // Do not notify errors for internal streams
369 if (message.type == MessageType::kError &&
370 message.message.error.error_stream_id == stream_id_) {
371 return;
372 }
373
374 notify_(message);
375 }
376
CombineErrorAndPendingEntriesToResult(RequestEntry & error_entry,RequestEntry & pending_request,std::unique_ptr<CaptureResult> & result) const377 void RealtimeZslResultRequestProcessor::CombineErrorAndPendingEntriesToResult(
378 RequestEntry& error_entry, RequestEntry& pending_request,
379 std::unique_ptr<CaptureResult>& result) const {
380 result->output_buffers.insert(
381 result->output_buffers.end(),
382 pending_request.capture_request->output_buffers.begin(),
383 pending_request.capture_request->output_buffers.end());
384 result->input_buffers.insert(
385 result->input_buffers.end(),
386 pending_request.capture_request->input_buffers.begin(),
387 pending_request.capture_request->input_buffers.end());
388 error_entry.capture_request->output_buffers = result->output_buffers;
389 error_entry.capture_request->input_buffers = result->input_buffers;
390 error_entry.zsl_buffer_received = pending_request.zsl_buffer_received;
391 error_entry.framework_buffer_count = pending_request.framework_buffer_count;
392 if (pending_request.capture_request->settings != nullptr) {
393 if (result->result_metadata == nullptr) {
394 // result is a buffer-only result and we have early metadata sitting in
395 // pending_request. Copy this early metadata and its partial_result count.
396 result->result_metadata = HalCameraMetadata::Clone(
397 pending_request.capture_request->settings.get());
398 result->partial_result = pending_request.partial_results_received;
399 } else {
400 // result carries final metadata and we have early metadata sitting in
401 // pending_request. Append the early metadata but keep the
402 // partial_result count to reflect that this is the final metadata.
403 result->result_metadata->Append(
404 pending_request.capture_request->settings->GetRawCameraMetadata());
405 }
406 error_entry.partial_results_received += result->partial_result;
407 }
408
409 // Reset capture request for pending request as all data has been
410 // transferred to error_entry already.
411 pending_request.capture_request = std::make_unique<CaptureRequest>();
412 pending_request.capture_request->frame_number = result->frame_number;
413 }
414
ReturnResultDirectlyForFramesWithErrorsLocked(RequestEntry & error_entry,RequestEntry & pending_request,std::unique_ptr<CaptureResult> result)415 void RealtimeZslResultRequestProcessor::ReturnResultDirectlyForFramesWithErrorsLocked(
416 RequestEntry& error_entry, RequestEntry& pending_request,
417 std::unique_ptr<CaptureResult> result) {
418 // Also need to process pending buffers and metadata for the frame if exists.
419 // If the result is complete (buffers and all partial results arrived), send
420 // the callback directly. Otherwise wait until the missing pieces arrive.
421 CombineErrorAndPendingEntriesToResult(error_entry, pending_request, result);
422
423 const bool has_returned_output_to_internal_stream_manager =
424 pending_request.has_returned_output_to_internal_stream_manager;
425
426 if (AllDataCollected(error_entry)) {
427 pending_error_frames_.erase(result->frame_number);
428 pending_frame_number_to_requests_.erase(result->frame_number);
429 }
430
431 // Don't send result to framework if only internal callback
432 if (has_returned_output_to_internal_stream_manager &&
433 result->result_metadata == nullptr && result->output_buffers.size() == 0) {
434 return;
435 }
436 ALOGV("%s: Returning capture result for frame %d due to existing errors.",
437 __FUNCTION__, result->frame_number);
438 process_capture_result_(std::move(result));
439 return;
440 }
441
442 } // namespace google_camera_hal
443 } // namespace android
444