1 /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #define LOG_TAG "QCameraFOVControl"
31
32 #include <stdlib.h>
33 #include <cutils/properties.h>
34 #include <utils/Errors.h>
35 #include "QCameraFOVControl.h"
36 #include "QCameraDualCamSettings.h"
37
38
39 extern "C" {
40 #include "mm_camera_dbg.h"
41 }
42
43 namespace qcamera {
44
45 /*===========================================================================
46 * FUNCTION : QCameraFOVControl constructor
47 *
48 * DESCRIPTION: class constructor
49 *
50 * PARAMETERS : none
51 *
52 * RETURN : void
53 *
54 *==========================================================================*/
QCameraFOVControl()55 QCameraFOVControl::QCameraFOVControl()
56 {
57 mZoomTranslator = NULL;
58 memset(&mDualCamParams, 0, sizeof(dual_cam_params_t));
59 memset(&mFovControlConfig, 0, sizeof(fov_control_config_t));
60 memset(&mFovControlData, 0, sizeof(fov_control_data_t));
61 memset(&mFovControlResult, 0, sizeof(fov_control_result_t));
62 }
63
64
65 /*===========================================================================
66 * FUNCTION : QCameraFOVControl destructor
67 *
68 * DESCRIPTION: class destructor
69 *
70 * PARAMETERS : none
71 *
72 * RETURN : void
73 *
74 *==========================================================================*/
~QCameraFOVControl()75 QCameraFOVControl::~QCameraFOVControl()
76 {
77 // De-initialize zoom translator lib
78 if (mZoomTranslator && mZoomTranslator->isInitialized()) {
79 mZoomTranslator->deInit();
80 }
81 }
82
83
84 /*===========================================================================
85 * FUNCTION : create
86 *
87 * DESCRIPTION: This is a static method to create FOV-control object. It calls
88 * private constructor of the class and only returns a valid object
89 * if it can successfully initialize the FOV-control.
90 *
91 * PARAMETERS :
92 * @capsMain : The capabilities for the main camera
93 * @capsAux : The capabilities for the aux camera
94 *
95 * RETURN : Valid object pointer if succeeds
96 * NULL if fails
97 *
98 *==========================================================================*/
create(cam_capability_t * capsMainCam,cam_capability_t * capsAuxCam)99 QCameraFOVControl* QCameraFOVControl::create(
100 cam_capability_t *capsMainCam,
101 cam_capability_t *capsAuxCam)
102 {
103 QCameraFOVControl *pFovControl = NULL;
104
105 if (capsMainCam && capsAuxCam) {
106 // Create FOV control object
107 pFovControl = new QCameraFOVControl();
108
109 if (pFovControl) {
110 bool success = false;
111 if (pFovControl->validateAndExtractParameters(capsMainCam, capsAuxCam)) {
112 // Based on focal lengths, map main and aux camera to wide and tele
113 if (pFovControl->mDualCamParams.paramsMain.focalLengthMm <
114 pFovControl->mDualCamParams.paramsAux.focalLengthMm) {
115 pFovControl->mFovControlData.camWide = CAM_TYPE_MAIN;
116 pFovControl->mFovControlData.camTele = CAM_TYPE_AUX;
117 pFovControl->mFovControlData.camState = STATE_WIDE;
118 } else {
119 pFovControl->mFovControlData.camWide = CAM_TYPE_AUX;
120 pFovControl->mFovControlData.camTele = CAM_TYPE_MAIN;
121 pFovControl->mFovControlData.camState = STATE_TELE;
122 }
123
124 // Initialize the master info to main camera
125 pFovControl->mFovControlResult.camMasterPreview = CAM_TYPE_MAIN;
126 pFovControl->mFovControlResult.camMaster3A = CAM_TYPE_MAIN;
127
128 // Check if LPM is enabled
129 char prop[PROPERTY_VALUE_MAX];
130 int lpmEnable = 1;
131 property_get("persist.dualcam.lpm.enable", prop, "1");
132 lpmEnable = atoi(prop);
133 if ((lpmEnable == 0) || (DUALCAM_LPM_ENABLE == 0)) {
134 pFovControl->mFovControlData.lpmEnabled = false;
135 } else {
136 pFovControl->mFovControlData.lpmEnabled = true;
137 }
138
139 // Open the external zoom translation library if requested
140 if (FOVC_USE_EXTERNAL_ZOOM_TRANSLATOR) {
141 pFovControl->mZoomTranslator =
142 QCameraExtZoomTranslator::create();
143 if (!pFovControl->mZoomTranslator) {
144 LOGE("Unable to open zoom translation lib");
145 }
146 }
147 success = true;
148 }
149
150 if (!success) {
151 LOGE("FOV-control: Failed to create an object");
152 delete pFovControl;
153 pFovControl = NULL;
154 }
155 } else {
156 LOGE("FOV-control: Failed to allocate memory for FOV-control object");
157 }
158 }
159
160 return pFovControl;
161 }
162
163
164 /*===========================================================================
165 * FUNCTION : consolidateCapabilities
166 *
167 * DESCRIPTION : Combine the capabilities from main and aux cameras to return
168 * the consolidated capabilities.
169 *
170 * PARAMETERS :
171 * @capsMainCam: Capabilities for the main camera
172 * @capsAuxCam : Capabilities for the aux camera
173 *
174 * RETURN : Consolidated capabilities
175 *
176 *==========================================================================*/
consolidateCapabilities(cam_capability_t * capsMainCam,cam_capability_t * capsAuxCam)177 cam_capability_t QCameraFOVControl::consolidateCapabilities(
178 cam_capability_t *capsMainCam,
179 cam_capability_t *capsAuxCam)
180 {
181 cam_capability_t capsConsolidated;
182 memset(&capsConsolidated, 0, sizeof(cam_capability_t));
183
184 if ((capsMainCam != NULL) &&
185 (capsAuxCam != NULL)) {
186
187 memcpy(&capsConsolidated, capsMainCam, sizeof(cam_capability_t));
188
189 // Consolidate preview sizes
190 uint32_t previewSizesTblCntMain = capsMainCam->preview_sizes_tbl_cnt;
191 uint32_t previewSizesTblCntAux = capsAuxCam->preview_sizes_tbl_cnt;
192 uint32_t previewSizesTblCntFinal = 0;
193
194 for (uint32_t i = 0; i < previewSizesTblCntMain; ++i) {
195 for (uint32_t j = 0; j < previewSizesTblCntAux; ++j) {
196 if ((capsMainCam->preview_sizes_tbl[i].width ==
197 capsAuxCam->preview_sizes_tbl[j].width) &&
198 (capsMainCam->preview_sizes_tbl[i].height ==
199 capsAuxCam->preview_sizes_tbl[j].height)) {
200 if (previewSizesTblCntFinal != i) {
201 capsConsolidated.preview_sizes_tbl[previewSizesTblCntFinal].width =
202 capsAuxCam->preview_sizes_tbl[j].width;
203 capsConsolidated.preview_sizes_tbl[previewSizesTblCntFinal].height =
204 capsMainCam->preview_sizes_tbl[j].height;
205 }
206 ++previewSizesTblCntFinal;
207 break;
208 }
209 }
210 }
211 capsConsolidated.preview_sizes_tbl_cnt = previewSizesTblCntFinal;
212
213 // Consolidate video sizes
214 uint32_t videoSizesTblCntMain = capsMainCam->video_sizes_tbl_cnt;
215 uint32_t videoSizesTblCntAux = capsAuxCam->video_sizes_tbl_cnt;
216 uint32_t videoSizesTblCntFinal = 0;
217
218 for (uint32_t i = 0; i < videoSizesTblCntMain; ++i) {
219 for (uint32_t j = 0; j < videoSizesTblCntAux; ++j) {
220 if ((capsMainCam->video_sizes_tbl[i].width ==
221 capsAuxCam->video_sizes_tbl[j].width) &&
222 (capsMainCam->video_sizes_tbl[i].height ==
223 capsAuxCam->video_sizes_tbl[j].height)) {
224 if (videoSizesTblCntFinal != i) {
225 capsConsolidated.video_sizes_tbl[videoSizesTblCntFinal].width =
226 capsAuxCam->video_sizes_tbl[j].width;
227 capsConsolidated.video_sizes_tbl[videoSizesTblCntFinal].height =
228 capsMainCam->video_sizes_tbl[j].height;
229 }
230 ++videoSizesTblCntFinal;
231 break;
232 }
233 }
234 }
235 capsConsolidated.video_sizes_tbl_cnt = videoSizesTblCntFinal;
236
237 // Consolidate livesnapshot sizes
238 uint32_t livesnapshotSizesTblCntMain = capsMainCam->livesnapshot_sizes_tbl_cnt;
239 uint32_t livesnapshotSizesTblCntAux = capsAuxCam->livesnapshot_sizes_tbl_cnt;
240 uint32_t livesnapshotSizesTblCntFinal = 0;
241
242 for (uint32_t i = 0; i < livesnapshotSizesTblCntMain; ++i) {
243 for (uint32_t j = 0; j < livesnapshotSizesTblCntAux; ++j) {
244 if ((capsMainCam->livesnapshot_sizes_tbl[i].width ==
245 capsAuxCam->livesnapshot_sizes_tbl[j].width) &&
246 (capsMainCam->livesnapshot_sizes_tbl[i].height ==
247 capsAuxCam->livesnapshot_sizes_tbl[j].height)) {
248 if (livesnapshotSizesTblCntFinal != i) {
249 capsConsolidated.livesnapshot_sizes_tbl[livesnapshotSizesTblCntFinal].width=
250 capsAuxCam->livesnapshot_sizes_tbl[j].width;
251 capsConsolidated.livesnapshot_sizes_tbl[livesnapshotSizesTblCntFinal].height=
252 capsMainCam->livesnapshot_sizes_tbl[j].height;
253 }
254 ++livesnapshotSizesTblCntFinal;
255 break;
256 }
257 }
258 }
259 capsConsolidated.livesnapshot_sizes_tbl_cnt = livesnapshotSizesTblCntFinal;
260
261 // Consolidate picture size
262 // Find max picture dimension for main camera
263 cam_dimension_t maxPicDimMain;
264 maxPicDimMain.width = 0;
265 maxPicDimMain.height = 0;
266
267 for(uint32_t i = 0; i < (capsMainCam->picture_sizes_tbl_cnt - 1); ++i) {
268 if ((maxPicDimMain.width * maxPicDimMain.height) <
269 (capsMainCam->picture_sizes_tbl[i].width *
270 capsMainCam->picture_sizes_tbl[i].height)) {
271 maxPicDimMain.width = capsMainCam->picture_sizes_tbl[i].width;
272 maxPicDimMain.height = capsMainCam->picture_sizes_tbl[i].height;
273 }
274 }
275
276 // Find max picture dimension for aux camera
277 cam_dimension_t maxPicDimAux;
278 maxPicDimAux.width = 0;
279 maxPicDimAux.height = 0;
280
281 for(uint32_t i = 0; i < (capsAuxCam->picture_sizes_tbl_cnt - 1); ++i) {
282 if ((maxPicDimAux.width * maxPicDimAux.height) <
283 (capsAuxCam->picture_sizes_tbl[i].width *
284 capsAuxCam->picture_sizes_tbl[i].height)) {
285 maxPicDimAux.width = capsAuxCam->picture_sizes_tbl[i].width;
286 maxPicDimAux.height = capsAuxCam->picture_sizes_tbl[i].height;
287 }
288 }
289
290 LOGH("MAIN Max picture wxh %dx%d", maxPicDimMain.width, maxPicDimMain.height);
291 LOGH("AUX Max picture wxh %dx%d", maxPicDimAux.width, maxPicDimAux.height);
292
293 // Choose the larger of the two max picture dimensions
294 if ((maxPicDimAux.width * maxPicDimAux.height) >
295 (maxPicDimMain.width * maxPicDimMain.height)) {
296 capsConsolidated.picture_sizes_tbl_cnt = capsAuxCam->picture_sizes_tbl_cnt;
297 memcpy(capsConsolidated.picture_sizes_tbl, capsAuxCam->picture_sizes_tbl,
298 (capsAuxCam->picture_sizes_tbl_cnt * sizeof(cam_dimension_t)));
299 }
300 LOGH("Consolidated Max picture wxh %dx%d", capsConsolidated.picture_sizes_tbl[0].width,
301 capsConsolidated.picture_sizes_tbl[0].height);
302
303 // Consolidate supported preview formats
304 uint32_t supportedPreviewFmtCntMain = capsMainCam->supported_preview_fmt_cnt;
305 uint32_t supportedPreviewFmtCntAux = capsAuxCam->supported_preview_fmt_cnt;
306 uint32_t supportedPreviewFmtCntFinal = 0;
307 for (uint32_t i = 0; i < supportedPreviewFmtCntMain; ++i) {
308 for (uint32_t j = 0; j < supportedPreviewFmtCntAux; ++j) {
309 if (capsMainCam->supported_preview_fmts[i] ==
310 capsAuxCam->supported_preview_fmts[j]) {
311 if (supportedPreviewFmtCntFinal != i) {
312 capsConsolidated.supported_preview_fmts[supportedPreviewFmtCntFinal] =
313 capsAuxCam->supported_preview_fmts[j];
314 }
315 ++supportedPreviewFmtCntFinal;
316 break;
317 }
318 }
319 }
320 capsConsolidated.supported_preview_fmt_cnt = supportedPreviewFmtCntFinal;
321
322 // Consolidate supported picture formats
323 uint32_t supportedPictureFmtCntMain = capsMainCam->supported_picture_fmt_cnt;
324 uint32_t supportedPictureFmtCntAux = capsAuxCam->supported_picture_fmt_cnt;
325 uint32_t supportedPictureFmtCntFinal = 0;
326 for (uint32_t i = 0; i < supportedPictureFmtCntMain; ++i) {
327 for (uint32_t j = 0; j < supportedPictureFmtCntAux; ++j) {
328 if (capsMainCam->supported_picture_fmts[i] ==
329 capsAuxCam->supported_picture_fmts[j]) {
330 if (supportedPictureFmtCntFinal != i) {
331 capsConsolidated.supported_picture_fmts[supportedPictureFmtCntFinal] =
332 capsAuxCam->supported_picture_fmts[j];
333 }
334 ++supportedPictureFmtCntFinal;
335 break;
336 }
337 }
338 }
339 capsConsolidated.supported_picture_fmt_cnt = supportedPictureFmtCntFinal;
340
341 if (mZoomTranslator) {
342 // Copy the opaque calibration data pointer and size
343 mFovControlData.zoomTransInitData.calibData =
344 capsConsolidated.related_cam_calibration.dc_otp_params;
345 mFovControlData.zoomTransInitData.calibDataSize =
346 capsConsolidated.related_cam_calibration.dc_otp_size;
347 }
348 }
349 return capsConsolidated;
350 }
351
352
353 /*===========================================================================
354 * FUNCTION : resetVars
355 *
356 * DESCRIPTION : Reset the variables used in FOV-control.
357 *
358 * PARAMETERS : None
359 *
360 * RETURN : None
361 *
362 *==========================================================================*/
resetVars()363 void QCameraFOVControl::resetVars()
364 {
365 // Copy the FOV-control settings for camera/camcorder from QCameraFOVControlSettings.h
366 if (mFovControlData.camcorderMode) {
367 mFovControlConfig.snapshotPPConfig.enablePostProcess =
368 FOVC_CAMCORDER_SNAPSHOT_PP_ENABLE;
369 } else {
370 mFovControlConfig.snapshotPPConfig.enablePostProcess = FOVC_CAM_SNAPSHOT_PP_ENABLE;
371 mFovControlConfig.snapshotPPConfig.zoomMin = FOVC_CAM_SNAPSHOT_PP_ZOOM_MIN;
372 mFovControlConfig.snapshotPPConfig.zoomMax = FOVC_CAM_SNAPSHOT_PP_ZOOM_MAX;
373 mFovControlConfig.snapshotPPConfig.luxMin = FOVC_CAM_SNAPSHOT_PP_LUX_MIN;
374 }
375 mFovControlConfig.auxSwitchBrightnessMin = FOVC_AUXCAM_SWITCH_LUX_MIN;
376 mFovControlConfig.auxSwitchFocusDistCmMin = FOVC_AUXCAM_SWITCH_FOCUS_DIST_CM_MIN;
377
378 mFovControlData.fallbackEnabled = FOVC_MAIN_CAM_FALLBACK_MECHANISM;
379
380 mFovControlConfig.zoomStableCountThreshold = FOVC_ZOOM_STABLE_COUNT_THRESHOLD;
381 mFovControlConfig.focusDistStableCountThreshold = FOVC_FOCUS_DIST_STABLE_COUNT_THRESHOLD;
382 mFovControlConfig.brightnessStableCountThreshold = FOVC_BRIGHTNESS_STABLE_COUNT_THRESHOLD;
383
384 // Reset variables
385 mFovControlData.zoomStableCount = 0;
386 mFovControlData.brightnessStableCount = 0;
387 mFovControlData.focusDistStableCount = 0;
388 mFovControlData.zoomDirection = ZOOM_STABLE;
389 mFovControlData.fallbackToWide = false;
390
391 mFovControlData.status3A.main.af.status = AF_INVALID;
392 mFovControlData.status3A.aux.af.status = AF_INVALID;
393
394 mFovControlData.afStatusMain = CAM_AF_STATE_INACTIVE;
395 mFovControlData.afStatusAux = CAM_AF_STATE_INACTIVE;
396
397 mFovControlData.wideCamStreaming = false;
398 mFovControlData.teleCamStreaming = false;
399
400 mFovControlData.spatialAlignResult.readyStatus = 0;
401 mFovControlData.spatialAlignResult.activeCameras = 0;
402 mFovControlData.spatialAlignResult.camMasterHint = 0;
403 mFovControlData.spatialAlignResult.shiftWide.shiftHorz = 0;
404 mFovControlData.spatialAlignResult.shiftWide.shiftVert = 0;
405 mFovControlData.spatialAlignResult.shiftTele.shiftHorz = 0;
406 mFovControlData.spatialAlignResult.shiftTele.shiftVert = 0;
407
408 // WA for now until the QTI solution is in place writing the spatial alignment ready status
409 mFovControlData.spatialAlignResult.readyStatus = 1;
410 }
411
412 /*===========================================================================
413 * FUNCTION : updateConfigSettings
414 *
415 * DESCRIPTION : Update the config settings such as margins and preview size
416 * and recalculate the transition parameters.
417 *
418 * PARAMETERS :
419 * @capsMainCam: Capabilities for the main camera
420 * @capsAuxCam : Capabilities for the aux camera
421 *
422 * RETURN :
423 * NO_ERROR : Success
424 * INVALID_OPERATION : Failure
425 *
426 *==========================================================================*/
updateConfigSettings(parm_buffer_t * paramsMainCam,parm_buffer_t * paramsAuxCam)427 int32_t QCameraFOVControl::updateConfigSettings(
428 parm_buffer_t* paramsMainCam,
429 parm_buffer_t* paramsAuxCam)
430 {
431 int32_t rc = INVALID_OPERATION;
432
433 if (paramsMainCam &&
434 paramsAuxCam &&
435 paramsMainCam->is_valid[CAM_INTF_META_STREAM_INFO] &&
436 paramsAuxCam->is_valid[CAM_INTF_META_STREAM_INFO]) {
437
438 cam_stream_size_info_t camMainStreamInfo;
439 READ_PARAM_ENTRY(paramsMainCam, CAM_INTF_META_STREAM_INFO, camMainStreamInfo);
440 mFovControlData.camcorderMode = false;
441
442 // Identify if in camera or camcorder mode
443 for (int i = 0; i < MAX_NUM_STREAMS; ++i) {
444 if (camMainStreamInfo.type[i] == CAM_STREAM_TYPE_VIDEO) {
445 mFovControlData.camcorderMode = true;
446 }
447 }
448
449 // Get the margins for the main camera. If video stream is present, the margins correspond
450 // to video stream. Otherwise, margins are copied from preview stream.
451 for (int i = 0; i < MAX_NUM_STREAMS; ++i) {
452 if (camMainStreamInfo.type[i] == CAM_STREAM_TYPE_VIDEO) {
453 mFovControlData.camMainWidthMargin = camMainStreamInfo.margins[i].widthMargins;
454 mFovControlData.camMainHeightMargin = camMainStreamInfo.margins[i].heightMargins;
455 }
456 if (camMainStreamInfo.type[i] == CAM_STREAM_TYPE_PREVIEW) {
457 // Update the preview dimension and ISP output size
458 mFovControlData.previewSize = camMainStreamInfo.stream_sizes[i];
459 mFovControlData.ispOutSize = camMainStreamInfo.stream_sz_plus_margin[i];
460 if (!mFovControlData.camcorderMode) {
461 mFovControlData.camMainWidthMargin =
462 camMainStreamInfo.margins[i].widthMargins;
463 mFovControlData.camMainHeightMargin =
464 camMainStreamInfo.margins[i].heightMargins;
465 break;
466 }
467 }
468 }
469
470 // Get the margins for the aux camera. If video stream is present, the margins correspond
471 // to the video stream. Otherwise, margins are copied from preview stream.
472 cam_stream_size_info_t camAuxStreamInfo;
473 READ_PARAM_ENTRY(paramsAuxCam, CAM_INTF_META_STREAM_INFO, camAuxStreamInfo);
474 for (int i = 0; i < MAX_NUM_STREAMS; ++i) {
475 if (camAuxStreamInfo.type[i] == CAM_STREAM_TYPE_VIDEO) {
476 mFovControlData.camAuxWidthMargin = camAuxStreamInfo.margins[i].widthMargins;
477 mFovControlData.camAuxHeightMargin = camAuxStreamInfo.margins[i].heightMargins;
478 }
479 if (camAuxStreamInfo.type[i] == CAM_STREAM_TYPE_PREVIEW) {
480 // Update the preview dimension
481 mFovControlData.previewSize = camAuxStreamInfo.stream_sizes[i];
482 if (!mFovControlData.camcorderMode) {
483 mFovControlData.camAuxWidthMargin = camAuxStreamInfo.margins[i].widthMargins;
484 mFovControlData.camAuxHeightMargin = camAuxStreamInfo.margins[i].heightMargins;
485 break;
486 }
487 }
488 }
489
490 #if 0 // Update to 07.01.01.253.071
491 // Get the sensor out dimensions
492 cam_dimension_t sensorDimMain = {0,0};
493 cam_dimension_t sensorDimAux = {0,0};
494 if (paramsMainCam->is_valid[CAM_INTF_PARM_RAW_DIMENSION]) {
495 READ_PARAM_ENTRY(paramsMainCam, CAM_INTF_PARM_RAW_DIMENSION, sensorDimMain);
496 }
497 if (paramsAuxCam->is_valid[CAM_INTF_PARM_RAW_DIMENSION]) {
498 READ_PARAM_ENTRY(paramsAuxCam, CAM_INTF_PARM_RAW_DIMENSION, sensorDimAux);
499 }
500 #endif // Update to 07.01.01.253.071
501
502 // Reset the internal variables
503 resetVars();
504
505 // Recalculate the transition parameters
506 if (calculateBasicFovRatio() && combineFovAdjustment()) {
507
508 calculateDualCamTransitionParams();
509
510 // Set initial camera state
511 float zoom = findZoomRatio(mFovControlData.zoomWide) /
512 (float)mFovControlData.zoomRatioTable[0];
513 if (zoom > mFovControlData.transitionParams.cutOverWideToTele) {
514 mFovControlResult.camMasterPreview = mFovControlData.camTele;
515 mFovControlResult.camMaster3A = mFovControlData.camTele;
516 mFovControlResult.activeCameras = (uint32_t)mFovControlData.camTele;
517 mFovControlData.camState = STATE_TELE;
518 LOGD("start camera state: TELE");
519 } else {
520 mFovControlResult.camMasterPreview = mFovControlData.camWide;
521 mFovControlResult.camMaster3A = mFovControlData.camWide;
522 mFovControlResult.activeCameras = (uint32_t)mFovControlData.camWide;
523 mFovControlData.camState = STATE_WIDE;
524 LOGD("start camera state: WIDE");
525 }
526 mFovControlResult.snapshotPostProcess = false;
527
528 // Deinit zoom translation lib if needed
529 if (mZoomTranslator && mZoomTranslator->isInitialized()) {
530 if (mZoomTranslator->deInit() != NO_ERROR) {
531 ALOGW("deinit failed for zoom translation lib");
532 }
533 }
534
535 #if 0 // Update to 07.01.01.253.071
536 // Initialize the zoom translation lib
537 if (mZoomTranslator) {
538 // Set the initialization data
539 mFovControlData.zoomTransInitData.previewDimension.width =
540 mFovControlData.previewSize.width;
541 mFovControlData.zoomTransInitData.previewDimension.height =
542 mFovControlData.previewSize.height;
543 mFovControlData.zoomTransInitData.ispOutDimension.width =
544 mFovControlData.ispOutSize.width;
545 mFovControlData.zoomTransInitData.ispOutDimension.height =
546 mFovControlData.ispOutSize.height;
547 mFovControlData.zoomTransInitData.sensorOutDimensionMain.width =
548 sensorDimMain.width;
549 mFovControlData.zoomTransInitData.sensorOutDimensionMain.height =
550 sensorDimMain.height;
551 mFovControlData.zoomTransInitData.sensorOutDimensionAux.width =
552 sensorDimAux.width;
553 mFovControlData.zoomTransInitData.sensorOutDimensionAux.height =
554 sensorDimAux.height;
555 mFovControlData.zoomTransInitData.zoomRatioTable =
556 mFovControlData.zoomRatioTable;
557 mFovControlData.zoomTransInitData.zoomRatioTableCount =
558 mFovControlData.zoomRatioTableCount;
559 mFovControlData.zoomTransInitData.mode = mFovControlData.camcorderMode ?
560 MODE_CAMCORDER : MODE_CAMERA;
561
562 if(mZoomTranslator->init(mFovControlData.zoomTransInitData) != NO_ERROR) {
563 LOGE("init failed for zoom translation lib");
564
565 // deinitialize the zoom translator and set to NULL
566 mZoomTranslator->deInit();
567 mZoomTranslator = NULL;
568 }
569 }
570 #endif // Update to 07.01.01.253.071
571
572 // FOV-control config is complete for the current use case
573 mFovControlData.configCompleted = true;
574 rc = NO_ERROR;
575 }
576 }
577
578 return rc;
579 }
580
581
582 /*===========================================================================
583 * FUNCTION : translateInputParams
584 *
585 * DESCRIPTION: Translate a subset of input parameters from main camera. As main
586 * and aux cameras have different properties/params, this translation
587 * is needed before the input parameters are sent to the aux camera.
588 *
589 * PARAMETERS :
590 * @paramsMainCam : Input parameters for main camera
591 * @paramsAuxCam : Input parameters for aux camera
592 *
593 * RETURN :
594 * NO_ERROR : Success
595 * INVALID_OPERATION : Failure
596 *
597 *==========================================================================*/
translateInputParams(parm_buffer_t * paramsMainCam,parm_buffer_t * paramsAuxCam)598 int32_t QCameraFOVControl::translateInputParams(
599 parm_buffer_t* paramsMainCam,
600 parm_buffer_t* paramsAuxCam)
601 {
602 int32_t rc = INVALID_OPERATION;
603 if (paramsMainCam && paramsAuxCam) {
604 // First copy all the parameters from main to aux and then translate the subset
605 memcpy(paramsAuxCam, paramsMainCam, sizeof(parm_buffer_t));
606
607 // Translate zoom
608 if (paramsMainCam->is_valid[CAM_INTF_PARM_ZOOM]) {
609 uint32_t userZoom = 0;
610 READ_PARAM_ENTRY(paramsMainCam, CAM_INTF_PARM_ZOOM, userZoom);
611 convertUserZoomToWideAndTele(userZoom);
612
613 // Update zoom values in the param buffers
614 uint32_t zoomMain = isMainCamFovWider() ?
615 mFovControlData.zoomWide : mFovControlData.zoomTele;
616 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsMainCam, CAM_INTF_PARM_ZOOM, zoomMain);
617
618 uint32_t zoomAux = isMainCamFovWider() ?
619 mFovControlData.zoomTele : mFovControlData.zoomWide;
620 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsAuxCam, CAM_INTF_PARM_ZOOM, zoomAux);
621
622 // Write the user zoom in main and aux param buffers
623 // The user zoom will always correspond to the wider camera
624 paramsMainCam->is_valid[CAM_INTF_PARM_DC_USERZOOM] = 1;
625 paramsAuxCam->is_valid[CAM_INTF_PARM_DC_USERZOOM] = 1;
626
627 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsMainCam, CAM_INTF_PARM_DC_USERZOOM,
628 mFovControlData.zoomWide);
629 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsAuxCam, CAM_INTF_PARM_DC_USERZOOM,
630 mFovControlData.zoomWide);
631
632 // Generate FOV-control result
633 generateFovControlResult();
634 }
635
636 // Translate focus areas
637 if (paramsMainCam->is_valid[CAM_INTF_PARM_AF_ROI]) {
638 cam_roi_info_t roiAfMain;
639 cam_roi_info_t roiAfAux;
640 READ_PARAM_ENTRY(paramsMainCam, CAM_INTF_PARM_AF_ROI, roiAfMain);
641 if (roiAfMain.num_roi > 0) {
642 roiAfAux = translateFocusAreas(roiAfMain, CAM_TYPE_AUX);
643 roiAfMain = translateFocusAreas(roiAfMain, CAM_TYPE_MAIN);
644 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsAuxCam, CAM_INTF_PARM_AF_ROI, roiAfAux);
645 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsMainCam, CAM_INTF_PARM_AF_ROI, roiAfMain);
646 }
647 }
648
649 // Translate metering areas
650 if (paramsMainCam->is_valid[CAM_INTF_PARM_AEC_ROI]) {
651 cam_set_aec_roi_t roiAecMain;
652 cam_set_aec_roi_t roiAecAux;
653 READ_PARAM_ENTRY(paramsMainCam, CAM_INTF_PARM_AEC_ROI, roiAecMain);
654 if (roiAecMain.aec_roi_enable == CAM_AEC_ROI_ON) {
655 roiAecAux = translateMeteringAreas(roiAecMain, CAM_TYPE_AUX);
656 roiAecMain = translateMeteringAreas(roiAecMain, CAM_TYPE_MAIN);
657 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsAuxCam, CAM_INTF_PARM_AEC_ROI, roiAecAux);
658 ADD_SET_PARAM_ENTRY_TO_BATCH(paramsMainCam, CAM_INTF_PARM_AEC_ROI, roiAecMain);
659 }
660 }
661 rc = NO_ERROR;
662 }
663 return rc;
664 }
665
666
667 /*===========================================================================
668 * FUNCTION : processResultMetadata
669 *
670 * DESCRIPTION: Process the metadata from main and aux cameras to generate the
671 * result metadata. The result metadata should be the metadata
672 * coming from the master camera. If aux camera is master, the
673 * subset of the metadata needs to be translated to main as that's
674 * the only camera seen by the application.
675 *
676 * PARAMETERS :
677 * @metaMain : metadata for main camera
678 * @metaAux : metadata for aux camera
679 *
680 * RETURN :
681 * Result metadata for the logical camera. After successfully processing main
682 * and aux metadata, the result metadata points to either main or aux metadata
683 * based on which one was the master. In case of failure, it returns NULL.
684 *==========================================================================*/
processResultMetadata(metadata_buffer_t * metaMain,metadata_buffer_t * metaAux)685 metadata_buffer_t* QCameraFOVControl::processResultMetadata(
686 metadata_buffer_t* metaMain,
687 metadata_buffer_t* metaAux)
688 {
689 metadata_buffer_t* metaResult = NULL;
690
691 if (metaMain || metaAux) {
692 metadata_buffer_t *meta = metaMain ? metaMain : metaAux;
693 cam_sync_type_t masterCam = mFovControlResult.camMasterPreview;
694
695 mMutex.lock();
696 // Book-keep the needed metadata from main camera and aux camera
697 IF_META_AVAILABLE(cam_sac_output_info_t, spatialAlignOutput,
698 CAM_INTF_META_DC_SAC_OUTPUT_INFO, meta) {
699
700 // Get master camera hint
701 if (spatialAlignOutput->is_master_hint_valid) {
702 uint8_t master = spatialAlignOutput->master_hint;
703 if (master == CAM_ROLE_WIDE) {
704 mFovControlData.spatialAlignResult.camMasterHint = mFovControlData.camWide;
705 } else if (master == CAM_ROLE_TELE) {
706 mFovControlData.spatialAlignResult.camMasterHint = mFovControlData.camTele;
707 }
708 }
709
710 // Get master camera used for the preview in the frame corresponding to this metadata
711 if (spatialAlignOutput->is_master_preview_valid) {
712 uint8_t master = spatialAlignOutput->master_preview;
713 if (master == CAM_ROLE_WIDE) {
714 masterCam = mFovControlData.camWide;
715 mFovControlData.spatialAlignResult.camMasterPreview = masterCam;
716 } else if (master == CAM_ROLE_TELE) {
717 masterCam = mFovControlData.camTele;
718 mFovControlData.spatialAlignResult.camMasterPreview = masterCam;
719 }
720 }
721
722 // Get master camera used for 3A in the frame corresponding to this metadata
723 if (spatialAlignOutput->is_master_3A_valid) {
724 uint8_t master = spatialAlignOutput->master_3A;
725 if (master == CAM_ROLE_WIDE) {
726 mFovControlData.spatialAlignResult.camMaster3A = mFovControlData.camWide;
727 } else if (master == CAM_ROLE_TELE) {
728 mFovControlData.spatialAlignResult.camMaster3A = mFovControlData.camTele;
729 }
730 }
731
732 // Get spatial alignment ready status
733 if (spatialAlignOutput->is_ready_status_valid) {
734 mFovControlData.spatialAlignResult.readyStatus = spatialAlignOutput->ready_status;
735 }
736 }
737
738 metadata_buffer_t *metaWide = isMainCamFovWider() ? metaMain : metaAux;
739 metadata_buffer_t *metaTele = isMainCamFovWider() ? metaAux : metaMain;
740
741 // Get spatial alignment output info for wide camera
742 if (metaWide) {
743 IF_META_AVAILABLE(cam_sac_output_info_t, spatialAlignOutput,
744 CAM_INTF_META_DC_SAC_OUTPUT_INFO, metaWide) {
745 // Get spatial alignment output shift for wide camera
746
747 if (spatialAlignOutput->is_output_shift_valid) {
748 // Calculate the spatial alignment shift for the current stream dimensions based
749 // on the reference resolution used for the output shift.
750 float horzShiftFactor = (float)mFovControlData.previewSize.width /
751 spatialAlignOutput->reference_res_for_output_shift.width;
752 float vertShiftFactor = (float)mFovControlData.previewSize.height /
753 spatialAlignOutput->reference_res_for_output_shift.height;
754
755 mFovControlData.spatialAlignResult.shiftWide.shiftHorz =
756 spatialAlignOutput->output_shift.shift_horz * horzShiftFactor;
757 mFovControlData.spatialAlignResult.shiftWide.shiftVert =
758 spatialAlignOutput->output_shift.shift_vert * vertShiftFactor;
759
760 LOGD("SAC output shift for Wide: x:%d, y:%d",
761 mFovControlData.spatialAlignResult.shiftWide.shiftHorz,
762 mFovControlData.spatialAlignResult.shiftWide.shiftVert);
763 }
764
765 // Get the AF roi shift for wide camera
766 if (spatialAlignOutput->is_focus_roi_shift_valid) {
767 // Calculate the spatial alignment shift for the current stream dimensions based
768 // on the reference resolution used for the output shift.
769 float horzShiftFactor = (float)mFovControlData.previewSize.width /
770 spatialAlignOutput->reference_res_for_focus_roi_shift.width;
771 float vertShiftFactor = (float)mFovControlData.previewSize.height /
772 spatialAlignOutput->reference_res_for_focus_roi_shift.height;
773
774 mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftHorz =
775 spatialAlignOutput->focus_roi_shift.shift_horz * horzShiftFactor;
776 mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftVert =
777 spatialAlignOutput->focus_roi_shift.shift_vert * vertShiftFactor;
778
779 LOGD("SAC AF ROI shift for Wide: x:%d, y:%d",
780 mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftHorz,
781 mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftVert);
782 }
783 }
784 }
785
786 // Get spatial alignment output info for tele camera
787 if (metaTele) {
788 IF_META_AVAILABLE(cam_sac_output_info_t, spatialAlignOutput,
789 CAM_INTF_META_DC_SAC_OUTPUT_INFO, metaTele) {
790
791 // Get spatial alignment output shift for tele camera
792 if (spatialAlignOutput->is_output_shift_valid) {
793 // Calculate the spatial alignment shift for the current stream dimensions based
794 // on the reference resolution used for the output shift.
795 float horzShiftFactor = (float)mFovControlData.previewSize.width /
796 spatialAlignOutput->reference_res_for_output_shift.width;
797 float vertShiftFactor = (float)mFovControlData.previewSize.height /
798 spatialAlignOutput->reference_res_for_output_shift.height;
799
800 mFovControlData.spatialAlignResult.shiftTele.shiftHorz =
801 spatialAlignOutput->output_shift.shift_horz * horzShiftFactor;
802 mFovControlData.spatialAlignResult.shiftTele.shiftVert =
803 spatialAlignOutput->output_shift.shift_vert * vertShiftFactor;
804
805 LOGD("SAC output shift for Tele: x:%d, y:%d",
806 mFovControlData.spatialAlignResult.shiftTele.shiftHorz,
807 mFovControlData.spatialAlignResult.shiftTele.shiftVert);
808 }
809
810 // Get the AF roi shift for tele camera
811 if (spatialAlignOutput->is_focus_roi_shift_valid) {
812 // Calculate the spatial alignment shift for the current stream dimensions based
813 // on the reference resolution used for the output shift.
814 float horzShiftFactor = (float)mFovControlData.previewSize.width /
815 spatialAlignOutput->reference_res_for_focus_roi_shift.width;
816 float vertShiftFactor = (float)mFovControlData.previewSize.height /
817 spatialAlignOutput->reference_res_for_focus_roi_shift.height;
818
819 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftHorz =
820 spatialAlignOutput->focus_roi_shift.shift_horz * horzShiftFactor;
821 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftVert =
822 spatialAlignOutput->focus_roi_shift.shift_vert * vertShiftFactor;
823
824 LOGD("SAC AF ROI shift for Tele: x:%d, y:%d",
825 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftHorz,
826 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftVert);
827 }
828 }
829 }
830
831 // Update the camera streaming status
832 if (metaWide) {
833 mFovControlData.wideCamStreaming = true;
834 IF_META_AVAILABLE(uint8_t, enableLPM, CAM_INTF_META_DC_LOW_POWER_ENABLE, metaWide) {
835 if (*enableLPM) {
836 // If LPM enabled is 1, this is probably the last metadata returned
837 // before going into LPM state
838 mFovControlData.wideCamStreaming = false;
839
840 // Update active cameras requested by spatial alignment
841 mFovControlData.spatialAlignResult.activeCameras &= ~mFovControlData.camWide;
842 } else {
843 mFovControlData.spatialAlignResult.activeCameras |= mFovControlData.camWide;
844 }
845 }
846 }
847
848 if (metaTele) {
849 mFovControlData.teleCamStreaming = true;
850 IF_META_AVAILABLE(uint8_t, enableLPM, CAM_INTF_META_DC_LOW_POWER_ENABLE, metaTele) {
851 if (*enableLPM) {
852 // If LPM enabled is 1, this is probably the last metadata returned
853 // before going into LPM state
854 mFovControlData.teleCamStreaming = false;
855
856 // Update active cameras requested by spatial alignment
857 mFovControlData.spatialAlignResult.activeCameras &= ~mFovControlData.camTele;
858 } else {
859 mFovControlData.spatialAlignResult.activeCameras |= mFovControlData.camTele;
860 }
861 }
862 }
863
864 // Get AF status
865 if (metaMain) {
866 IF_META_AVAILABLE(uint32_t, afState, CAM_INTF_META_AF_STATE, metaMain) {
867 if ((*afState) != CAM_AF_STATE_INACTIVE) {
868 mFovControlData.status3A.main.af.status = AF_VALID;
869 } else {
870 mFovControlData.status3A.main.af.status = AF_INVALID;
871 }
872 mFovControlData.afStatusMain = *afState;
873 LOGD("AF state: Main cam: %d", mFovControlData.afStatusMain);
874 }
875
876 IF_META_AVAILABLE(float, luxIndex, CAM_INTF_META_AEC_LUX_INDEX, metaMain) {
877 mFovControlData.status3A.main.ae.luxIndex = *luxIndex;
878 LOGD("Lux Index: Main cam: %f", mFovControlData.status3A.main.ae.luxIndex);
879 }
880
881 IF_META_AVAILABLE(int32_t, objDist, CAM_INTF_META_AF_OBJ_DIST_CM, metaMain) {
882 mFovControlData.status3A.main.af.focusDistCm = (*objDist < 0) ? 0 : *objDist;
883 LOGD("Obj Dist: Main cam: %d", mFovControlData.status3A.main.af.focusDistCm);
884 }
885 }
886 if (metaAux) {
887 IF_META_AVAILABLE(uint32_t, afState, CAM_INTF_META_AF_STATE, metaAux) {
888 if ((*afState) != CAM_AF_STATE_INACTIVE) {
889 mFovControlData.status3A.aux.af.status = AF_VALID;
890 } else {
891 mFovControlData.status3A.aux.af.status = AF_INVALID;
892 }
893 mFovControlData.afStatusAux = *afState;
894 LOGD("AF state: Aux cam: %d", mFovControlData.afStatusAux);
895 }
896
897 IF_META_AVAILABLE(float, luxIndex, CAM_INTF_META_AEC_LUX_INDEX, metaAux) {
898 mFovControlData.status3A.aux.ae.luxIndex = *luxIndex;
899 LOGD("Lux Index: Aux cam: %f", mFovControlData.status3A.aux.ae.luxIndex);
900 }
901
902 IF_META_AVAILABLE(int32_t, objDist, CAM_INTF_META_AF_OBJ_DIST_CM, metaAux) {
903 mFovControlData.status3A.aux.af.focusDistCm = (*objDist < 0) ? 0 : *objDist;
904 LOGD("Obj Dist: Aux cam: %d", mFovControlData.status3A.aux.af.focusDistCm);
905 }
906 }
907
908 if ((masterCam == CAM_TYPE_AUX) && metaAux) {
909 // Translate face detection ROI from aux camera
910 IF_META_AVAILABLE(cam_face_detection_data_t, metaFD,
911 CAM_INTF_META_FACE_DETECTION, metaAux) {
912 cam_face_detection_data_t metaFDTranslated;
913 metaFDTranslated = translateRoiFD(*metaFD, CAM_TYPE_AUX);
914 ADD_SET_PARAM_ENTRY_TO_BATCH(metaAux, CAM_INTF_META_FACE_DETECTION,
915 metaFDTranslated);
916 }
917 metaResult = metaAux;
918 }
919 else if ((masterCam == CAM_TYPE_MAIN) && metaMain) {
920 // Translate face detection ROI from main camera
921 IF_META_AVAILABLE(cam_face_detection_data_t, metaFD,
922 CAM_INTF_META_FACE_DETECTION, metaMain) {
923 cam_face_detection_data_t metaFDTranslated;
924 metaFDTranslated = translateRoiFD(*metaFD, CAM_TYPE_MAIN);
925 ADD_SET_PARAM_ENTRY_TO_BATCH(metaMain, CAM_INTF_META_FACE_DETECTION,
926 metaFDTranslated);
927 }
928 metaResult = metaMain;
929 } else {
930 // Metadata for the master camera was dropped
931 metaResult = NULL;
932 }
933
934 // If snapshot postprocess is enabled, consolidate the AF status to be sent to the app
935 // when in the transition state.
936 // Only return focused if both are focused.
937 if ((mFovControlResult.snapshotPostProcess == true) &&
938 (mFovControlData.camState == STATE_TRANSITION) &&
939 metaResult) {
940 if (((mFovControlData.afStatusMain == CAM_AF_STATE_FOCUSED_LOCKED) ||
941 (mFovControlData.afStatusMain == CAM_AF_STATE_NOT_FOCUSED_LOCKED)) &&
942 ((mFovControlData.afStatusAux == CAM_AF_STATE_FOCUSED_LOCKED) ||
943 (mFovControlData.afStatusAux == CAM_AF_STATE_NOT_FOCUSED_LOCKED))) {
944 // If both indicate focused, return focused.
945 // If either one indicates 'not focused', return 'not focused'.
946 if ((mFovControlData.afStatusMain == CAM_AF_STATE_FOCUSED_LOCKED) &&
947 (mFovControlData.afStatusAux == CAM_AF_STATE_FOCUSED_LOCKED)) {
948 ADD_SET_PARAM_ENTRY_TO_BATCH(metaResult, CAM_INTF_META_AF_STATE,
949 CAM_AF_STATE_FOCUSED_LOCKED);
950 } else {
951 ADD_SET_PARAM_ENTRY_TO_BATCH(metaResult, CAM_INTF_META_AF_STATE,
952 CAM_AF_STATE_NOT_FOCUSED_LOCKED);
953 }
954 } else {
955 // If either one indicates passive state or active scan, return that state
956 if ((mFovControlData.afStatusMain != CAM_AF_STATE_FOCUSED_LOCKED) &&
957 (mFovControlData.afStatusMain != CAM_AF_STATE_NOT_FOCUSED_LOCKED)) {
958 ADD_SET_PARAM_ENTRY_TO_BATCH(metaResult, CAM_INTF_META_AF_STATE,
959 mFovControlData.afStatusMain);
960 } else {
961 ADD_SET_PARAM_ENTRY_TO_BATCH(metaResult, CAM_INTF_META_AF_STATE,
962 mFovControlData.afStatusAux);
963 }
964 }
965 IF_META_AVAILABLE(uint32_t, afState, CAM_INTF_META_AF_STATE, metaResult) {
966 LOGD("Result AF state: %d", *afState);
967 }
968 }
969
970 mMutex.unlock();
971
972 // Generate FOV-control result only if the result meta is valid
973 if (metaResult) {
974 generateFovControlResult();
975 }
976 }
977 return metaResult;
978 }
979
980
981 /*===========================================================================
982 * FUNCTION : generateFovControlResult
983 *
984 * DESCRIPTION: Generate FOV control result
985 *
986 * PARAMETERS : None
987 *
988 * RETURN : None
989 *
990 *==========================================================================*/
generateFovControlResult()991 void QCameraFOVControl::generateFovControlResult()
992 {
993 Mutex::Autolock lock(mMutex);
994
995 float zoom = findZoomRatio(mFovControlData.zoomWide) / (float)mFovControlData.zoomRatioTable[0];
996 uint32_t zoomWide = mFovControlData.zoomWide;
997 uint32_t zoomWidePrev = mFovControlData.zoomWidePrev;
998
999 if (mFovControlData.configCompleted == false) {
1000 // Return as invalid result if the FOV-control configuration is not yet complete
1001 mFovControlResult.isValid = false;
1002 return;
1003 }
1004
1005 // Update previous zoom value
1006 mFovControlData.zoomWidePrev = mFovControlData.zoomWide;
1007
1008 uint32_t currentBrightness = 0;
1009 uint32_t currentFocusDist = 0;
1010
1011 if (mFovControlResult.camMasterPreview == CAM_TYPE_MAIN) {
1012 currentBrightness = mFovControlData.status3A.main.ae.luxIndex;
1013 currentFocusDist = mFovControlData.status3A.main.af.focusDistCm;
1014 } else if (mFovControlResult.camMasterPreview == CAM_TYPE_AUX) {
1015 currentBrightness = mFovControlData.status3A.aux.ae.luxIndex;
1016 currentFocusDist = mFovControlData.status3A.aux.af.focusDistCm;
1017 }
1018
1019 float transitionLow = mFovControlData.transitionParams.transitionLow;
1020 float transitionHigh = mFovControlData.transitionParams.transitionHigh;
1021 float cutOverWideToTele = mFovControlData.transitionParams.cutOverWideToTele;
1022 float cutOverTeleToWide = mFovControlData.transitionParams.cutOverTeleToWide;
1023
1024 cam_sync_type_t camWide = mFovControlData.camWide;
1025 cam_sync_type_t camTele = mFovControlData.camTele;
1026
1027 uint16_t thresholdBrightness = mFovControlConfig.auxSwitchBrightnessMin;
1028 uint16_t thresholdFocusDist = mFovControlConfig.auxSwitchFocusDistCmMin;
1029
1030 if (zoomWide == zoomWidePrev) {
1031 mFovControlData.zoomDirection = ZOOM_STABLE;
1032 ++mFovControlData.zoomStableCount;
1033 } else if (zoomWide > zoomWidePrev) {
1034 mFovControlData.zoomDirection = ZOOM_IN;
1035 mFovControlData.zoomStableCount = 0;
1036 } else {
1037 mFovControlData.zoomDirection = ZOOM_OUT;
1038 mFovControlData.zoomStableCount = 0;
1039 }
1040
1041 // Update snapshot post-process flags
1042 if (mFovControlConfig.snapshotPPConfig.enablePostProcess &&
1043 (zoom >= mFovControlConfig.snapshotPPConfig.zoomMin) &&
1044 (zoom <= mFovControlConfig.snapshotPPConfig.zoomMax)) {
1045 mFovControlResult.snapshotPostProcessZoomRange = true;
1046 } else {
1047 mFovControlResult.snapshotPostProcessZoomRange = false;
1048 }
1049
1050 if (mFovControlResult.snapshotPostProcessZoomRange &&
1051 (currentBrightness >= mFovControlConfig.snapshotPPConfig.luxMin) &&
1052 (currentFocusDist >= mFovControlConfig.snapshotPPConfig.focusDistanceMin)) {
1053 mFovControlResult.snapshotPostProcess = true;
1054 } else {
1055 mFovControlResult.snapshotPostProcess = false;
1056 }
1057
1058 switch (mFovControlData.camState) {
1059 case STATE_WIDE:
1060 // If the scene continues to be bright, update stable count; reset otherwise
1061 if (currentBrightness >= thresholdBrightness) {
1062 ++mFovControlData.brightnessStableCount;
1063 } else {
1064 mFovControlData.brightnessStableCount = 0;
1065 }
1066
1067 // If the scene continues to be non-macro, update stable count; reset otherwise
1068 if (currentFocusDist >= thresholdFocusDist) {
1069 ++mFovControlData.focusDistStableCount;
1070 } else {
1071 mFovControlData.focusDistStableCount = 0;
1072 }
1073
1074 // Reset fallback to main flag if zoom is less than cutover point
1075 if (zoom <= cutOverTeleToWide) {
1076 mFovControlData.fallbackToWide = false;
1077 }
1078
1079 // Check if the scene is good for aux (bright and far focused)
1080 if ((currentBrightness >= thresholdBrightness) &&
1081 (currentFocusDist >= thresholdFocusDist)) {
1082 // Lower constraint if zooming in or if snapshot postprocessing is true
1083 if (mFovControlResult.snapshotPostProcess ||
1084 (((zoom >= transitionLow) ||
1085 (sacRequestedDualZone())) &&
1086 (mFovControlData.zoomDirection == ZOOM_IN) &&
1087 (mFovControlData.fallbackToWide == false))) {
1088 mFovControlData.camState = STATE_TRANSITION;
1089 mFovControlResult.activeCameras = (camWide | camTele);
1090 }
1091 // Higher constraint if not zooming in
1092 else if ((zoom > cutOverWideToTele) &&
1093 (mFovControlData.brightnessStableCount >=
1094 mFovControlConfig.brightnessStableCountThreshold) &&
1095 (mFovControlData.focusDistStableCount >=
1096 mFovControlConfig.focusDistStableCountThreshold)) {
1097 // Enter the transition state
1098 mFovControlData.camState = STATE_TRANSITION;
1099 mFovControlResult.activeCameras = (camWide | camTele);
1100
1101 // Reset fallback to wide flag
1102 mFovControlData.fallbackToWide = false;
1103
1104 // Reset zoom stable count
1105 mFovControlData.zoomStableCount = 0;
1106 }
1107 }
1108 break;
1109
1110 case STATE_TRANSITION:
1111 // Reset brightness stable count
1112 mFovControlData.brightnessStableCount = 0;
1113 // Reset focus distance stable count
1114 mFovControlData.focusDistStableCount = 0;
1115
1116 // Set the master info
1117 // Switch to wide
1118 if ((mFovControlResult.camMasterPreview == camTele) &&
1119 canSwitchMasterTo(CAM_TYPE_WIDE)) {
1120 mFovControlResult.camMasterPreview = camWide;
1121 mFovControlResult.camMaster3A = camWide;
1122 }
1123 // switch to tele
1124 else if ((mFovControlResult.camMasterPreview == camWide) &&
1125 canSwitchMasterTo(CAM_TYPE_TELE)) {
1126 mFovControlResult.camMasterPreview = camTele;
1127 mFovControlResult.camMaster3A = camTele;
1128 }
1129
1130 // Change the transition state if necessary.
1131 // If fallback to wide is initiated, try to move to wide state
1132 if (mFovControlData.fallbackEnabled && mFovControlData.fallbackToWide) {
1133 if (mFovControlResult.camMasterPreview == camWide) {
1134 mFovControlData.camState = STATE_WIDE;
1135 mFovControlResult.activeCameras = camWide;
1136 }
1137 }
1138 // If snapshot post processing is required, do not change the state.
1139 else if (mFovControlResult.snapshotPostProcess == false) {
1140 if ((zoom < transitionLow) &&
1141 !sacRequestedDualZone() &&
1142 (mFovControlResult.camMasterPreview == camWide)) {
1143 mFovControlData.camState = STATE_WIDE;
1144 mFovControlResult.activeCameras = camWide;
1145 } else if ((zoom > transitionHigh) &&
1146 !sacRequestedDualZone() &&
1147 (mFovControlResult.camMasterPreview == camTele)) {
1148 mFovControlData.camState = STATE_TELE;
1149 mFovControlResult.activeCameras = camTele;
1150 } else if (mFovControlData.zoomStableCount >=
1151 mFovControlConfig.zoomStableCountThreshold) {
1152 // If the zoom is stable put the non-master camera to LPM for power optimization
1153 if (mFovControlResult.camMasterPreview == camWide) {
1154 mFovControlData.camState = STATE_WIDE;
1155 mFovControlResult.activeCameras = camWide;
1156 } else {
1157 mFovControlData.camState = STATE_TELE;
1158 mFovControlResult.activeCameras = camTele;
1159 }
1160 }
1161 }
1162 break;
1163
1164 case STATE_TELE:
1165 // If the scene continues to be dark, update stable count; reset otherwise
1166 if (currentBrightness < thresholdBrightness) {
1167 ++mFovControlData.brightnessStableCount;
1168 } else {
1169 mFovControlData.brightnessStableCount = 0;
1170 }
1171
1172 // If the scene continues to be macro, update stable count; reset otherwise
1173 if (currentFocusDist < thresholdFocusDist) {
1174 ++mFovControlData.focusDistStableCount;
1175 } else {
1176 mFovControlData.focusDistStableCount = 0;
1177 }
1178
1179 // Lower constraint if zooming out or if the snapshot postprocessing is true
1180 if (mFovControlResult.snapshotPostProcess ||
1181 (((zoom <= transitionHigh) || sacRequestedDualZone()) &&
1182 (mFovControlData.zoomDirection == ZOOM_OUT))) {
1183 mFovControlData.camState = STATE_TRANSITION;
1184 mFovControlResult.activeCameras = (camWide | camTele);
1185 }
1186 // Higher constraint if not zooming out. Only if fallback is enabled
1187 else if (((currentBrightness < thresholdBrightness) ||
1188 (currentFocusDist < thresholdFocusDist)) &&
1189 mFovControlData.fallbackEnabled) {
1190 // Enter transition state if brightness or focus distance is below threshold
1191 if ((mFovControlData.brightnessStableCount >=
1192 mFovControlConfig.brightnessStableCountThreshold) ||
1193 (mFovControlData.focusDistStableCount >=
1194 mFovControlConfig.focusDistStableCountThreshold)) {
1195 mFovControlData.camState = STATE_TRANSITION;
1196 mFovControlResult.activeCameras = (camWide | camTele);
1197
1198 // Reset zoom stable count and set fallback flag to true
1199 mFovControlData.zoomStableCount = 0;
1200 mFovControlData.fallbackToWide = true;
1201 LOGD("Low light/Macro scene - fall back to Wide from Tele");
1202 }
1203 }
1204 break;
1205 }
1206
1207 // Update snapshot postprocess result based on fall back to wide decision
1208 if (mFovControlData.fallbackEnabled && mFovControlData.fallbackToWide) {
1209 mFovControlResult.snapshotPostProcess = false;
1210 }
1211
1212 mFovControlResult.isValid = true;
1213 // Debug print for the FOV-control result
1214 LOGD("Effective zoom: %f", zoom);
1215 LOGD("zoom direction: %d", (uint32_t)mFovControlData.zoomDirection);
1216 LOGD("zoomWide: %d, zoomTele: %d", zoomWide, mFovControlData.zoomTele);
1217 LOGD("Snapshot postprocess: %d", mFovControlResult.snapshotPostProcess);
1218 LOGD("Master camera : %s", (mFovControlResult.camMasterPreview == CAM_TYPE_MAIN) ?
1219 "CAM_TYPE_MAIN" : "CAM_TYPE_AUX");
1220 LOGD("Master camera for preview: %s",
1221 (mFovControlResult.camMasterPreview == camWide ) ? "Wide" : "Tele");
1222 LOGD("Master camera for 3A : %s",
1223 (mFovControlResult.camMaster3A == camWide ) ? "Wide" : "Tele");
1224 LOGD("Wide camera status : %s",
1225 (mFovControlResult.activeCameras & camWide) ? "Active" : "LPM");
1226 LOGD("Tele camera status : %s",
1227 (mFovControlResult.activeCameras & camTele) ? "Active" : "LPM");
1228 LOGD("transition state: %s", ((mFovControlData.camState == STATE_WIDE) ? "STATE_WIDE" :
1229 ((mFovControlData.camState == STATE_TELE) ? "STATE_TELE" : "STATE_TRANSITION" )));
1230 }
1231
1232
1233 /*===========================================================================
1234 * FUNCTION : getFovControlResult
1235 *
1236 * DESCRIPTION: Return FOV-control result
1237 *
1238 * PARAMETERS : None
1239 *
1240 * RETURN : FOV-control result
1241 *
1242 *==========================================================================*/
getFovControlResult()1243 fov_control_result_t QCameraFOVControl::getFovControlResult()
1244 {
1245 Mutex::Autolock lock(mMutex);
1246 fov_control_result_t fovControlResult = mFovControlResult;
1247 return fovControlResult;
1248 }
1249
1250
1251 /*===========================================================================
1252 * FUNCTION : isMainCamFovWider
1253 *
1254 * DESCRIPTION : Check if the main camera FOV is wider than aux
1255 *
1256 * PARAMETERS : None
1257 *
1258 * RETURN :
1259 * true : If main cam FOV is wider than tele
1260 * false : If main cam FOV is narrower than tele
1261 *
1262 *==========================================================================*/
isMainCamFovWider()1263 inline bool QCameraFOVControl::isMainCamFovWider()
1264 {
1265 if (mDualCamParams.paramsMain.focalLengthMm <
1266 mDualCamParams.paramsAux.focalLengthMm) {
1267 return true;
1268 } else {
1269 return false;
1270 }
1271 }
1272
1273
1274 /*===========================================================================
1275 * FUNCTION : sacRequestedDualZone
1276 *
1277 * DESCRIPTION : Check if Spatial alignment block requested both the cameras to be active.
1278 * The request is valid only when LPM is enabled.
1279 *
1280 * PARAMETERS : None
1281 *
1282 * RETURN :
1283 * true : If dual zone is requested with LPM enabled
1284 * false : If LPM is disabled or if dual zone is not requested with LPM enabled
1285 *
1286 *==========================================================================*/
sacRequestedDualZone()1287 inline bool QCameraFOVControl::sacRequestedDualZone()
1288 {
1289 bool ret = false;
1290 cam_sync_type_t camWide = mFovControlData.camWide;
1291 cam_sync_type_t camTele = mFovControlData.camTele;
1292
1293 // Return true if Spatial alignment block requested both the cameras to be active
1294 // in the case of lpm enabled
1295 if ((mFovControlData.spatialAlignResult.activeCameras == (camWide | camTele)) &&
1296 (mFovControlData.lpmEnabled)) {
1297 ret = true;
1298 }
1299 return ret;
1300 }
1301
1302
1303 /*===========================================================================
1304 * FUNCTION : canSwitchMasterTo
1305 *
1306 * DESCRIPTION : Check if the master can be switched to the camera- cam.
1307 *
1308 * PARAMETERS :
1309 * @cam : cam type
1310 *
1311 * RETURN :
1312 * true : If master can be switched
1313 * false : If master cannot be switched
1314 *
1315 *==========================================================================*/
canSwitchMasterTo(cam_type cam)1316 bool QCameraFOVControl::canSwitchMasterTo(
1317 cam_type cam)
1318 {
1319 bool ret = false;
1320 float zoom = findZoomRatio(mFovControlData.zoomWide) / (float)mFovControlData.zoomRatioTable[0];
1321 float cutOverWideToTele = mFovControlData.transitionParams.cutOverWideToTele;
1322 float cutOverTeleToWide = mFovControlData.transitionParams.cutOverTeleToWide;
1323 af_status afStatusAux = mFovControlData.status3A.aux.af.status;
1324
1325 char prop[PROPERTY_VALUE_MAX];
1326 int override = 0;
1327 property_get("persist.camera.fovc.override", prop, "0");
1328 override = atoi(prop);
1329 if(override) {
1330 afStatusAux = AF_VALID;
1331 }
1332
1333 if (cam == CAM_TYPE_WIDE) {
1334 if (mFovControlData.availableSpatialAlignSolns & CAM_SPATIAL_ALIGN_OEM) {
1335 // In case of OEM Spatial alignment solution, check the spatial alignment ready
1336 if (mFovControlData.wideCamStreaming && isSpatialAlignmentReady()) {
1337 ret = true;
1338 }
1339 } else {
1340 // In case of QTI Spatial alignment solution and no spatial alignment solution,
1341 // check the fallback flag or if the zoom level has crossed the threhold.
1342 if ((mFovControlData.fallbackEnabled && mFovControlData.fallbackToWide) ||
1343 (zoom < cutOverTeleToWide)) {
1344 if (mFovControlData.wideCamStreaming) {
1345 ret = true;
1346 }
1347 }
1348 }
1349 } else if (cam == CAM_TYPE_TELE) {
1350 if (mFovControlData.fallbackEnabled && mFovControlData.fallbackToWide) {
1351 // If fallback to wide is initiated, don't switch the master to tele
1352 ret = false;
1353 } else if (mFovControlData.availableSpatialAlignSolns & CAM_SPATIAL_ALIGN_OEM) {
1354 // In case of OEM Spatial alignment solution, check the spatial alignment ready and
1355 // af status
1356 if (mFovControlData.teleCamStreaming &&
1357 isSpatialAlignmentReady() &&
1358 (afStatusAux == AF_VALID)) {
1359 ret = true;
1360 }
1361 } else if (mFovControlData.availableSpatialAlignSolns & CAM_SPATIAL_ALIGN_QTI) {
1362 // In case of QTI Spatial alignment solution check the spatial alignment ready flag,
1363 // af status and if the zoom level has crossed the threhold.
1364 if ((zoom > cutOverWideToTele) &&
1365 isSpatialAlignmentReady() &&
1366 (afStatusAux == AF_VALID)) {
1367 ret = true;
1368 }
1369 } else {
1370 // In case of no spatial alignment solution check af status and
1371 // if the zoom level has crossed the threhold.
1372 if ((zoom > cutOverWideToTele) &&
1373 (afStatusAux == AF_VALID)) {
1374 ret = true;
1375 }
1376 }
1377 } else {
1378 LOGE("Request to switch to invalid cam type");
1379 }
1380 return ret;
1381 }
1382
1383 /*===========================================================================
1384 * FUNCTION : isSpatialAlignmentReady
1385 *
1386 * DESCRIPTION : Check if the spatial alignment is ready.
1387 * For QTI solution, check ready_status flag
1388 * For OEM solution, check camMasterHint
1389 * If the spatial alignment solution is not needed, return true
1390 *
1391 * PARAMETERS : None
1392 *
1393 * RETURN :
1394 * true : If spatial alignment is ready
1395 * false : If spatial alignment is not yet ready
1396 *
1397 *==========================================================================*/
isSpatialAlignmentReady()1398 bool QCameraFOVControl::isSpatialAlignmentReady()
1399 {
1400 bool ret = true;
1401 cam_sync_type_t camWide = mFovControlData.camWide;
1402 cam_sync_type_t camTele = mFovControlData.camTele;
1403
1404 if (mFovControlData.availableSpatialAlignSolns & CAM_SPATIAL_ALIGN_OEM) {
1405 uint8_t currentMaster = (uint8_t)mFovControlResult.camMasterPreview;
1406 uint8_t camMasterHint = mFovControlData.spatialAlignResult.camMasterHint;
1407
1408 if (((currentMaster == camWide) && (camMasterHint == camTele)) ||
1409 ((currentMaster == camTele) && (camMasterHint == camWide))){
1410 ret = true;
1411 } else {
1412 ret = false;
1413 }
1414 } else if (mFovControlData.availableSpatialAlignSolns & CAM_SPATIAL_ALIGN_QTI) {
1415 if (mFovControlData.spatialAlignResult.readyStatus) {
1416 ret = true;
1417 } else {
1418 ret = false;
1419 }
1420 }
1421
1422 char prop[PROPERTY_VALUE_MAX];
1423 int override = 0;
1424 property_get("persist.camera.fovc.override", prop, "0");
1425 override = atoi(prop);
1426 if(override) {
1427 ret = true;
1428 }
1429
1430 return ret;
1431 }
1432
1433
1434 /*===========================================================================
1435 * FUNCTION : validateAndExtractParameters
1436 *
1437 * DESCRIPTION : Validates a subset of parameters from capabilities and
1438 * saves those parameters for decision making.
1439 *
1440 * PARAMETERS :
1441 * @capsMain : The capabilities for the main camera
1442 * @capsAux : The capabilities for the aux camera
1443 *
1444 * RETURN :
1445 * true : Success
1446 * false : Failure
1447 *
1448 *==========================================================================*/
validateAndExtractParameters(cam_capability_t * capsMainCam,cam_capability_t * capsAuxCam)1449 bool QCameraFOVControl::validateAndExtractParameters(
1450 cam_capability_t *capsMainCam,
1451 cam_capability_t *capsAuxCam)
1452 {
1453 bool rc = false;
1454 if (capsMainCam && capsAuxCam) {
1455
1456 mFovControlConfig.percentMarginHysterisis = 5;
1457 mFovControlConfig.percentMarginMain = 25;
1458 mFovControlConfig.percentMarginAux = 15;
1459 mFovControlConfig.waitTimeForHandoffMs = 1000;
1460
1461 mDualCamParams.paramsMain.sensorStreamWidth =
1462 capsMainCam->related_cam_calibration.main_cam_specific_calibration.\
1463 native_sensor_resolution_width;
1464 mDualCamParams.paramsMain.sensorStreamHeight =
1465 capsMainCam->related_cam_calibration.main_cam_specific_calibration.\
1466 native_sensor_resolution_height;
1467
1468 mDualCamParams.paramsAux.sensorStreamWidth =
1469 capsMainCam->related_cam_calibration.aux_cam_specific_calibration.\
1470 native_sensor_resolution_width;
1471 mDualCamParams.paramsAux.sensorStreamHeight =
1472 capsMainCam->related_cam_calibration.aux_cam_specific_calibration.\
1473 native_sensor_resolution_height;
1474
1475 mDualCamParams.paramsMain.focalLengthMm = capsMainCam->focal_length;
1476 mDualCamParams.paramsAux.focalLengthMm = capsAuxCam->focal_length;
1477
1478 mDualCamParams.paramsMain.pixelPitchUm = capsMainCam->pixel_pitch_um;
1479 mDualCamParams.paramsAux.pixelPitchUm = capsAuxCam->pixel_pitch_um;
1480
1481 if ((capsMainCam->min_focus_distance > 0) &&
1482 (capsAuxCam->min_focus_distance > 0)) {
1483 // Convert the min focus distance from diopters to cm
1484 // and choose the max of both sensors.
1485 uint32_t minFocusDistCmMain = (100.0f / capsMainCam->min_focus_distance);
1486 uint32_t minFocusDistCmAux = (100.0f / capsAuxCam->min_focus_distance);
1487 mDualCamParams.minFocusDistanceCm = (minFocusDistCmMain > minFocusDistCmAux) ?
1488 minFocusDistCmMain : minFocusDistCmAux;
1489 }
1490
1491 if (capsMainCam->related_cam_calibration.relative_position_flag == 0) {
1492 mDualCamParams.positionAux = CAM_POSITION_RIGHT;
1493 } else {
1494 mDualCamParams.positionAux = CAM_POSITION_LEFT;
1495 }
1496
1497 if ((capsMainCam->avail_spatial_align_solns & CAM_SPATIAL_ALIGN_QTI) ||
1498 (capsMainCam->avail_spatial_align_solns & CAM_SPATIAL_ALIGN_OEM)) {
1499 mFovControlData.availableSpatialAlignSolns =
1500 capsMainCam->avail_spatial_align_solns;
1501 } else {
1502 LOGW("Spatial alignment not supported");
1503 }
1504
1505 if (capsMainCam->zoom_supported > 0) {
1506 mFovControlData.zoomRatioTable = capsMainCam->zoom_ratio_tbl;
1507 mFovControlData.zoomRatioTableCount = capsMainCam->zoom_ratio_tbl_cnt;
1508 } else {
1509 LOGE("zoom feature not supported");
1510 return false;
1511 }
1512 rc = true;
1513 }
1514
1515 return rc;
1516 }
1517
1518 /*===========================================================================
1519 * FUNCTION : calculateBasicFovRatio
1520 *
1521 * DESCRIPTION: Calculate the FOV ratio between main and aux cameras
1522 *
1523 * PARAMETERS : None
1524 *
1525 * RETURN :
1526 * true : Success
1527 * false : Failure
1528 *
1529 *==========================================================================*/
calculateBasicFovRatio()1530 bool QCameraFOVControl::calculateBasicFovRatio()
1531 {
1532 float fovWide = 0.0f;
1533 float fovTele = 0.0f;
1534 bool rc = false;
1535
1536 if ((mDualCamParams.paramsMain.focalLengthMm > 0.0f) &&
1537 (mDualCamParams.paramsAux.focalLengthMm > 0.0f)) {
1538 if (mDualCamParams.paramsMain.focalLengthMm <
1539 mDualCamParams.paramsAux.focalLengthMm) {
1540 fovWide = (mDualCamParams.paramsMain.sensorStreamWidth *
1541 mDualCamParams.paramsMain.pixelPitchUm) /
1542 mDualCamParams.paramsMain.focalLengthMm;
1543
1544 fovTele = (mDualCamParams.paramsAux.sensorStreamWidth *
1545 mDualCamParams.paramsAux.pixelPitchUm) /
1546 mDualCamParams.paramsAux.focalLengthMm;
1547 } else {
1548 fovWide = (mDualCamParams.paramsAux.sensorStreamWidth *
1549 mDualCamParams.paramsAux.pixelPitchUm) /
1550 mDualCamParams.paramsAux.focalLengthMm;
1551
1552 fovTele = (mDualCamParams.paramsMain.sensorStreamWidth *
1553 mDualCamParams.paramsMain.pixelPitchUm) /
1554 mDualCamParams.paramsMain.focalLengthMm;
1555 }
1556 if (fovTele > 0.0f) {
1557 mFovControlData.basicFovRatio = (fovWide / fovTele);
1558 rc = true;
1559 }
1560 }
1561
1562 LOGD("Main cam focalLengthMm : %f", mDualCamParams.paramsMain.focalLengthMm);
1563 LOGD("Aux cam focalLengthMm : %f", mDualCamParams.paramsAux.focalLengthMm);
1564 LOGD("Main cam sensorStreamWidth : %u", mDualCamParams.paramsMain.sensorStreamWidth);
1565 LOGD("Main cam sensorStreamHeight: %u", mDualCamParams.paramsMain.sensorStreamHeight);
1566 LOGD("Main cam pixelPitchUm : %f", mDualCamParams.paramsMain.pixelPitchUm);
1567 LOGD("Main cam focalLengthMm : %f", mDualCamParams.paramsMain.focalLengthMm);
1568 LOGD("Aux cam sensorStreamWidth : %u", mDualCamParams.paramsAux.sensorStreamWidth);
1569 LOGD("Aux cam sensorStreamHeight : %u", mDualCamParams.paramsAux.sensorStreamHeight);
1570 LOGD("Aux cam pixelPitchUm : %f", mDualCamParams.paramsAux.pixelPitchUm);
1571 LOGD("Aux cam focalLengthMm : %f", mDualCamParams.paramsAux.focalLengthMm);
1572 LOGD("fov wide : %f", fovWide);
1573 LOGD("fov tele : %f", fovTele);
1574 LOGD("BasicFovRatio : %f", mFovControlData.basicFovRatio);
1575
1576 return rc;
1577 }
1578
1579
1580 /*===========================================================================
1581 * FUNCTION : combineFovAdjustment
1582 *
1583 * DESCRIPTION: Calculate the final FOV adjustment by combining basic FOV ratio
1584 * with the margin info
1585 *
1586 * PARAMETERS : None
1587 *
1588 * RETURN :
1589 * true : Success
1590 * false : Failure
1591 *
1592 *==========================================================================*/
combineFovAdjustment()1593 bool QCameraFOVControl::combineFovAdjustment()
1594 {
1595 float ratioMarginWidth;
1596 float ratioMarginHeight;
1597 float adjustedRatio;
1598 bool rc = false;
1599
1600 ratioMarginWidth = (1.0 + (mFovControlData.camMainWidthMargin)) /
1601 (1.0 + (mFovControlData.camAuxWidthMargin));
1602 ratioMarginHeight = (1.0 + (mFovControlData.camMainHeightMargin)) /
1603 (1.0 + (mFovControlData.camAuxHeightMargin));
1604
1605 adjustedRatio = (ratioMarginHeight < ratioMarginWidth) ? ratioMarginHeight : ratioMarginWidth;
1606
1607 if (adjustedRatio > 0.0f) {
1608 mFovControlData.transitionParams.cutOverFactor =
1609 (mFovControlData.basicFovRatio / adjustedRatio);
1610 rc = true;
1611 }
1612
1613 LOGD("Main cam margin for width : %f", mFovControlData.camMainWidthMargin);
1614 LOGD("Main cam margin for height : %f", mFovControlData.camMainHeightMargin);
1615 LOGD("Aux cam margin for width : %f", mFovControlData.camAuxWidthMargin);
1616 LOGD("Aux cam margin for height : %f", mFovControlData.camAuxHeightMargin);
1617 LOGD("Width margin ratio : %f", ratioMarginWidth);
1618 LOGD("Height margin ratio : %f", ratioMarginHeight);
1619
1620 return rc;
1621 }
1622
1623
1624 /*===========================================================================
1625 * FUNCTION : calculateDualCamTransitionParams
1626 *
1627 * DESCRIPTION: Calculate the transition parameters needed to switch the camera
1628 * between main and aux
1629 *
1630 * PARAMETERS :
1631 * @fovAdjustBasic : basic FOV ratio
1632 * @zoomTranslationFactor: translation factor for main, aux zoom
1633 *
1634 * RETURN : none
1635 *
1636 *==========================================================================*/
calculateDualCamTransitionParams()1637 void QCameraFOVControl::calculateDualCamTransitionParams()
1638 {
1639 float percentMarginWide;
1640 float percentMarginTele;
1641
1642 if (isMainCamFovWider()) {
1643 percentMarginWide = mFovControlConfig.percentMarginMain;
1644 percentMarginTele = mFovControlConfig.percentMarginAux;
1645 } else {
1646 percentMarginWide = mFovControlConfig.percentMarginAux;
1647 percentMarginTele = mFovControlConfig.percentMarginMain;
1648 }
1649
1650 mFovControlData.transitionParams.cropRatio = mFovControlData.basicFovRatio;
1651
1652 mFovControlData.transitionParams.cutOverWideToTele =
1653 mFovControlData.transitionParams.cutOverFactor +
1654 (mFovControlConfig.percentMarginHysterisis / 100.0) * mFovControlData.basicFovRatio;
1655
1656 mFovControlData.transitionParams.cutOverTeleToWide =
1657 mFovControlData.transitionParams.cutOverFactor;
1658
1659 mFovControlData.transitionParams.transitionHigh =
1660 mFovControlData.transitionParams.cutOverWideToTele +
1661 (percentMarginWide / 100.0) * mFovControlData.basicFovRatio;
1662
1663 mFovControlData.transitionParams.transitionLow =
1664 mFovControlData.transitionParams.cutOverTeleToWide -
1665 (percentMarginTele / 100.0) * mFovControlData.basicFovRatio;
1666
1667 if (mFovControlConfig.snapshotPPConfig.enablePostProcess) {
1668 // Expand the transition zone if necessary to account for
1669 // the snapshot post-process settings
1670 if (mFovControlConfig.snapshotPPConfig.zoomMax >
1671 mFovControlData.transitionParams.transitionHigh) {
1672 mFovControlData.transitionParams.transitionHigh =
1673 mFovControlConfig.snapshotPPConfig.zoomMax;
1674 }
1675 if (mFovControlConfig.snapshotPPConfig.zoomMin <
1676 mFovControlData.transitionParams.transitionLow) {
1677 mFovControlData.transitionParams.transitionLow =
1678 mFovControlConfig.snapshotPPConfig.zoomMin;
1679 }
1680
1681 // Set aux switch brightness threshold as the lower of aux switch and
1682 // snapshot post-process thresholds
1683 if (mFovControlConfig.snapshotPPConfig.luxMin < mFovControlConfig.auxSwitchBrightnessMin) {
1684 mFovControlConfig.auxSwitchBrightnessMin = mFovControlConfig.snapshotPPConfig.luxMin;
1685 }
1686 }
1687
1688 LOGD("transition param: TransitionLow %f", mFovControlData.transitionParams.transitionLow);
1689 LOGD("transition param: TeleToWide %f", mFovControlData.transitionParams.cutOverTeleToWide);
1690 LOGD("transition param: WideToTele %f", mFovControlData.transitionParams.cutOverWideToTele);
1691 LOGD("transition param: TransitionHigh %f", mFovControlData.transitionParams.transitionHigh);
1692 }
1693
1694
1695 /*===========================================================================
1696 * FUNCTION : findZoomValue
1697 *
1698 * DESCRIPTION: For the input zoom ratio, find the zoom value.
1699 * Zoom table contains zoom ratios where the indices
1700 * in the zoom table indicate the corresponding zoom values.
1701 * PARAMETERS :
1702 * @zoomRatio : Zoom ratio
1703 *
1704 * RETURN : Zoom value
1705 *
1706 *==========================================================================*/
findZoomValue(uint32_t zoomRatio)1707 uint32_t QCameraFOVControl::findZoomValue(
1708 uint32_t zoomRatio)
1709 {
1710 uint32_t zoom = 0;
1711 for (uint32_t i = 0; i < mFovControlData.zoomRatioTableCount; ++i) {
1712 if (zoomRatio <= mFovControlData.zoomRatioTable[i]) {
1713 zoom = i;
1714 break;
1715 }
1716 }
1717 return zoom;
1718 }
1719
1720
1721 /*===========================================================================
1722 * FUNCTION : findZoomRatio
1723 *
1724 * DESCRIPTION: For the input zoom value, find the zoom ratio.
1725 * Zoom table contains zoom ratios where the indices
1726 * in the zoom table indicate the corresponding zoom values.
1727 * PARAMETERS :
1728 * @zoom : zoom value
1729 *
1730 * RETURN : zoom ratio
1731 *
1732 *==========================================================================*/
findZoomRatio(uint32_t zoom)1733 uint32_t QCameraFOVControl::findZoomRatio(
1734 uint32_t zoom)
1735 {
1736 return mFovControlData.zoomRatioTable[zoom];
1737 }
1738
1739
1740 /*===========================================================================
1741 * FUNCTION : readjustZoomForTele
1742 *
1743 * DESCRIPTION: Calculate the zoom value for the tele camera based on zoom value
1744 * for the wide camera
1745 *
1746 * PARAMETERS :
1747 * @zoomWide : Zoom value for wide camera
1748 *
1749 * RETURN : Zoom value for tele camera
1750 *
1751 *==========================================================================*/
readjustZoomForTele(uint32_t zoomWide)1752 uint32_t QCameraFOVControl::readjustZoomForTele(
1753 uint32_t zoomWide)
1754 {
1755 uint32_t zoomRatioWide;
1756 uint32_t zoomRatioTele;
1757
1758 zoomRatioWide = findZoomRatio(zoomWide);
1759 zoomRatioTele = zoomRatioWide / mFovControlData.transitionParams.cutOverFactor;
1760
1761 return(findZoomValue(zoomRatioTele));
1762 }
1763
1764
1765 /*===========================================================================
1766 * FUNCTION : readjustZoomForWide
1767 *
1768 * DESCRIPTION: Calculate the zoom value for the wide camera based on zoom value
1769 * for the tele camera
1770 *
1771 * PARAMETERS :
1772 * @zoomTele : Zoom value for tele camera
1773 *
1774 * RETURN : Zoom value for wide camera
1775 *
1776 *==========================================================================*/
readjustZoomForWide(uint32_t zoomTele)1777 uint32_t QCameraFOVControl::readjustZoomForWide(
1778 uint32_t zoomTele)
1779 {
1780 uint32_t zoomRatioWide;
1781 uint32_t zoomRatioTele;
1782
1783 zoomRatioTele = findZoomRatio(zoomTele);
1784 zoomRatioWide = zoomRatioTele * mFovControlData.transitionParams.cutOverFactor;
1785
1786 return(findZoomValue(zoomRatioWide));
1787 }
1788
1789
1790 /*===========================================================================
1791 * FUNCTION : convertUserZoomToWideAndTele
1792 *
1793 * DESCRIPTION: Calculate the zoom value for the wide and tele cameras
1794 * based on the input user zoom value
1795 *
1796 * PARAMETERS :
1797 * @zoom : User zoom value
1798 *
1799 * RETURN : none
1800 *
1801 *==========================================================================*/
convertUserZoomToWideAndTele(uint32_t zoom)1802 void QCameraFOVControl::convertUserZoomToWideAndTele(
1803 uint32_t zoom)
1804 {
1805 Mutex::Autolock lock(mMutex);
1806
1807 // If the zoom translation library is present and initialized,
1808 // use it to get wide and tele zoom values
1809 if (mZoomTranslator && mZoomTranslator->isInitialized()) {
1810 uint32_t zoomWide = 0;
1811 uint32_t zoomTele = 0;
1812 if (mZoomTranslator->getZoomValues(zoom, &zoomWide, &zoomTele) != NO_ERROR) {
1813 LOGE("getZoomValues failed from zoom translation lib");
1814 // Use zoom translation logic from FOV-control
1815 mFovControlData.zoomWide = zoom;
1816 mFovControlData.zoomTele = readjustZoomForTele(mFovControlData.zoomWide);
1817 } else {
1818 // Use the zoom values provided by zoom translation lib
1819 mFovControlData.zoomWide = zoomWide;
1820 mFovControlData.zoomTele = zoomTele;
1821 }
1822 } else {
1823 mFovControlData.zoomWide = zoom;
1824 mFovControlData.zoomTele = readjustZoomForTele(mFovControlData.zoomWide);
1825 }
1826 }
1827
1828
1829 /*===========================================================================
1830 * FUNCTION : translateFocusAreas
1831 *
1832 * DESCRIPTION: Translate the focus areas from main to aux camera.
1833 *
1834 * PARAMETERS :
1835 * @roiAfMain : Focus area ROI for main camera
1836 * @cam : Cam type
1837 *
1838 * RETURN : Translated focus area ROI for aux camera
1839 *
1840 *==========================================================================*/
translateFocusAreas(cam_roi_info_t roiAfMain,cam_sync_type_t cam)1841 cam_roi_info_t QCameraFOVControl::translateFocusAreas(
1842 cam_roi_info_t roiAfMain,
1843 cam_sync_type_t cam)
1844 {
1845 float fovRatio;
1846 float zoomWide;
1847 float zoomTele;
1848 float AuxDiffRoiLeft;
1849 float AuxDiffRoiTop;
1850 float AuxRoiLeft;
1851 float AuxRoiTop;
1852 cam_roi_info_t roiAfTrans = roiAfMain;
1853 int32_t shiftHorzAdjusted;
1854 int32_t shiftVertAdjusted;
1855 float zoom = findZoomRatio(mFovControlData.zoomWide) / (float)mFovControlData.zoomRatioTable[0];
1856
1857 zoomWide = findZoomRatio(mFovControlData.zoomWide);
1858 zoomTele = findZoomRatio(mFovControlData.zoomTele);
1859
1860 if (cam == mFovControlData.camWide) {
1861 fovRatio = 1.0f;
1862 } else {
1863 fovRatio = (zoomTele / zoomWide) * mFovControlData.transitionParams.cropRatio;
1864 }
1865
1866 // Acquire the mutex in order to read the spatial alignment result which is written
1867 // by another thread
1868 mMutex.lock();
1869 if (cam == mFovControlData.camWide) {
1870 shiftHorzAdjusted = mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftHorz;
1871 shiftVertAdjusted = mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftVert;
1872 } else {
1873 shiftHorzAdjusted = (mFovControlData.transitionParams.cropRatio / zoom) *
1874 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftHorz;
1875 shiftVertAdjusted = (mFovControlData.transitionParams.cropRatio / zoom) *
1876 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftVert;
1877 }
1878 mMutex.unlock();
1879
1880 for (int i = 0; i < roiAfMain.num_roi; ++i) {
1881 roiAfTrans.roi[i].width = roiAfMain.roi[i].width * fovRatio;
1882 roiAfTrans.roi[i].height = roiAfMain.roi[i].height * fovRatio;
1883
1884 AuxDiffRoiLeft = (roiAfTrans.roi[i].width - roiAfMain.roi[i].width) / 2.0f;
1885 AuxRoiLeft = roiAfMain.roi[i].left - AuxDiffRoiLeft;
1886 AuxDiffRoiTop = (roiAfTrans.roi[i].height - roiAfMain.roi[i].height) / 2.0f;
1887 AuxRoiTop = roiAfMain.roi[i].top - AuxDiffRoiTop;
1888
1889 roiAfTrans.roi[i].left = AuxRoiLeft - shiftHorzAdjusted;
1890 roiAfTrans.roi[i].top = AuxRoiTop - shiftVertAdjusted;
1891
1892 // Check the ROI bounds and correct if necessory
1893 // If ROI is out of bounds, revert to default ROI
1894 if ((roiAfTrans.roi[i].left >= mFovControlData.previewSize.width) ||
1895 (roiAfTrans.roi[i].top >= mFovControlData.previewSize.height) ||
1896 (roiAfTrans.roi[i].width >= mFovControlData.previewSize.width) ||
1897 (roiAfTrans.roi[i].height >= mFovControlData.previewSize.height)) {
1898 // TODO : use default ROI when available from AF. This part of the code
1899 // is still being worked upon. WA - set it to main cam ROI
1900 roiAfTrans = roiAfMain;
1901 LOGW("AF ROI translation failed, reverting to the default ROI");
1902 } else {
1903 if (roiAfTrans.roi[i].left < 0) {
1904 roiAfTrans.roi[i].left = 0;
1905 LOGW("AF ROI translation failed");
1906 }
1907 if (roiAfTrans.roi[i].top < 0) {
1908 roiAfTrans.roi[i].top = 0;
1909 LOGW("AF ROI translation failed");
1910 }
1911 if ((roiAfTrans.roi[i].left + roiAfTrans.roi[i].width) >=
1912 mFovControlData.previewSize.width) {
1913 roiAfTrans.roi[i].width =
1914 mFovControlData.previewSize.width - roiAfTrans.roi[i].left;
1915 LOGW("AF ROI translation failed");
1916 }
1917 if ((roiAfTrans.roi[i].top + roiAfTrans.roi[i].height) >=
1918 mFovControlData.previewSize.height) {
1919 roiAfTrans.roi[i].height =
1920 mFovControlData.previewSize.height - roiAfTrans.roi[i].top;
1921 LOGW("AF ROI translation failed");
1922 }
1923 }
1924
1925 LOGD("Translated AF ROI-%d %s: L:%d, T:%d, W:%d, H:%d", i,
1926 (cam == CAM_TYPE_MAIN) ? "main cam" : "aux cam", roiAfTrans.roi[i].left,
1927 roiAfTrans.roi[i].top, roiAfTrans.roi[i].width, roiAfTrans.roi[i].height);
1928 }
1929 return roiAfTrans;
1930 }
1931
1932
1933 /*===========================================================================
1934 * FUNCTION : translateMeteringAreas
1935 *
1936 * DESCRIPTION: Translate the AEC metering areas from main to aux camera.
1937 *
1938 * PARAMETERS :
1939 * @roiAfMain : AEC ROI for main camera
1940 * @cam : Cam type
1941 *
1942 * RETURN : Translated AEC ROI for aux camera
1943 *
1944 *==========================================================================*/
translateMeteringAreas(cam_set_aec_roi_t roiAecMain,cam_sync_type_t cam)1945 cam_set_aec_roi_t QCameraFOVControl::translateMeteringAreas(
1946 cam_set_aec_roi_t roiAecMain,
1947 cam_sync_type_t cam)
1948 {
1949 float fovRatio;
1950 float zoomWide;
1951 float zoomTele;
1952 float AuxDiffRoiX;
1953 float AuxDiffRoiY;
1954 float AuxRoiX;
1955 float AuxRoiY;
1956 cam_set_aec_roi_t roiAecTrans = roiAecMain;
1957 int32_t shiftHorzAdjusted;
1958 int32_t shiftVertAdjusted;
1959 float zoom = findZoomRatio(mFovControlData.zoomWide) / (float)mFovControlData.zoomRatioTable[0];
1960
1961 zoomWide = findZoomRatio(mFovControlData.zoomWide);
1962 zoomTele = findZoomRatio(mFovControlData.zoomTele);
1963
1964 if (cam == mFovControlData.camWide) {
1965 fovRatio = 1.0f;
1966 } else {
1967 fovRatio = (zoomTele / zoomWide) * mFovControlData.transitionParams.cropRatio;
1968 }
1969
1970 // Acquire the mutex in order to read the spatial alignment result which is written
1971 // by another thread
1972 mMutex.lock();
1973 if (cam == mFovControlData.camWide) {
1974 shiftHorzAdjusted = mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftHorz;
1975 shiftVertAdjusted = mFovControlData.spatialAlignResult.shiftAfRoiWide.shiftVert;
1976 } else {
1977 shiftHorzAdjusted = (mFovControlData.transitionParams.cropRatio / zoom) *
1978 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftHorz;
1979 shiftVertAdjusted = (mFovControlData.transitionParams.cropRatio / zoom) *
1980 mFovControlData.spatialAlignResult.shiftAfRoiTele.shiftVert;
1981 }
1982 mMutex.unlock();
1983
1984 for (int i = 0; i < roiAecMain.num_roi; ++i) {
1985 AuxDiffRoiX = fovRatio * ((float)roiAecMain.cam_aec_roi_position.coordinate[i].x -
1986 (mFovControlData.previewSize.width / 2));
1987 AuxRoiX = (mFovControlData.previewSize.width / 2) + AuxDiffRoiX;
1988
1989 AuxDiffRoiY = fovRatio * ((float)roiAecMain.cam_aec_roi_position.coordinate[i].y -
1990 (mFovControlData.previewSize.height / 2));
1991 AuxRoiY = (mFovControlData.previewSize.height / 2) + AuxDiffRoiY;
1992
1993 roiAecTrans.cam_aec_roi_position.coordinate[i].x = AuxRoiX - shiftHorzAdjusted;
1994 roiAecTrans.cam_aec_roi_position.coordinate[i].y = AuxRoiY - shiftVertAdjusted;
1995
1996 // Check the ROI bounds and correct if necessory
1997 if ((AuxRoiX < 0) ||
1998 (AuxRoiY < 0)) {
1999 roiAecTrans.cam_aec_roi_position.coordinate[i].x = 0;
2000 roiAecTrans.cam_aec_roi_position.coordinate[i].y = 0;
2001 LOGW("AEC ROI translation failed");
2002 } else if ((AuxRoiX >= mFovControlData.previewSize.width) ||
2003 (AuxRoiY >= mFovControlData.previewSize.height)) {
2004 // Clamp the Aux AEC ROI co-ordinates to max possible value
2005 if (AuxRoiX >= mFovControlData.previewSize.width) {
2006 roiAecTrans.cam_aec_roi_position.coordinate[i].x =
2007 mFovControlData.previewSize.width - 1;
2008 }
2009 if (AuxRoiY >= mFovControlData.previewSize.height) {
2010 roiAecTrans.cam_aec_roi_position.coordinate[i].y =
2011 mFovControlData.previewSize.height - 1;
2012 }
2013 LOGW("AEC ROI translation failed");
2014 }
2015
2016 LOGD("Translated AEC ROI-%d %s: x:%d, y:%d", i,
2017 (cam == CAM_TYPE_MAIN) ? "main cam" : "aux cam",
2018 roiAecTrans.cam_aec_roi_position.coordinate[i].x,
2019 roiAecTrans.cam_aec_roi_position.coordinate[i].y);
2020 }
2021 return roiAecTrans;
2022 }
2023
2024
2025 /*===========================================================================
2026 * FUNCTION : translateRoiFD
2027 *
2028 * DESCRIPTION: Translate face detection ROI from aux metadata to main
2029 *
2030 * PARAMETERS :
2031 * @faceDetectionInfo : face detection data from aux metadata. This face
2032 * detection data is overwritten with the translated
2033 * FD ROI.
2034 * @cam : Cam type
2035 *
2036 * RETURN : none
2037 *
2038 *==========================================================================*/
translateRoiFD(cam_face_detection_data_t metaFD,cam_sync_type_t cam)2039 cam_face_detection_data_t QCameraFOVControl::translateRoiFD(
2040 cam_face_detection_data_t metaFD,
2041 cam_sync_type_t cam)
2042 {
2043 cam_face_detection_data_t metaFDTranslated = metaFD;
2044 int32_t shiftHorz = 0;
2045 int32_t shiftVert = 0;
2046
2047 if (cam == mFovControlData.camWide) {
2048 shiftHorz = mFovControlData.spatialAlignResult.shiftWide.shiftHorz;
2049 shiftVert = mFovControlData.spatialAlignResult.shiftWide.shiftVert;
2050 } else {
2051 shiftHorz = mFovControlData.spatialAlignResult.shiftTele.shiftHorz;
2052 shiftVert = mFovControlData.spatialAlignResult.shiftTele.shiftVert;
2053 }
2054
2055 for (int i = 0; i < metaFDTranslated.num_faces_detected; ++i) {
2056 metaFDTranslated.faces[i].face_boundary.left += shiftHorz;
2057 metaFDTranslated.faces[i].face_boundary.top += shiftVert;
2058 }
2059
2060 // If ROI is out of bounds, remove that FD ROI from the list
2061 for (int i = 0; i < metaFDTranslated.num_faces_detected; ++i) {
2062 if ((metaFDTranslated.faces[i].face_boundary.left < 0) ||
2063 (metaFDTranslated.faces[i].face_boundary.left >= mFovControlData.previewSize.width) ||
2064 (metaFDTranslated.faces[i].face_boundary.top < 0) ||
2065 (metaFDTranslated.faces[i].face_boundary.top >= mFovControlData.previewSize.height) ||
2066 ((metaFDTranslated.faces[i].face_boundary.left +
2067 metaFDTranslated.faces[i].face_boundary.width) >=
2068 mFovControlData.previewSize.width) ||
2069 ((metaFDTranslated.faces[i].face_boundary.top +
2070 metaFDTranslated.faces[i].face_boundary.height) >=
2071 mFovControlData.previewSize.height)) {
2072 // Invalid FD ROI detected
2073 LOGD("Failed translating FD ROI %s: L:%d, T:%d, W:%d, H:%d",
2074 (cam == CAM_TYPE_MAIN) ? "main cam" : "aux cam",
2075 metaFDTranslated.faces[i].face_boundary.left,
2076 metaFDTranslated.faces[i].face_boundary.top,
2077 metaFDTranslated.faces[i].face_boundary.width,
2078 metaFDTranslated.faces[i].face_boundary.height);
2079
2080 // Remove it by copying the last FD ROI at this index
2081 if (i < (metaFDTranslated.num_faces_detected - 1)) {
2082 metaFDTranslated.faces[i] =
2083 metaFDTranslated.faces[metaFDTranslated.num_faces_detected - 1];
2084 // Decrement the current index to process the newly copied FD ROI.
2085 --i;
2086 }
2087 --metaFDTranslated.num_faces_detected;
2088 }
2089 else {
2090 LOGD("Translated FD ROI-%d %s: L:%d, T:%d, W:%d, H:%d", i,
2091 (cam == CAM_TYPE_MAIN) ? "main cam" : "aux cam",
2092 metaFDTranslated.faces[i].face_boundary.left,
2093 metaFDTranslated.faces[i].face_boundary.top,
2094 metaFDTranslated.faces[i].face_boundary.width,
2095 metaFDTranslated.faces[i].face_boundary.height);
2096 }
2097 }
2098 return metaFDTranslated;
2099 }
2100
2101
2102 /*===========================================================================
2103 * FUNCTION : getFrameMargins
2104 *
2105 * DESCRIPTION : Return frame margin data for the requested camera
2106 *
2107 * PARAMETERS :
2108 * @masterCamera : Master camera id
2109 *
2110 * RETURN : Frame margins
2111 *
2112 *==========================================================================*/
getFrameMargins(int8_t masterCamera)2113 cam_frame_margins_t QCameraFOVControl::getFrameMargins(
2114 int8_t masterCamera)
2115 {
2116 cam_frame_margins_t frameMargins;
2117 memset(&frameMargins, 0, sizeof(cam_frame_margins_t));
2118
2119 if (masterCamera == CAM_TYPE_MAIN) {
2120 frameMargins.widthMargins = mFovControlData.camMainWidthMargin;
2121 frameMargins.heightMargins = mFovControlData.camMainHeightMargin;
2122 } else if (masterCamera == CAM_TYPE_AUX) {
2123 frameMargins.widthMargins = mFovControlData.camAuxWidthMargin;
2124 frameMargins.heightMargins = mFovControlData.camAuxHeightMargin;
2125 }
2126
2127 return frameMargins;
2128 }
2129 }; // namespace qcamera
2130