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_RealtimeZslRequestProcessor"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include "realtime_zsl_request_processor.h"
21
22 #include <log/log.h>
23 #include <utils/Trace.h>
24
25 #include <cstdint>
26 #include <shared_mutex>
27
28 #include "hal_types.h"
29 #include "hal_utils.h"
30 #include "system/graphics-base-v1.0.h"
31 #include "utils/Errors.h"
32 #include "vendor_tag_defs.h"
33
34 namespace android {
35 namespace google_camera_hal {
36
37 namespace {
38 // The width and height will be selected according to the following priority.
39 // 1. select the JPEG size if it is in the supported output YUV list
40 // 2. select the smallest output YUV size that
41 // 1) has width/height ratio between the width/height ratio of JPEG and the
42 // max available output size
43 // 2) is larger than JPEG size
SelectWidthAndHeight(uint32_t jpeg_width,uint32_t jpeg_height,CameraDeviceSessionHwl & device_session_hwl,uint32_t & selected_width,uint32_t & selected_height)44 status_t SelectWidthAndHeight(uint32_t jpeg_width, uint32_t jpeg_height,
45 CameraDeviceSessionHwl& device_session_hwl,
46 uint32_t& selected_width,
47 uint32_t& selected_height) {
48 std::unique_ptr<HalCameraMetadata> characteristics;
49 status_t res = device_session_hwl.GetCameraCharacteristics(&characteristics);
50 if (res != OK) {
51 ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
52 return BAD_VALUE;
53 }
54
55 camera_metadata_ro_entry entry;
56 res = characteristics->Get(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
57 &entry);
58 if (res != OK) {
59 ALOGE("%s: Not able to get ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS",
60 __FUNCTION__);
61 return BAD_VALUE;
62 }
63 int available_size = entry.count / 4;
64
65 uint32_t max_width = 0, max_height = 0;
66 for (int i = 0; i < available_size; ++i) {
67 if (entry.data.i32[4 * i] ==
68 android_pixel_format_t::HAL_PIXEL_FORMAT_YCBCR_420_888 &&
69 entry.data.i32[4 * i + 3] == static_cast<int32_t>(StreamType::kOutput)) {
70 uint32_t width = static_cast<uint32_t>(entry.data.i32[1 + 4 * i]);
71 uint32_t height = static_cast<uint32_t>(entry.data.i32[2 + 4 * i]);
72
73 // The request JPEG size is a supported output YUV size. It is our top
74 // choice, return directly if found.
75 if (jpeg_width == width && jpeg_height == height) {
76 selected_height = jpeg_height;
77 selected_width = jpeg_width;
78 return OK;
79 }
80 max_width = std::max(max_width, width);
81 max_height = std::max(max_height, height);
82 }
83 }
84
85 bool selected = false;
86 for (int i = 0; i < available_size; i++) {
87 if (entry.data.i32[4 * i] ==
88 android_pixel_format_t::HAL_PIXEL_FORMAT_YCBCR_420_888 &&
89 entry.data.i32[4 * i + 3] == static_cast<int32_t>(StreamType::kOutput)) {
90 uint32_t width = static_cast<uint32_t>(entry.data.i32[1 + 4 * i]);
91 uint32_t height = static_cast<uint32_t>(entry.data.i32[2 + 4 * i]);
92 if (width < jpeg_width || height < jpeg_height) {
93 // YUV size is smaller than JPEG size
94 continue;
95 }
96 if (selected && width > selected_width) {
97 // Already found a smaller YUV size that fulfill the request
98 continue;
99 }
100
101 // Select the smallest supported YUV size with width/height ratio between
102 // JPEG and the max available output size. It is our second choice.
103 if ((jpeg_height * width - jpeg_width * height) *
104 (height * max_width - width * max_height) >=
105 0) {
106 selected = true;
107 selected_height = height;
108 selected_width = width;
109 }
110 }
111 }
112 if (!selected) {
113 // Select the largest supported YUV size. That is our last choice.
114 selected_height = max_height;
115 selected_width = max_width;
116 }
117 return OK;
118 }
119 } // namespace
120
Create(CameraDeviceSessionHwl * device_session_hwl,android_pixel_format_t pixel_format)121 std::unique_ptr<RealtimeZslRequestProcessor> RealtimeZslRequestProcessor::Create(
122 CameraDeviceSessionHwl* device_session_hwl,
123 android_pixel_format_t pixel_format) {
124 ATRACE_CALL();
125 if (device_session_hwl == nullptr) {
126 ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
127 return nullptr;
128 }
129 if (pixel_format != android_pixel_format_t::HAL_PIXEL_FORMAT_YCBCR_420_888) {
130 ALOGE("%s: only YCBCR_420_888 is supported for YUV ZSL", __FUNCTION__);
131 return nullptr;
132 }
133
134 auto request_processor = std::unique_ptr<RealtimeZslRequestProcessor>(
135 new RealtimeZslRequestProcessor(device_session_hwl));
136 if (request_processor == nullptr) {
137 ALOGE("%s: Creating RealtimeZslRequestProcessor failed.", __FUNCTION__);
138 return nullptr;
139 }
140
141 status_t res = request_processor->Initialize(device_session_hwl);
142 if (res != OK) {
143 ALOGE("%s: Initializing RealtimeZslRequestProcessor failed: %s (%d).",
144 __FUNCTION__, strerror(-res), res);
145 return nullptr;
146 }
147
148 return request_processor;
149 }
150
Initialize(CameraDeviceSessionHwl * device_session_hwl)151 status_t RealtimeZslRequestProcessor::Initialize(
152 CameraDeviceSessionHwl* device_session_hwl) {
153 ATRACE_CALL();
154 std::unique_ptr<HalCameraMetadata> characteristics;
155 status_t res = device_session_hwl->GetCameraCharacteristics(&characteristics);
156 if (res != OK) {
157 ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
158 return BAD_VALUE;
159 }
160
161 camera_metadata_ro_entry entry;
162 res = characteristics->Get(
163 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &entry);
164 if (res == OK) {
165 active_array_width_ = entry.data.i32[2];
166 active_array_height_ = entry.data.i32[3];
167 ALOGI("%s Active size (%d x %d).", __FUNCTION__, active_array_width_,
168 active_array_height_);
169 } else {
170 ALOGE("%s Get active size failed: %s (%d).", __FUNCTION__, strerror(-res),
171 res);
172 return res;
173 }
174
175 return OK;
176 }
177
ConfigureStreams(InternalStreamManager * internal_stream_manager,const StreamConfiguration & stream_config,StreamConfiguration * process_block_stream_config)178 status_t RealtimeZslRequestProcessor::ConfigureStreams(
179 InternalStreamManager* internal_stream_manager,
180 const StreamConfiguration& stream_config,
181 StreamConfiguration* process_block_stream_config) {
182 ATRACE_CALL();
183 if (process_block_stream_config == nullptr ||
184 internal_stream_manager == nullptr) {
185 ALOGE(
186 "%s: process_block_stream_config (%p) is nullptr or "
187 "internal_stream_manager (%p) is nullptr",
188 __FUNCTION__, process_block_stream_config, internal_stream_manager);
189 return BAD_VALUE;
190 }
191
192 // For YUV ZSL, we will use the JPEG size for ZSL buffer size. We already
193 // checked the size is supported in capture session.
194 for (const auto& stream : stream_config.streams) {
195 if (utils::IsSoftwareDenoiseEligibleSnapshotStream(stream)) {
196 if (SelectWidthAndHeight(stream.width, stream.height,
197 *device_session_hwl_, active_array_width_,
198 active_array_height_) != OK) {
199 ALOGE("%s: failed to select ZSL YUV buffer width and height",
200 __FUNCTION__);
201 return BAD_VALUE;
202 }
203 ALOGI("%s, Snapshot size is (%d x %d), selected size is (%d x %d)",
204 __FUNCTION__, stream.width, stream.height, active_array_width_,
205 active_array_height_);
206 break;
207 }
208 }
209
210 // Register internal stream
211 Stream stream_to_add;
212 stream_to_add.stream_type = StreamType::kOutput;
213 stream_to_add.width = active_array_width_;
214 stream_to_add.height = active_array_height_;
215 stream_to_add.format = HAL_PIXEL_FORMAT_YCBCR_420_888;
216 stream_to_add.usage = 0;
217 stream_to_add.rotation = StreamRotation::kRotation0;
218 stream_to_add.data_space = HAL_DATASPACE_ARBITRARY;
219 // For YUV ZSL buffer, if the stream configuration constains physical stream,
220 // we will add the new stream as physical stream. As we support physical
221 // streams only or logical streams only combination. We can check the stream
222 // type of the first stream in the list.
223 if (stream_config.streams[0].is_physical_camera_stream) {
224 stream_to_add.is_physical_camera_stream = true;
225 stream_to_add.physical_camera_id =
226 stream_config.streams[0].physical_camera_id;
227 }
228
229 status_t result = internal_stream_manager->RegisterNewInternalStream(
230 stream_to_add, &stream_id_);
231 if (result != OK) {
232 ALOGE("%s: RegisterNewInternalStream failed.", __FUNCTION__);
233 return UNKNOWN_ERROR;
234 }
235
236 internal_stream_manager_ = internal_stream_manager;
237 // Set id back to stream and then HWL can get correct HAL stream ID
238 stream_to_add.id = stream_id_;
239
240 process_block_stream_config->streams = stream_config.streams;
241 // Add internal stream
242 process_block_stream_config->streams.push_back(stream_to_add);
243 process_block_stream_config->operation_mode = stream_config.operation_mode;
244 process_block_stream_config->session_params =
245 HalCameraMetadata::Clone(stream_config.session_params.get());
246 process_block_stream_config->stream_config_counter =
247 stream_config.stream_config_counter;
248 process_block_stream_config->log_id = stream_config.log_id;
249
250 return OK;
251 }
252
SetProcessBlock(std::unique_ptr<ProcessBlock> process_block)253 status_t RealtimeZslRequestProcessor::SetProcessBlock(
254 std::unique_ptr<ProcessBlock> process_block) {
255 ATRACE_CALL();
256 if (process_block == nullptr) {
257 ALOGE("%s: process_block is nullptr", __FUNCTION__);
258 return BAD_VALUE;
259 }
260
261 std::lock_guard lock(process_block_lock_);
262 if (process_block_ != nullptr) {
263 ALOGE("%s: Already configured.", __FUNCTION__);
264 return ALREADY_EXISTS;
265 }
266
267 process_block_ = std::move(process_block);
268 return OK;
269 }
270
ProcessRequest(const CaptureRequest & request)271 status_t RealtimeZslRequestProcessor::ProcessRequest(
272 const CaptureRequest& request) {
273 ATRACE_CALL();
274 std::shared_lock lock(process_block_lock_);
275 if (process_block_ == nullptr) {
276 ALOGE("%s: Not configured yet.", __FUNCTION__);
277 return NO_INIT;
278 }
279
280 // Update if preview intent has been requested.
281 camera_metadata_ro_entry entry;
282 if (!preview_intent_seen_ && request.settings != nullptr &&
283 request.settings->Get(ANDROID_CONTROL_CAPTURE_INTENT, &entry) == OK) {
284 if (entry.count == 1 &&
285 *entry.data.u8 == ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW) {
286 preview_intent_seen_ = true;
287 ALOGI("%s: First request with preview intent. ZSL starts.", __FUNCTION__);
288 }
289 }
290
291 CaptureRequest block_request;
292
293 block_request.frame_number = request.frame_number;
294 block_request.settings = HalCameraMetadata::Clone(request.settings.get());
295 block_request.input_buffers = request.input_buffers;
296 block_request.output_buffers = request.output_buffers;
297
298 for (auto& metadata : request.input_buffer_metadata) {
299 block_request.input_buffer_metadata.push_back(
300 HalCameraMetadata::Clone(metadata.get()));
301 }
302
303 for (auto& [camera_id, physical_metadata] : request.physical_camera_settings) {
304 block_request.physical_camera_settings[camera_id] =
305 HalCameraMetadata::Clone(physical_metadata.get());
306 }
307
308 // Get one buffer from internal stream manager
309 StreamBuffer buffer = {};
310 status_t result;
311 if (preview_intent_seen_) {
312 result = internal_stream_manager_->GetStreamBuffer(stream_id_, &buffer);
313 if (result != OK) {
314 ALOGE("%s: frame:%d GetStreamBuffer failed.", __FUNCTION__,
315 request.frame_number);
316 return UNKNOWN_ERROR;
317 }
318 }
319
320 // Add output to capture request
321 if (preview_intent_seen_) {
322 block_request.output_buffers.push_back(buffer);
323 }
324
325 std::vector<ProcessBlockRequest> block_requests(1);
326 block_requests[0].request = std::move(block_request);
327 return process_block_->ProcessRequests(block_requests, request);
328 }
329
Flush()330 status_t RealtimeZslRequestProcessor::Flush() {
331 ATRACE_CALL();
332 std::shared_lock lock(process_block_lock_);
333 if (process_block_ == nullptr) {
334 return OK;
335 }
336
337 return process_block_->Flush();
338 }
339
RepeatingRequestEnd(int32_t frame_number,const std::vector<int32_t> & stream_ids)340 void RealtimeZslRequestProcessor::RepeatingRequestEnd(
341 int32_t frame_number, const std::vector<int32_t>& stream_ids) {
342 ATRACE_CALL();
343 std::shared_lock lock(process_block_lock_);
344 if (process_block_ != nullptr) {
345 process_block_->RepeatingRequestEnd(frame_number, stream_ids);
346 }
347 }
348
349 } // namespace google_camera_hal
350 } // namespace android
351