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