• 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_TAG "Camera3-ZoomRatioMapper"
18 //#define LOG_NDEBUG 0
19 
20 #include <algorithm>
21 
22 #include "device3/ZoomRatioMapper.h"
23 #include "utils/SessionConfigurationUtilsHost.h"
24 
25 namespace android {
26 
27 namespace camera3 {
28 
initRemappedKeys()29 void ZoomRatioMapper::initRemappedKeys() {
30     mRemappedKeys.insert(
31             kMeteringRegionsToCorrect.begin(),
32             kMeteringRegionsToCorrect.end());
33     mRemappedKeys.insert(
34             kRectsToCorrect.begin(),
35             kRectsToCorrect.end());
36     mRemappedKeys.insert(
37             kResultPointsToCorrectNoClamp.begin(),
38             kResultPointsToCorrectNoClamp.end());
39 
40     mRemappedKeys.insert(ANDROID_CONTROL_ZOOM_RATIO);
41 }
42 
initZoomRatioInTemplate(CameraMetadata * request)43 status_t ZoomRatioMapper::initZoomRatioInTemplate(CameraMetadata *request) {
44     camera_metadata_entry_t entry;
45     entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
46     float defaultZoomRatio = 1.0f;
47     if (entry.count == 0) {
48         return request->update(ANDROID_CONTROL_ZOOM_RATIO, &defaultZoomRatio, 1);
49     }
50     return OK;
51 }
52 
overrideZoomRatioTags(CameraMetadata * deviceInfo,bool * supportNativeZoomRatio)53 status_t ZoomRatioMapper::overrideZoomRatioTags(
54         CameraMetadata* deviceInfo, bool* supportNativeZoomRatio) {
55     if (deviceInfo == nullptr || supportNativeZoomRatio == nullptr) {
56         return BAD_VALUE;
57     }
58 
59     camera_metadata_entry_t entry;
60     entry = deviceInfo->find(ANDROID_CONTROL_ZOOM_RATIO_RANGE);
61     if (entry.count != 2 && entry.count != 0) return BAD_VALUE;
62 
63     // Hal has zoom ratio support
64     if (entry.count == 2) {
65         *supportNativeZoomRatio = true;
66         return OK;
67     }
68 
69     // Hal has no zoom ratio support
70     *supportNativeZoomRatio = false;
71 
72     entry = deviceInfo->find(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
73     if (entry.count != 1) {
74         ALOGI("%s: Camera device doesn't support SCALER_AVAILABLE_MAX_DIGITAL_ZOOM key!",
75                 __FUNCTION__);
76         return OK;
77     }
78 
79     float zoomRange[] = {1.0f, entry.data.f[0]};
80     status_t res = deviceInfo->update(ANDROID_CONTROL_ZOOM_RATIO_RANGE, zoomRange, 2);
81     if (res != OK) {
82         ALOGE("%s: Failed to update CONTROL_ZOOM_RATIO_RANGE key: %s (%d)",
83                 __FUNCTION__, strerror(-res), res);
84         return res;
85     }
86 
87     std::vector<int32_t> requestKeys;
88     entry = deviceInfo->find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
89     if (entry.count > 0) {
90         requestKeys.insert(requestKeys.end(), entry.data.i32, entry.data.i32 + entry.count);
91     }
92     requestKeys.push_back(ANDROID_CONTROL_ZOOM_RATIO);
93     res = deviceInfo->update(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
94             requestKeys.data(), requestKeys.size());
95     if (res != OK) {
96         ALOGE("%s: Failed to update REQUEST_AVAILABLE_REQUEST_KEYS: %s (%d)",
97                 __FUNCTION__, strerror(-res), res);
98         return res;
99     }
100 
101     std::vector<int32_t> resultKeys;
102     entry = deviceInfo->find(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS);
103     if (entry.count > 0) {
104         resultKeys.insert(resultKeys.end(), entry.data.i32, entry.data.i32 + entry.count);
105     }
106     resultKeys.push_back(ANDROID_CONTROL_ZOOM_RATIO);
107     res = deviceInfo->update(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
108             resultKeys.data(), resultKeys.size());
109     if (res != OK) {
110         ALOGE("%s: Failed to update REQUEST_AVAILABLE_RESULT_KEYS: %s (%d)",
111                 __FUNCTION__, strerror(-res), res);
112         return res;
113     }
114 
115     std::vector<int32_t> charKeys;
116     entry = deviceInfo->find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
117     if (entry.count > 0) {
118         charKeys.insert(charKeys.end(), entry.data.i32, entry.data.i32 + entry.count);
119     }
120     charKeys.push_back(ANDROID_CONTROL_ZOOM_RATIO_RANGE);
121     res = deviceInfo->update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
122             charKeys.data(), charKeys.size());
123     if (res != OK) {
124         ALOGE("%s: Failed to update REQUEST_AVAILABLE_CHARACTERISTICS_KEYS: %s (%d)",
125                 __FUNCTION__, strerror(-res), res);
126         return res;
127     }
128 
129     return OK;
130 }
131 
ZoomRatioMapper(const CameraMetadata * deviceInfo,bool supportNativeZoomRatio,bool usePrecorrectArray)132 ZoomRatioMapper::ZoomRatioMapper(const CameraMetadata* deviceInfo,
133         bool supportNativeZoomRatio, bool usePrecorrectArray) {
134     initRemappedKeys();
135 
136     int32_t arrayW = 0;
137     int32_t arrayH = 0;
138     int32_t arrayMaximumResolutionW = 0;
139     int32_t arrayMaximumResolutionH = 0;
140     int32_t activeW = 0;
141     int32_t activeH = 0;
142     int32_t activeMaximumResolutionW = 0;
143     int32_t activeMaximumResolutionH = 0;
144 
145     if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
146             ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &arrayW, &arrayH)) {
147         ALOGE("%s: Couldn't get pre correction active array size", __FUNCTION__);
148         return;
149     }
150      if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
151             ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &activeW, &activeH)) {
152         ALOGE("%s: Couldn't get active array size", __FUNCTION__);
153         return;
154     }
155 
156     bool supportsUltraHighResolutionCapture =
157             camera3::SessionConfigurationUtils::supportsUltraHighResolutionCapture(*deviceInfo);
158     if (supportsUltraHighResolutionCapture) {
159         if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
160                 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
161                 &arrayMaximumResolutionW, &arrayMaximumResolutionH)) {
162             ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
163                     __FUNCTION__);
164             return;
165         }
166          if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
167                 ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
168                 &activeMaximumResolutionW, &activeMaximumResolutionH)) {
169             ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
170                     __FUNCTION__);
171             return;
172         }
173     }
174 
175     if (usePrecorrectArray) {
176         mArrayWidth = arrayW;
177         mArrayHeight = arrayH;
178         mArrayWidthMaximumResolution = arrayMaximumResolutionW;
179         mArrayHeightMaximumResolution = arrayMaximumResolutionH;
180     } else {
181         mArrayWidth = activeW;
182         mArrayHeight = activeH;
183         mArrayWidthMaximumResolution = activeMaximumResolutionW;
184         mArrayHeightMaximumResolution = activeMaximumResolutionH;
185     }
186     mHalSupportsZoomRatio = supportNativeZoomRatio;
187 
188     ALOGV("%s: array size: %d x %d, full res array size: %d x %d,  mHalSupportsZoomRatio %d",
189             __FUNCTION__, mArrayWidth, mArrayHeight, mArrayWidthMaximumResolution,
190             mArrayHeightMaximumResolution, mHalSupportsZoomRatio);
191     mIsValid = true;
192 }
193 
getArrayDimensionsToBeUsed(const CameraMetadata * settings,int32_t * arrayWidth,int32_t * arrayHeight)194 status_t ZoomRatioMapper::getArrayDimensionsToBeUsed(const CameraMetadata *settings,
195         int32_t *arrayWidth, int32_t *arrayHeight) {
196     if (settings == nullptr || arrayWidth == nullptr || arrayHeight == nullptr) {
197         return BAD_VALUE;
198     }
199     // First we get the sensorPixelMode from the settings metadata.
200     int32_t sensorPixelMode = ANDROID_SENSOR_PIXEL_MODE_DEFAULT;
201     camera_metadata_ro_entry sensorPixelModeEntry = settings->find(ANDROID_SENSOR_PIXEL_MODE);
202     if (sensorPixelModeEntry.count != 0) {
203         sensorPixelMode = sensorPixelModeEntry.data.u8[0];
204         if (sensorPixelMode != ANDROID_SENSOR_PIXEL_MODE_DEFAULT &&
205             sensorPixelMode != ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) {
206             ALOGE("%s: Request sensor pixel mode is not one of the valid values %d",
207                       __FUNCTION__, sensorPixelMode);
208             return BAD_VALUE;
209         }
210     }
211     if (sensorPixelMode == ANDROID_SENSOR_PIXEL_MODE_DEFAULT) {
212         *arrayWidth = mArrayWidth;
213         *arrayHeight = mArrayHeight;
214     } else {
215         *arrayWidth = mArrayWidthMaximumResolution;
216         *arrayHeight = mArrayHeightMaximumResolution;
217     }
218     return OK;
219 }
220 
updateCaptureRequest(CameraMetadata * request)221 status_t ZoomRatioMapper::updateCaptureRequest(CameraMetadata* request) {
222     if (!mIsValid) return INVALID_OPERATION;
223 
224     status_t res = OK;
225     bool zoomRatioIs1 = true;
226     camera_metadata_entry_t entry;
227     int arrayHeight, arrayWidth = 0;
228     res = getArrayDimensionsToBeUsed(request, &arrayWidth, &arrayHeight);
229     if (res != OK) {
230         return res;
231     }
232     entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
233     if (entry.count == 1 && entry.data.f[0] != 1.0f) {
234         zoomRatioIs1 = false;
235 
236         // If cropRegion is windowboxing, override it with activeArray
237         camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
238         if (cropRegionEntry.count == 4) {
239             int cropWidth = cropRegionEntry.data.i32[2];
240             int cropHeight = cropRegionEntry.data.i32[3];
241             if (cropWidth < arrayWidth && cropHeight < arrayHeight) {
242                 cropRegionEntry.data.i32[0] = 0;
243                 cropRegionEntry.data.i32[1] = 0;
244                 cropRegionEntry.data.i32[2] = arrayWidth;
245                 cropRegionEntry.data.i32[3] = arrayHeight;
246             }
247         }
248     }
249 
250     if (mHalSupportsZoomRatio && zoomRatioIs1) {
251         res = separateZoomFromCropLocked(request, false/*isResult*/, arrayWidth, arrayHeight);
252     } else if (!mHalSupportsZoomRatio && !zoomRatioIs1) {
253         res = combineZoomAndCropLocked(request, false/*isResult*/, arrayWidth, arrayHeight);
254     }
255 
256     // If CONTROL_ZOOM_RATIO is in request, but HAL doesn't support
257     // CONTROL_ZOOM_RATIO, remove it from the request.
258     if (!mHalSupportsZoomRatio && entry.count == 1) {
259         request->erase(ANDROID_CONTROL_ZOOM_RATIO);
260     }
261 
262     return res;
263 }
264 
updateCaptureResult(CameraMetadata * result,bool requestedZoomRatioIs1)265 status_t ZoomRatioMapper::updateCaptureResult(CameraMetadata* result, bool requestedZoomRatioIs1) {
266     if (!mIsValid) return INVALID_OPERATION;
267 
268     status_t res = OK;
269 
270     int arrayHeight, arrayWidth = 0;
271     res = getArrayDimensionsToBeUsed(result, &arrayWidth, &arrayHeight);
272     if (res != OK) {
273         return res;
274     }
275     if (mHalSupportsZoomRatio && requestedZoomRatioIs1) {
276         res = combineZoomAndCropLocked(result, true/*isResult*/, arrayWidth, arrayHeight);
277     } else if (!mHalSupportsZoomRatio && !requestedZoomRatioIs1) {
278         res = separateZoomFromCropLocked(result, true/*isResult*/, arrayWidth, arrayHeight);
279     } else {
280         camera_metadata_entry_t entry = result->find(ANDROID_CONTROL_ZOOM_RATIO);
281         if (entry.count == 0) {
282             float zoomRatio1x = 1.0f;
283             result->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio1x, 1);
284         }
285     }
286 
287     return res;
288 }
289 
deriveZoomRatio(const CameraMetadata * metadata,float * zoomRatioRet,int arrayWidth,int arrayHeight)290 status_t ZoomRatioMapper::deriveZoomRatio(const CameraMetadata* metadata, float *zoomRatioRet,
291         int arrayWidth, int arrayHeight) {
292     if (metadata == nullptr || zoomRatioRet == nullptr) {
293         return BAD_VALUE;
294     }
295     float zoomRatio = 1.0;
296 
297     camera_metadata_ro_entry_t entry;
298     entry = metadata->find(ANDROID_SCALER_CROP_REGION);
299     if (entry.count != 4) {
300         *zoomRatioRet = 1;
301         return OK;
302     }
303     // Center of the preCorrection/active size
304     float arrayCenterX = arrayWidth / 2.0;
305     float arrayCenterY = arrayHeight / 2.0;
306 
307     // Re-map crop region to coordinate system centered to (arrayCenterX,
308     // arrayCenterY).
309     float cropRegionLeft = arrayCenterX - entry.data.i32[0] ;
310     float cropRegionTop = arrayCenterY - entry.data.i32[1];
311     float cropRegionRight = entry.data.i32[0] + entry.data.i32[2] - arrayCenterX;
312     float cropRegionBottom = entry.data.i32[1] + entry.data.i32[3] - arrayCenterY;
313 
314     // Calculate the scaling factor for left, top, bottom, right
315     float zoomRatioLeft = std::max(arrayWidth / (2 * cropRegionLeft), 1.0f);
316     float zoomRatioTop = std::max(arrayHeight / (2 * cropRegionTop), 1.0f);
317     float zoomRatioRight = std::max(arrayWidth / (2 * cropRegionRight), 1.0f);
318     float zoomRatioBottom = std::max(arrayHeight / (2 * cropRegionBottom), 1.0f);
319 
320     // Use minimum scaling factor to handle letterboxing or pillarboxing
321     zoomRatio = std::min(std::min(zoomRatioLeft, zoomRatioRight),
322             std::min(zoomRatioTop, zoomRatioBottom));
323 
324     ALOGV("%s: derived zoomRatio is %f", __FUNCTION__, zoomRatio);
325     *zoomRatioRet = zoomRatio;
326     return OK;
327 }
328 
separateZoomFromCropLocked(CameraMetadata * metadata,bool isResult,int arrayWidth,int arrayHeight)329 status_t ZoomRatioMapper::separateZoomFromCropLocked(CameraMetadata* metadata, bool isResult,
330         int arrayWidth, int arrayHeight) {
331     float zoomRatio = 1.0;
332     status_t res = deriveZoomRatio(metadata, &zoomRatio, arrayWidth, arrayHeight);
333 
334     if (res != OK) {
335         ALOGE("%s: Failed to derive zoom ratio: %s(%d)",
336                 __FUNCTION__, strerror(-res), res);
337         return res;
338     }
339 
340     // Update zoomRatio metadata tag
341     res = metadata->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
342     if (res != OK) {
343         ALOGE("%s: Failed to update ANDROID_CONTROL_ZOOM_RATIO: %s(%d)",
344                 __FUNCTION__, strerror(-res), res);
345         return res;
346     }
347 
348     // Scale regions using zoomRatio
349     camera_metadata_entry_t entry;
350     for (auto region : kMeteringRegionsToCorrect) {
351         entry = metadata->find(region);
352         for (size_t j = 0; j < entry.count; j += 5) {
353             int32_t weight = entry.data.i32[j + 4];
354             if (weight == 0) {
355                 continue;
356             }
357             scaleRegion(entry.data.i32 + j, zoomRatio, arrayWidth,
358                     arrayHeight);
359         }
360     }
361 
362     for (auto rect : kRectsToCorrect) {
363         entry = metadata->find(rect);
364         scaleRects(entry.data.i32, entry.count / 4, zoomRatio, arrayWidth, arrayHeight);
365     }
366 
367     if (isResult) {
368         for (auto pts : kResultPointsToCorrectNoClamp) {
369             entry = metadata->find(pts);
370             scaleCoordinates(entry.data.i32, entry.count / 2, zoomRatio, false /*clamp*/,
371                     arrayWidth, arrayHeight);
372         }
373     }
374 
375     return OK;
376 }
377 
combineZoomAndCropLocked(CameraMetadata * metadata,bool isResult,int arrayWidth,int arrayHeight)378 status_t ZoomRatioMapper::combineZoomAndCropLocked(CameraMetadata* metadata, bool isResult,
379         int arrayWidth, int arrayHeight) {
380     float zoomRatio = 1.0f;
381     camera_metadata_entry_t entry;
382     entry = metadata->find(ANDROID_CONTROL_ZOOM_RATIO);
383     if (entry.count == 1) {
384         zoomRatio = entry.data.f[0];
385     }
386 
387     // Unscale regions with zoomRatio
388     for (auto region : kMeteringRegionsToCorrect) {
389         entry = metadata->find(region);
390         for (size_t j = 0; j < entry.count; j += 5) {
391             int32_t weight = entry.data.i32[j + 4];
392             if (weight == 0) {
393                 continue;
394             }
395             scaleRegion(entry.data.i32 + j, 1.0 / zoomRatio, arrayWidth,
396                     arrayHeight);
397         }
398     }
399     for (auto rect : kRectsToCorrect) {
400         entry = metadata->find(rect);
401         scaleRects(entry.data.i32, entry.count / 4, 1.0 / zoomRatio, arrayWidth, arrayHeight);
402     }
403     if (isResult) {
404         for (auto pts : kResultPointsToCorrectNoClamp) {
405             entry = metadata->find(pts);
406             scaleCoordinates(entry.data.i32, entry.count / 2, 1.0 / zoomRatio, false /*clamp*/,
407                     arrayWidth, arrayHeight);
408         }
409     }
410 
411     zoomRatio = 1.0;
412     status_t res = metadata->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
413     if (res != OK) {
414         return res;
415     }
416 
417     return OK;
418 }
419 
scaleCoordinates(int32_t * coordPairs,int coordCount,float scaleRatio,bool clamp,int32_t arrayWidth,int32_t arrayHeight)420 void ZoomRatioMapper::scaleCoordinates(int32_t* coordPairs, int coordCount,
421         float scaleRatio, bool clamp, int32_t arrayWidth, int32_t arrayHeight) {
422     // A pixel's coordinate is represented by the position of its top-left corner.
423     // To avoid the rounding error, we use the coordinate for the center of the
424     // pixel instead:
425     // 1. First shift the coordinate system half pixel both horizontally and
426     // vertically, so that [x, y] is the center of the pixel, not the top-left corner.
427     // 2. Do zoom operation to scale the coordinate relative to the center of
428     // the active array (shifted by 0.5 pixel as well).
429     // 3. Shift the coordinate system back by directly using the pixel center
430     // coordinate.
431     for (int i = 0; i < coordCount * 2; i += 2) {
432         float x = coordPairs[i];
433         float y = coordPairs[i + 1];
434         float xCentered = x - (arrayWidth - 2) / 2;
435         float yCentered = y - (arrayHeight - 2) / 2;
436         float scaledX = xCentered * scaleRatio;
437         float scaledY = yCentered * scaleRatio;
438         scaledX += (arrayWidth - 2) / 2;
439         scaledY += (arrayHeight - 2) / 2;
440         coordPairs[i] = static_cast<int32_t>(std::round(scaledX));
441         coordPairs[i+1] = static_cast<int32_t>(std::round(scaledY));
442         // Clamp to within activeArray/preCorrectionActiveArray
443         if (clamp) {
444             int32_t right = arrayWidth - 1;
445             int32_t bottom = arrayHeight - 1;
446             coordPairs[i] =
447                     std::min(right, std::max(0, coordPairs[i]));
448             coordPairs[i+1] =
449                     std::min(bottom, std::max(0, coordPairs[i+1]));
450         }
451         ALOGV("%s: coordinates: %d, %d", __FUNCTION__, coordPairs[i], coordPairs[i+1]);
452     }
453 }
454 
scaleRegion(int32_t * region,float scaleRatio,int32_t arrayWidth,int32_t arrayHeight)455 void ZoomRatioMapper::scaleRegion(int32_t* region, float scaleRatio,
456         int32_t arrayWidth, int32_t arrayHeight) {
457     // Top-left (inclusive)
458     scaleCoordinates(region, 1, scaleRatio, true /*clamp*/, arrayWidth,
459             arrayHeight);
460     // Bottom-right (exclusive): Use adjacent inclusive pixel to
461     // calculate.
462     region[2] -= 1;
463     region[3] -= 1;
464     scaleCoordinates(region + 2, 1, scaleRatio, true /*clamp*/, arrayWidth,
465             arrayHeight);
466     region[2] += 1;
467     region[3] += 1;
468     // Make sure bottom-right >= top-left
469     region[2] = std::max(region[0], region[2]);
470     region[3] = std::max(region[1], region[3]);
471 }
472 
scaleRects(int32_t * rects,int rectCount,float scaleRatio,int32_t arrayWidth,int32_t arrayHeight)473 void ZoomRatioMapper::scaleRects(int32_t* rects, int rectCount,
474         float scaleRatio, int32_t arrayWidth, int32_t arrayHeight) {
475     for (int i = 0; i < rectCount * 4; i += 4) {
476         // Map from (l, t, width, height) to (l, t, l+width-1, t+height-1),
477         // where both top-left and bottom-right are inclusive.
478         int32_t coords[4] = {
479             rects[i],
480             rects[i + 1],
481             rects[i] + rects[i + 2] - 1,
482             rects[i + 1] + rects[i + 3] - 1
483         };
484 
485         // top-left
486         scaleCoordinates(coords, 1, scaleRatio, true /*clamp*/, arrayWidth, arrayHeight);
487         // bottom-right
488         scaleCoordinates(coords+2, 1, scaleRatio, true /*clamp*/, arrayWidth, arrayHeight);
489 
490         // Map back to (l, t, width, height)
491         rects[i] = coords[0];
492         rects[i + 1] = coords[1];
493         rects[i + 2] = coords[2] - coords[0] + 1;
494         rects[i + 3] = coords[3] - coords[1] + 1;
495     }
496 }
497 
498 } // namespace camera3
499 
500 } // namespace android
501