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