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_Utils"
19
20 #include "utils.h"
21
22 #include <cutils/properties.h>
23 #include <hardware/gralloc.h>
24
25 #include "vendor_tag_defs.h"
26
27 namespace android {
28 namespace google_camera_hal {
29 namespace utils {
30
31 const std::string kRealtimeThreadSetProp = "persist.camera.realtimethread";
32
IsDepthStream(const Stream & stream)33 bool IsDepthStream(const Stream& stream) {
34 if (stream.stream_type == StreamType::kOutput &&
35 stream.data_space == HAL_DATASPACE_DEPTH &&
36 stream.format == HAL_PIXEL_FORMAT_Y16) {
37 return true;
38 }
39
40 return false;
41 }
42
IsPreviewStream(const Stream & stream)43 bool IsPreviewStream(const Stream& stream) {
44 if (stream.stream_type == StreamType::kOutput &&
45 stream.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
46 ((stream.usage & GRALLOC_USAGE_HW_COMPOSER) == GRALLOC_USAGE_HW_COMPOSER ||
47 (stream.usage & GRALLOC_USAGE_HW_TEXTURE) == GRALLOC_USAGE_HW_TEXTURE)) {
48 return true;
49 }
50
51 return false;
52 }
53
IsJPEGSnapshotStream(const Stream & stream)54 bool IsJPEGSnapshotStream(const Stream& stream) {
55 if (stream.stream_type == StreamType::kOutput &&
56 stream.format == HAL_PIXEL_FORMAT_BLOB &&
57 (stream.data_space == HAL_DATASPACE_JFIF ||
58 stream.data_space == HAL_DATASPACE_V0_JFIF)) {
59 return true;
60 }
61
62 return false;
63 }
64
IsOutputZslStream(const Stream & stream)65 bool IsOutputZslStream(const Stream& stream) {
66 if (stream.stream_type == StreamType::kOutput &&
67 (stream.usage & GRALLOC_USAGE_HW_CAMERA_ZSL) ==
68 GRALLOC_USAGE_HW_CAMERA_ZSL) {
69 return true;
70 }
71
72 return false;
73 }
74
IsVideoStream(const Stream & stream)75 bool IsVideoStream(const Stream& stream) {
76 if (stream.stream_type == StreamType::kOutput &&
77 (stream.usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) != 0) {
78 return true;
79 }
80
81 return false;
82 }
83
IsRawStream(const Stream & stream)84 bool IsRawStream(const Stream& stream) {
85 if (stream.stream_type == StreamType::kOutput &&
86 (stream.format == HAL_PIXEL_FORMAT_RAW10 ||
87 stream.format == HAL_PIXEL_FORMAT_RAW16 ||
88 stream.format == HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
89 return true;
90 }
91
92 return false;
93 }
94
IsInputRawStream(const Stream & stream)95 bool IsInputRawStream(const Stream& stream) {
96 if (stream.stream_type == StreamType::kInput &&
97 (stream.format == HAL_PIXEL_FORMAT_RAW10 ||
98 stream.format == HAL_PIXEL_FORMAT_RAW16 ||
99 stream.format == HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
100 return true;
101 }
102
103 return false;
104 }
105
IsArbitraryDataSpaceRawStream(const Stream & stream)106 bool IsArbitraryDataSpaceRawStream(const Stream& stream) {
107 return IsRawStream(stream) && (stream.data_space == HAL_DATASPACE_ARBITRARY);
108 }
109
IsYUVSnapshotStream(const Stream & stream)110 bool IsYUVSnapshotStream(const Stream& stream) {
111 if (stream.stream_type == StreamType::kOutput &&
112 stream.format == HAL_PIXEL_FORMAT_YCbCr_420_888 &&
113 !IsVideoStream(stream) && !IsPreviewStream(stream)) {
114 return true;
115 }
116
117 return false;
118 }
119
GetSensorPhysicalSize(const HalCameraMetadata * characteristics,float * width,float * height)120 status_t GetSensorPhysicalSize(const HalCameraMetadata* characteristics,
121 float* width, float* height) {
122 if (characteristics == nullptr || width == nullptr || height == nullptr) {
123 ALOGE("%s: characteristics or width/height is nullptr", __FUNCTION__);
124 return BAD_VALUE;
125 }
126
127 camera_metadata_ro_entry entry;
128 status_t res = characteristics->Get(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, &entry);
129 if (res != OK || entry.count != 2) {
130 ALOGE(
131 "%s: Getting ANDROID_SENSOR_INFO_PHYSICAL_SIZE failed: %s(%d) count: "
132 "%zu",
133 __FUNCTION__, strerror(-res), res, entry.count);
134 return res;
135 }
136
137 *width = entry.data.f[0];
138 *height = entry.data.f[1];
139 return OK;
140 }
141
GetSensorActiveArraySize(const HalCameraMetadata * characteristics,Rect * active_array)142 status_t GetSensorActiveArraySize(const HalCameraMetadata* characteristics,
143 Rect* active_array) {
144 if (characteristics == nullptr || active_array == nullptr) {
145 ALOGE("%s: characteristics or active_array is nullptr", __FUNCTION__);
146 return BAD_VALUE;
147 }
148
149 camera_metadata_ro_entry entry;
150 status_t res =
151 characteristics->Get(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &entry);
152 if (res != OK || entry.count != 4) {
153 ALOGE(
154 "%s: Getting ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE failed: %s(%d) "
155 "count: %zu",
156 __FUNCTION__, strerror(-res), res, entry.count);
157 return res;
158 }
159
160 active_array->left = entry.data.i32[0];
161 active_array->top = entry.data.i32[1];
162 active_array->right = entry.data.i32[0] + entry.data.i32[2] - 1;
163 active_array->bottom = entry.data.i32[1] + entry.data.i32[3] - 1;
164
165 return OK;
166 }
167
GetZoomRatioRange(const HalCameraMetadata * characteristics,ZoomRatioRange * zoom_ratio_range)168 status_t GetZoomRatioRange(const HalCameraMetadata* characteristics,
169 ZoomRatioRange* zoom_ratio_range) {
170 if (characteristics == nullptr || zoom_ratio_range == nullptr) {
171 ALOGE("%s: characteristics or zoom_ratio_range is nullptr", __FUNCTION__);
172 return BAD_VALUE;
173 }
174
175 camera_metadata_ro_entry entry;
176 status_t res = characteristics->Get(ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
177 if (res != OK || entry.count != 2) {
178 ALOGE(
179 "%s: Getting ANDROID_CONTROL_ZOOM_RATIO_RANGE failed: %s(%d) "
180 "count: %zu",
181 __FUNCTION__, strerror(-res), res, entry.count);
182 return res;
183 }
184
185 zoom_ratio_range->min = entry.data.f[0];
186 zoom_ratio_range->max = entry.data.f[1];
187
188 return OK;
189 }
190
GetSensorPixelArraySize(const HalCameraMetadata * characteristics,Dimension * pixel_array)191 status_t GetSensorPixelArraySize(const HalCameraMetadata* characteristics,
192 Dimension* pixel_array) {
193 if (characteristics == nullptr || pixel_array == nullptr) {
194 ALOGE("%s: characteristics or pixel_array is nullptr", __FUNCTION__);
195 return BAD_VALUE;
196 }
197
198 camera_metadata_ro_entry entry;
199 status_t res =
200 characteristics->Get(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, &entry);
201 if (res != OK || entry.count != 2) {
202 ALOGE(
203 "%s: Getting ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE failed: %s(%d) "
204 "count: %zu",
205 __FUNCTION__, strerror(-res), res, entry.count);
206 return res;
207 }
208
209 pixel_array->width = entry.data.i32[0];
210 pixel_array->height = entry.data.i32[1];
211
212 return OK;
213 }
214
GetFocalLength(const HalCameraMetadata * characteristics,float * focal_length)215 status_t GetFocalLength(const HalCameraMetadata* characteristics,
216 float* focal_length) {
217 if (characteristics == nullptr || focal_length == nullptr) {
218 ALOGE("%s: characteristics or focal_length is nullptr", __FUNCTION__);
219 return BAD_VALUE;
220 }
221
222 camera_metadata_ro_entry entry;
223 status_t res =
224 characteristics->Get(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &entry);
225 if (res != OK || entry.count != 1) {
226 ALOGE(
227 "%s: Getting ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS failed: %s(%d) "
228 "count: %zu",
229 __FUNCTION__, strerror(-res), res, entry.count);
230 return res;
231 }
232
233 *focal_length = entry.data.f[0];
234
235 return OK;
236 }
237
IsLiveSnapshotConfigured(const StreamConfiguration & stream_config)238 bool IsLiveSnapshotConfigured(const StreamConfiguration& stream_config) {
239 bool has_video_stream = false;
240 bool has_jpeg_stream = false;
241 for (auto stream : stream_config.streams) {
242 if (utils::IsVideoStream(stream)) {
243 has_video_stream = true;
244 } else if (utils::IsJPEGSnapshotStream(stream)) {
245 has_jpeg_stream = true;
246 }
247 }
248
249 return (has_video_stream & has_jpeg_stream);
250 }
251
IsHighSpeedModeFpsCompatible(StreamConfigurationMode mode,const HalCameraMetadata * old_session,const HalCameraMetadata * new_session)252 bool IsHighSpeedModeFpsCompatible(StreamConfigurationMode mode,
253 const HalCameraMetadata* old_session,
254 const HalCameraMetadata* new_session) {
255 if (mode != StreamConfigurationMode::kConstrainedHighSpeed) {
256 return false;
257 }
258
259 camera_metadata_ro_entry_t ae_target_fps_entry;
260 int32_t old_max_fps = 0;
261 int32_t new_max_fps = 0;
262
263 if (old_session->Get(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
264 &ae_target_fps_entry) == OK) {
265 old_max_fps = ae_target_fps_entry.data.i32[1];
266 }
267 if (new_session->Get(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
268 &ae_target_fps_entry) == OK) {
269 new_max_fps = ae_target_fps_entry.data.i32[1];
270 }
271
272 ALOGI("%s: HFR: old max fps: %d, new max fps: %d", __FUNCTION__, old_max_fps,
273 new_max_fps);
274
275 if (new_max_fps == old_max_fps) {
276 return true;
277 }
278
279 return false;
280 }
281
IsSessionParameterCompatible(const HalCameraMetadata * old_session,const HalCameraMetadata * new_session)282 bool IsSessionParameterCompatible(const HalCameraMetadata* old_session,
283 const HalCameraMetadata* new_session) {
284 auto old_session_count = old_session->GetEntryCount();
285 auto new_session_count = new_session->GetEntryCount();
286 if (old_session_count == 0 || new_session_count == 0) {
287 ALOGI("No session paramerter, old:%zu, new:%zu", old_session_count,
288 new_session_count);
289 if (new_session_count != 0) {
290 camera_metadata_ro_entry_t entry;
291 if (new_session->Get(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, &entry) == OK) {
292 int32_t max_fps = entry.data.i32[1];
293 if (max_fps > 30) {
294 ALOGI("new session paramerter max fps:%d", max_fps);
295 return false;
296 }
297 }
298 }
299 return true;
300 }
301
302 if (old_session_count != new_session_count) {
303 ALOGI(
304 "Entry count has changed from %zu "
305 "to %zu",
306 old_session_count, new_session_count);
307 return false;
308 }
309
310 for (size_t entry_index = 0; entry_index < new_session_count; entry_index++) {
311 camera_metadata_ro_entry_t new_entry;
312 // Get the medata from new session first
313 if (new_session->GetByIndex(&new_entry, entry_index) != OK) {
314 ALOGW("Unable to get new session entry for index %zu", entry_index);
315 return false;
316 }
317
318 // Get the same tag from old session
319 camera_metadata_ro_entry_t old_entry;
320 if (old_session->Get(new_entry.tag, &old_entry) != OK) {
321 ALOGW("Unable to get old session tag 0x%x", new_entry.tag);
322 return false;
323 }
324
325 if (new_entry.count != old_entry.count) {
326 ALOGI(
327 "New entry count %zu doesn't "
328 "match old entry count %zu",
329 new_entry.count, old_entry.count);
330 return false;
331 }
332
333 if (new_entry.tag == ANDROID_CONTROL_AE_TARGET_FPS_RANGE) {
334 // Stream reconfiguration is not needed in case the upper
335 // framerate range remains unchanged. Any other modification
336 // to the session parameters must trigger new stream
337 // configuration.
338 int32_t old_min_fps = old_entry.data.i32[0];
339 int32_t old_max_fps = old_entry.data.i32[1];
340 int32_t new_min_fps = new_entry.data.i32[0];
341 int32_t new_max_fps = new_entry.data.i32[1];
342 if (old_max_fps == new_max_fps) {
343 ALOGI("%s: Ignore fps (%d, %d) to (%d, %d)", __FUNCTION__, old_min_fps,
344 old_max_fps, new_min_fps, new_max_fps);
345 continue;
346 }
347
348 return false;
349 } else {
350 // Same type and count, compare values
351 size_t type_size = camera_metadata_type_size[old_entry.type];
352 size_t entry_size = type_size * old_entry.count;
353 int32_t cmp = memcmp(new_entry.data.u8, old_entry.data.u8, entry_size);
354 if (cmp != 0) {
355 ALOGI("Session parameter value has changed");
356 return false;
357 }
358 }
359 }
360
361 return true;
362 }
363
ConvertZoomRatio(const float zoom_ratio,const Dimension & active_array_dimension,int32_t * left,int32_t * top,int32_t * width,int32_t * height)364 void ConvertZoomRatio(const float zoom_ratio,
365 const Dimension& active_array_dimension, int32_t* left,
366 int32_t* top, int32_t* width, int32_t* height) {
367 if (left == nullptr || top == nullptr || width == nullptr ||
368 height == nullptr) {
369 ALOGE("%s, invalid params", __FUNCTION__);
370 return;
371 }
372
373 assert(zoom_ratio != 0);
374 *left = std::round(*left / zoom_ratio + 0.5f * active_array_dimension.width *
375 (1.0f - 1.0f / zoom_ratio));
376 *top = std::round(*top / zoom_ratio + 0.5f * active_array_dimension.height *
377 (1.0f - 1.0f / zoom_ratio));
378 *width = std::round(*width / zoom_ratio);
379 *height = std::round(*height / zoom_ratio);
380
381 if (zoom_ratio >= 1.0f) {
382 utils::ClampBoundary(active_array_dimension, left, top, width, height);
383 }
384 }
385
SupportRealtimeThread()386 bool SupportRealtimeThread() {
387 static bool support_real_time = false;
388 static bool first_time = false;
389 if (first_time == false) {
390 first_time = true;
391 support_real_time = property_get_bool(kRealtimeThreadSetProp.c_str(), false);
392 }
393
394 return support_real_time;
395 }
396
SetRealtimeThread(pthread_t thread)397 status_t SetRealtimeThread(pthread_t thread) {
398 struct sched_param param = {
399 .sched_priority = 1,
400 };
401 int32_t res =
402 pthread_setschedparam(thread, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m);
403 if (res != 0) {
404 ALOGE("%s: Couldn't set SCHED_FIFO", __FUNCTION__);
405 return BAD_VALUE;
406 }
407
408 return OK;
409 }
410
UpdateThreadSched(pthread_t thread,int32_t policy,struct sched_param * param)411 status_t UpdateThreadSched(pthread_t thread, int32_t policy,
412 struct sched_param* param) {
413 if (param == nullptr) {
414 ALOGE("%s: sched_param is nullptr", __FUNCTION__);
415 return BAD_VALUE;
416 }
417 int32_t res = pthread_setschedparam(thread, policy, param);
418 if (res != 0) {
419 ALOGE("%s: Couldn't set schedparam", __FUNCTION__);
420 return BAD_VALUE;
421 }
422
423 return OK;
424 }
425
426 } // namespace utils
427 } // namespace google_camera_hal
428 } // namespace android
429