10a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin/* 20a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Copyright (C) 2014 The Android Open Source Project 30a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 40a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 50a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * you may not use this file except in compliance with the License. 60a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * You may obtain a copy of the License at 70a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 80a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 90a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 100a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Unless required by applicable law or agreed to in writing, software 110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 120a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * See the License for the specific language governing permissions and 140a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * limitations under the License. 150a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 160a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 170a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinpackage android.hardware.camera2.legacy; 180a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 190a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.graphics.Rect; 200a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.Camera; 210a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.Camera.FaceDetectionListener; 220a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.impl.CameraMetadataNative; 230a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.legacy.ParameterUtils.ZoomData; 240a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.CameraCharacteristics; 250a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.CaptureRequest; 260a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.CaptureResult; 270a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.params.Face; 280a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.utils.ListUtils; 290a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.utils.ParamsUtils; 300a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.util.Log; 310a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.util.Size; 320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport com.android.internal.util.ArrayUtils; 340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport java.util.ArrayList; 360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport java.util.Arrays; 370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport java.util.List; 380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 390a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport static android.hardware.camera2.CaptureRequest.*; 400a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport static com.android.internal.util.Preconditions.*; 410a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 420a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin/** 430a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Map legacy face detect callbacks into face detection results. 440a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 450a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin@SuppressWarnings("deprecation") 460a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinpublic class LegacyFaceDetectMapper { 470a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private static String TAG = "LegacyFaceDetectMapper"; 480a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 490a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private final Camera mCamera; 518c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin /** Is the camera capable of face detection? */ 520a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private final boolean mFaceDetectSupported; 538c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin /** Is the camera is running face detection? */ 540a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private boolean mFaceDetectEnabled = false; 558c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin /** Did the last request say to use SCENE_MODE = FACE_PRIORITY? */ 568c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin private boolean mFaceDetectScenePriority = false; 578c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin /** Did the last request enable the face detect mode to ON? */ 588c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin private boolean mFaceDetectReporting = false; 590a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 608c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin /** Synchronize access to all fields */ 610a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private final Object mLock = new Object(); 620a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private Camera.Face[] mFaces; 630a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private Camera.Face[] mFacesPrev; 640a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin /** 650a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Instantiate a new face detect mapper. 660a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 670a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * @param camera a non-{@code null} camera1 device 680a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * @param characteristics a non-{@code null} camera characteristics for that camera1 690a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 700a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * @throws NullPointerException if any of the args were {@code null} 710a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 720a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin public LegacyFaceDetectMapper(Camera camera, CameraCharacteristics characteristics) { 730a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mCamera = checkNotNull(camera, "camera must not be null"); 740a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin checkNotNull(characteristics, "characteristics must not be null"); 750a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 760a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFaceDetectSupported = ArrayUtils.contains( 770a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin characteristics.get( 780a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES), 790a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin STATISTICS_FACE_DETECT_MODE_SIMPLE); 800a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 810a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (!mFaceDetectSupported) { 820a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin return; 830a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 840a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 850a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mCamera.setFaceDetectionListener(new FaceDetectionListener() { 860a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 870a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin @Override 880a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin public void onFaceDetection(Camera.Face[] faces, Camera camera) { 890a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin int lengthFaces = faces == null ? 0 : faces.length; 900a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin synchronized (mLock) { 910a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (mFaceDetectEnabled) { 920a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFaces = faces; 930a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } else if (lengthFaces > 0) { 940a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // stopFaceDetectMode could race against the requests, print a debug log 950a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.d(TAG, 960a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin "onFaceDetection - Ignored some incoming faces since" + 970a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin "face detection was disabled"); 980a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 990a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1000a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1010a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (VERBOSE) { 1020a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.v(TAG, "onFaceDetection - read " + lengthFaces + " faces"); 1030a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1040a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1050a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin }); 1060a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1070a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1080a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin /** 1090a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Process the face detect mode from the capture request into an api1 face detect toggle. 1100a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 1110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * <p>This method should be called after the parameters are {@link LegacyRequestMapper mapped} 1120a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * with the request.</p> 1130a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 1140a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * <p>Callbacks are processed in the background, and the next call to {@link #mapResultTriggers} 1150a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * will have the latest faces detected as reflected by the camera1 callbacks.</p> 1160a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 1170a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * <p>None of the arguments will be mutated.</p> 1180a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 1190a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * @param captureRequest a non-{@code null} request 1200a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * @param parameters a non-{@code null} parameters corresponding to this request (read-only) 1210a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 1220a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin public void processFaceDetectMode(CaptureRequest captureRequest, 1230a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Camera.Parameters parameters) { 1240a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin checkNotNull(captureRequest, "captureRequest must not be null"); 1250a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1260a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin /* 1270a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * statistics.faceDetectMode 1280a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 1290a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin int fdMode = ParamsUtils.getOrDefault(captureRequest, STATISTICS_FACE_DETECT_MODE, 1300a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin STATISTICS_FACE_DETECT_MODE_OFF); 1310a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (fdMode != STATISTICS_FACE_DETECT_MODE_OFF && !mFaceDetectSupported) { 1330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.w(TAG, 1340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin "processFaceDetectMode - Ignoring statistics.faceDetectMode; " + 1350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin "face detection is not available"); 1360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin return; 1370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1398c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin /* 1408c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * control.sceneMode 1418c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin */ 1428c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin int sceneMode = ParamsUtils.getOrDefault(captureRequest, CONTROL_SCENE_MODE, 1438c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin CONTROL_SCENE_MODE_DISABLED); 1448c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin if (sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY && !mFaceDetectSupported) { 1458c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin Log.w(TAG, "processFaceDetectMode - ignoring control.sceneMode == FACE_PRIORITY; " + 1468c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin "face detection is not available"); 1478c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin return; 1488c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin } 1498c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin 1500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // Print some warnings out in case the values were wrong 1510a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin switch (fdMode) { 1520a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin case STATISTICS_FACE_DETECT_MODE_OFF: 1530a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin case STATISTICS_FACE_DETECT_MODE_SIMPLE: 1540a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin break; 1550a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin case STATISTICS_FACE_DETECT_MODE_FULL: 1560a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.w(TAG, 1570a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin "processFaceDetectMode - statistics.faceDetectMode == FULL unsupported, " + 1580a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin "downgrading to SIMPLE"); 1590a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin break; 1600a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin default: 1610a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.w(TAG, "processFaceDetectMode - ignoring unknown statistics.faceDetectMode = " 1620a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin + fdMode); 1630a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin return; 1640a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1650a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1668c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin boolean enableFaceDetect = (fdMode != STATISTICS_FACE_DETECT_MODE_OFF) 1678c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin || (sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY); 1680a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin synchronized (mLock) { 1690a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // Enable/disable face detection if it's changed since last time 1700a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (enableFaceDetect != mFaceDetectEnabled) { 1710a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (enableFaceDetect) { 1720a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mCamera.startFaceDetection(); 1730a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1740a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (VERBOSE) { 1750a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.v(TAG, "processFaceDetectMode - start face detection"); 1760a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1770a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } else { 1780a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mCamera.stopFaceDetection(); 1790a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1800a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (VERBOSE) { 1810a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.v(TAG, "processFaceDetectMode - stop face detection"); 1820a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1830a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1840a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFaces = null; 1850a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1860a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1870a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFaceDetectEnabled = enableFaceDetect; 1888c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin mFaceDetectScenePriority = sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY; 1898c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin mFaceDetectReporting = fdMode != STATISTICS_FACE_DETECT_MODE_OFF; 1900a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1910a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1920a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 1930a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 1940a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin /** 1950a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Update the {@code result} camera metadata map with the new value for the 1960a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * {@code statistics.faces} and {@code statistics.faceDetectMode}. 1970a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 1980a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * <p>Face detect callbacks are processed in the background, and each call to 1990a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * {@link #mapResultFaces} will have the latest faces as reflected by the camera1 callbacks.</p> 2000a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * 2018c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * <p>If the scene mode was set to {@code FACE_PRIORITY} but face detection is disabled, 2028c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * the camera will still run face detection in the background, but no faces will be reported 2038c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * in the capture result.</p> 2048c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * 2050a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * @param result a non-{@code null} result 2060a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * @param legacyRequest a non-{@code null} request (read-only) 2070a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 2080a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin public void mapResultFaces(CameraMetadataNative result, LegacyRequest legacyRequest) { 2090a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin checkNotNull(result, "result must not be null"); 2100a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin checkNotNull(legacyRequest, "legacyRequest must not be null"); 2110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2120a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Camera.Face[] faces, previousFaces; 2130a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin int fdMode; 2148c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin boolean fdScenePriority; 2150a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin synchronized (mLock) { 2168c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin fdMode = mFaceDetectReporting ? 2170a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin STATISTICS_FACE_DETECT_MODE_SIMPLE : STATISTICS_FACE_DETECT_MODE_OFF; 2180a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2198c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin if (mFaceDetectReporting) { 2200a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin faces = mFaces; 2210a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } else { 2220a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin faces = null; 2230a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 2240a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2258c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin fdScenePriority = mFaceDetectScenePriority; 2268c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin 2270a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin previousFaces = mFacesPrev; 2280a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFacesPrev = faces; 2290a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 2300a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2310a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin CameraCharacteristics characteristics = legacyRequest.characteristics; 2320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin CaptureRequest request = legacyRequest.captureRequest; 2330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Size previewSize = legacyRequest.previewSize; 2340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Camera.Parameters params = legacyRequest.parameters; 2350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Rect activeArray = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 2370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin ZoomData zoomData = ParameterUtils.convertScalerCropRegion(activeArray, 2380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin request.get(CaptureRequest.SCALER_CROP_REGION), previewSize, params); 2390a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2400a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin List<Face> convertedFaces = new ArrayList<>(); 2410a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (faces != null) { 2420a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin for (Camera.Face face : faces) { 2430a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (face != null) { 2440a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin convertedFaces.add( 2450a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin ParameterUtils.convertFaceFromLegacy(face, activeArray, zoomData)); 2460a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } else { 2470a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.w(TAG, "mapResultFaces - read NULL face from camera1 device"); 2480a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 2490a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 2500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 2510a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2520a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (VERBOSE && previousFaces != faces) { // Log only in verbose and IF the faces changed 2530a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.v(TAG, "mapResultFaces - changed to " + ListUtils.listToString(convertedFaces)); 2540a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 2550a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 2560a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin result.set(CaptureResult.STATISTICS_FACES, convertedFaces.toArray(new Face[0])); 2570a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin result.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, fdMode); 2588c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin 2598c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin // Override scene mode with FACE_PRIORITY if the request was using FACE_PRIORITY 2608c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin if (fdScenePriority) { 2618c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin result.set(CaptureResult.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_FACE_PRIORITY); 2628c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin } 2630a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 2640a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin} 265