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