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