• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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_TAG "GCH_ZoomRatioMapper"
18 
19 #include <log/log.h>
20 #include <cmath>
21 
22 #include "utils.h"
23 #include "zoom_ratio_mapper.h"
24 
25 namespace android {
26 namespace google_camera_hal {
27 
28 int32_t kWeightedRectToConvert[] = {ANDROID_CONTROL_AE_REGIONS,
29                                     ANDROID_CONTROL_AF_REGIONS,
30                                     ANDROID_CONTROL_AWB_REGIONS};
31 
32 int32_t kRectToConvert[] = {ANDROID_SCALER_CROP_REGION};
33 
34 int32_t kResultPointsToConvert[] = {ANDROID_STATISTICS_FACE_LANDMARKS,
35                                     ANDROID_STATISTICS_FACE_RECTANGLES};
36 
Initialize(InitParams * params)37 void ZoomRatioMapper::Initialize(InitParams* params) {
38   if (params == nullptr) {
39     ALOGE("%s: invalid param", __FUNCTION__);
40     return;
41   }
42   memcpy(&active_array_dimension_, &params->active_array_dimension,
43          sizeof(active_array_dimension_));
44   physical_cam_active_array_dimension_ =
45       params->physical_cam_active_array_dimension;
46   memcpy(&zoom_ratio_range_, &params->zoom_ratio_range,
47          sizeof(zoom_ratio_range_));
48   zoom_ratio_mapper_hwl_ = std::move(params->zoom_ratio_mapper_hwl);
49   is_zoom_ratio_supported_ = true;
50 }
51 
UpdateCaptureRequest(CaptureRequest * request)52 void ZoomRatioMapper::UpdateCaptureRequest(CaptureRequest* request) {
53   if (request == nullptr) {
54     ALOGE("%s: request is nullptr", __FUNCTION__);
55     return;
56   }
57 
58   if (!is_zoom_ratio_supported_) {
59     ALOGV("%s: zoom ratio is not supported", __FUNCTION__);
60     return;
61   }
62 
63   if (request->settings != nullptr) {
64     ApplyZoomRatio(active_array_dimension_, true, request->settings.get());
65   }
66 
67   for (auto& [camera_id, metadata] : request->physical_camera_settings) {
68     if (metadata != nullptr) {
69       auto physical_cam_iter =
70           physical_cam_active_array_dimension_.find(camera_id);
71       if (physical_cam_iter == physical_cam_active_array_dimension_.end()) {
72         ALOGE("%s: Physical camera id %d is not found!", __FUNCTION__,
73               camera_id);
74         continue;
75       }
76       Dimension physical_active_array_dimension = physical_cam_iter->second;
77       ApplyZoomRatio(physical_active_array_dimension, true, metadata.get());
78     }
79   }
80   if (zoom_ratio_mapper_hwl_) {
81     zoom_ratio_mapper_hwl_->UpdateCaptureRequest(request);
82   }
83 }
84 
UpdateCaptureResult(CaptureResult * result)85 void ZoomRatioMapper::UpdateCaptureResult(CaptureResult* result) {
86   if (result == nullptr) {
87     ALOGE("%s: result is nullptr", __FUNCTION__);
88     return;
89   }
90 
91   if (!is_zoom_ratio_supported_) {
92     ALOGV("%s: zoom ratio is not supported", __FUNCTION__);
93     return;
94   }
95 
96   if (result->result_metadata != nullptr) {
97     ApplyZoomRatio(active_array_dimension_, false,
98                    result->result_metadata.get());
99   }
100 
101   for (auto& [camera_id, metadata] : result->physical_metadata) {
102     if (metadata != nullptr) {
103       auto physical_cam_iter =
104           physical_cam_active_array_dimension_.find(camera_id);
105       if (physical_cam_iter == physical_cam_active_array_dimension_.end()) {
106         ALOGE("%s: Physical camera id %d is not found!", __FUNCTION__,
107               camera_id);
108         continue;
109       }
110       Dimension physical_active_array_dimension = physical_cam_iter->second;
111       ApplyZoomRatio(physical_active_array_dimension, false, metadata.get());
112     }
113   }
114   if (zoom_ratio_mapper_hwl_) {
115     zoom_ratio_mapper_hwl_->UpdateCaptureResult(result);
116   }
117 }
118 
ApplyZoomRatio(const Dimension & active_array_dimension,const bool is_request,HalCameraMetadata * metadata)119 void ZoomRatioMapper::ApplyZoomRatio(const Dimension& active_array_dimension,
120                                      const bool is_request,
121                                      HalCameraMetadata* metadata) {
122   if (metadata == nullptr) {
123     ALOGE("%s: metadata is nullptr", __FUNCTION__);
124     return;
125   }
126 
127   camera_metadata_ro_entry entry = {};
128   status_t res = metadata->Get(ANDROID_CONTROL_ZOOM_RATIO, &entry);
129   if (res != OK) {
130     ALOGE("%s: Failed to get the zoom ratio", __FUNCTION__);
131     return;
132   }
133   float zoom_ratio = entry.data.f[0];
134 
135   if (zoom_ratio < zoom_ratio_range_.min) {
136     ALOGE("%s, zoom_ratio(%f) is smaller than lower bound(%f)", __FUNCTION__,
137           zoom_ratio, zoom_ratio_range_.min);
138     zoom_ratio = zoom_ratio_range_.min;
139   } else if (zoom_ratio > zoom_ratio_range_.max) {
140     ALOGE("%s, zoom_ratio(%f) is larger than upper bound(%f)", __FUNCTION__,
141           zoom_ratio, zoom_ratio_range_.max);
142     zoom_ratio = zoom_ratio_range_.max;
143   }
144 
145   if (zoom_ratio_mapper_hwl_ != nullptr && is_request) {
146     zoom_ratio_mapper_hwl_->LimitZoomRatioIfConcurrent(&zoom_ratio);
147   }
148 
149   if (fabs(zoom_ratio - entry.data.f[0]) > 1e-9) {
150     metadata->Set(ANDROID_CONTROL_ZOOM_RATIO, &zoom_ratio, entry.count);
151   }
152 
153   for (auto tag_id : kRectToConvert) {
154     UpdateRects(zoom_ratio, tag_id, active_array_dimension, is_request,
155                 metadata);
156   }
157 
158   for (auto tag_id : kWeightedRectToConvert) {
159     UpdateWeightedRects(zoom_ratio, tag_id, active_array_dimension, is_request,
160                         metadata);
161   }
162 
163   if (!is_request) {
164     for (auto tag_id : kResultPointsToConvert) {
165       UpdatePoints(zoom_ratio, tag_id, active_array_dimension, metadata);
166     }
167   }
168 }
169 
UpdateRects(const float zoom_ratio,const uint32_t tag_id,const Dimension & active_array_dimension,const bool is_request,HalCameraMetadata * metadata)170 void ZoomRatioMapper::UpdateRects(const float zoom_ratio, const uint32_t tag_id,
171                                   const Dimension& active_array_dimension,
172                                   const bool is_request,
173                                   HalCameraMetadata* metadata) {
174   if (metadata == nullptr) {
175     ALOGE("%s: metadata is nullptr", __FUNCTION__);
176     return;
177   }
178   camera_metadata_ro_entry entry = {};
179   status_t res = metadata->Get(tag_id, &entry);
180   if (res != OK || entry.count == 0) {
181     ALOGE("%s: Failed to get the region: %d, res: %d", __FUNCTION__, tag_id,
182           res);
183     return;
184   }
185   int32_t left = entry.data.i32[0];
186   int32_t top = entry.data.i32[1];
187   int32_t width = entry.data.i32[2];
188   int32_t height = entry.data.i32[3];
189 
190   if (is_request) {
191     utils::ConvertZoomRatio(zoom_ratio, active_array_dimension, &left, &top,
192                             &width, &height);
193   } else {
194     utils::RevertZoomRatio(zoom_ratio, active_array_dimension, true, &left,
195                            &top, &width, &height);
196   }
197   int32_t rect[4] = {left, top, width, height};
198 
199   ALOGV(
200       "%s: is request: %d, zoom ratio: %f, set rect: [%d, %d, %d, %d] -> [%d, "
201       "%d, %d, %d]",
202       __FUNCTION__, is_request, zoom_ratio, entry.data.i32[0], entry.data.i32[1],
203       entry.data.i32[2], entry.data.i32[3], rect[0], rect[1], rect[2], rect[3]);
204 
205   res = metadata->Set(tag_id, rect, sizeof(rect) / sizeof(int32_t));
206   if (res != OK) {
207     ALOGE("%s: Updating region: %u failed: %s (%d)", __FUNCTION__, tag_id,
208           strerror(-res), res);
209   }
210 }
211 
UpdateWeightedRects(const float zoom_ratio,const uint32_t tag_id,const Dimension & active_array_dimension,const bool is_request,HalCameraMetadata * metadata)212 void ZoomRatioMapper::UpdateWeightedRects(
213     const float zoom_ratio, const uint32_t tag_id,
214     const Dimension& active_array_dimension, const bool is_request,
215     HalCameraMetadata* metadata) {
216   if (metadata == nullptr) {
217     ALOGE("%s: metadata is nullptr", __FUNCTION__);
218     return;
219   }
220   camera_metadata_ro_entry entry = {};
221   status_t res = metadata->Get(tag_id, &entry);
222   if (res != OK || entry.count == 0) {
223     ALOGV("%s: Failed to get the region: %d, res: %d", __FUNCTION__, tag_id,
224           res);
225     return;
226   }
227   const WeightedRect* regions =
228       reinterpret_cast<const WeightedRect*>(entry.data.i32);
229   const size_t kNumElementsInTuple = sizeof(WeightedRect) / sizeof(int32_t);
230   std::vector<WeightedRect> updated_regions(entry.count / kNumElementsInTuple);
231 
232   for (size_t i = 0; i < updated_regions.size(); i++) {
233     int32_t left = regions[i].left;
234     int32_t top = regions[i].top;
235     int32_t width = regions[i].right - regions[i].left + 1;
236     int32_t height = regions[i].bottom - regions[i].top + 1;
237 
238     if (is_request) {
239       utils::ConvertZoomRatio(zoom_ratio, active_array_dimension, &left, &top,
240                               &width, &height);
241     } else {
242       utils::RevertZoomRatio(zoom_ratio, active_array_dimension, true, &left,
243                              &top, &width, &height);
244     }
245 
246     updated_regions[i].left = left;
247     updated_regions[i].top = top;
248     updated_regions[i].right = left + width - 1;
249     updated_regions[i].bottom = top + height - 1;
250     updated_regions[i].weight = regions[i].weight;
251 
252     ALOGV("%s: set region(%d): [%d, %d, %d, %d, %d]", __FUNCTION__, tag_id,
253           updated_regions[i].left, updated_regions[i].top,
254           updated_regions[i].right, updated_regions[i].bottom,
255           updated_regions[i].weight);
256   }
257   res = metadata->Set(tag_id, reinterpret_cast<int32_t*>(updated_regions.data()),
258                       updated_regions.size() * kNumElementsInTuple);
259   if (res != OK) {
260     ALOGE("%s: Updating region(%d) failed: %s (%d)", __FUNCTION__, tag_id,
261           strerror(-res), res);
262   }
263 }
264 
UpdatePoints(const float zoom_ratio,const uint32_t tag_id,const Dimension & active_array_dimension,HalCameraMetadata * metadata)265 void ZoomRatioMapper::UpdatePoints(const float zoom_ratio, const uint32_t tag_id,
266                                    const Dimension& active_array_dimension,
267                                    HalCameraMetadata* metadata) {
268   if (metadata == nullptr) {
269     ALOGE("%s: metadata is nullptr", __FUNCTION__);
270     return;
271   }
272   camera_metadata_ro_entry entry = {};
273   if (metadata->Get(tag_id, &entry) != OK) {
274     ALOGV("%s: tag: %u not published.", __FUNCTION__, tag_id);
275     return;
276   }
277 
278   if (entry.count <= 0) {
279     ALOGV("%s: No data found, tag: %u", __FUNCTION__, tag_id);
280     return;
281   }
282   // x, y
283   const uint32_t kDataSizePerPoint = 2;
284   const uint32_t point_num = entry.count / kDataSizePerPoint;
285   std::vector<PointI> points(point_num);
286   uint32_t data_index = 0;
287 
288   for (uint32_t i = 0; i < point_num; i++) {
289     data_index = i * kDataSizePerPoint;
290     PointI* transformed = &points.at(i);
291     transformed->x = entry.data.i32[data_index];
292     transformed->y = entry.data.i32[data_index + 1];
293     utils::RevertZoomRatio(zoom_ratio, active_array_dimension, true,
294                            &transformed->x, &transformed->y);
295   }
296 
297   status_t res = metadata->Set(
298       tag_id, reinterpret_cast<int32_t*>(points.data()), entry.count);
299 
300   if (res != OK) {
301     ALOGE("%s: Updating tag: %u failed: %s (%d)", __FUNCTION__, tag_id,
302           strerror(-res), res);
303   }
304 }
305 
306 }  // namespace google_camera_hal
307 }  // namespace android
308