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