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