Home | History | Annotate | Download | only in v2
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.one.v2;
     18 
     19 import android.graphics.PointF;
     20 import android.graphics.Rect;
     21 import android.hardware.camera2.CameraCharacteristics;
     22 import android.hardware.camera2.CaptureResult;
     23 import android.hardware.camera2.params.MeteringRectangle;
     24 
     25 import com.android.camera.debug.Log;
     26 import com.android.camera.one.OneCamera;
     27 import com.android.camera.one.Settings3A;
     28 import com.android.camera.util.CameraUtil;
     29 
     30 /**
     31  * Helper class to implement auto focus and 3A in camera2-based
     32  * {@link com.android.camera.one.OneCamera} implementations.
     33  */
     34 public class AutoFocusHelper {
     35     private static final Log.Tag TAG = new Log.Tag("OneCameraAFHelp");
     36 
     37     /** camera2 API metering region weight. */
     38     private static final int CAMERA2_REGION_WEIGHT = (int)
     39         (CameraUtil.lerp(MeteringRectangle.METERING_WEIGHT_MIN, MeteringRectangle.METERING_WEIGHT_MAX,
     40                         Settings3A.getMeteringRegionWeight()));
     41 
     42     /** Zero weight 3A region, to reset regions per API. */
     43     private static final MeteringRectangle[] ZERO_WEIGHT_3A_REGION = new MeteringRectangle[]{
     44             new MeteringRectangle(0, 0, 0, 0, 0)
     45     };
     46 
     47     public static MeteringRectangle[] getZeroWeightRegion() {
     48         return ZERO_WEIGHT_3A_REGION;
     49     }
     50 
     51     /**
     52      * Convert reported camera2 AF state to OneCamera AutoFocusState.
     53      */
     54     public static OneCamera.AutoFocusState stateFromCamera2State(int state) {
     55         switch (state) {
     56             case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
     57                 return OneCamera.AutoFocusState.ACTIVE_SCAN;
     58             case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
     59                 return OneCamera.AutoFocusState.PASSIVE_SCAN;
     60             case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
     61                 return OneCamera.AutoFocusState.PASSIVE_FOCUSED;
     62             case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
     63                 return OneCamera.AutoFocusState.ACTIVE_FOCUSED;
     64             case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
     65                 return OneCamera.AutoFocusState.PASSIVE_UNFOCUSED;
     66             case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
     67                 return OneCamera.AutoFocusState.ACTIVE_UNFOCUSED;
     68             default:
     69                 return OneCamera.AutoFocusState.INACTIVE;
     70         }
     71     }
     72 
     73     /**
     74      * Complain if CONTROL_AF_STATE is not present in result.
     75      * Could indicate bug in API implementation.
     76      */
     77     public static boolean checkControlAfState(CaptureResult result) {
     78         boolean missing = result.get(CaptureResult.CONTROL_AF_STATE) == null;
     79         if (missing) {
     80             // throw new IllegalStateException("CaptureResult missing CONTROL_AF_STATE.");
     81             Log.e(TAG, "\n!!!! TotalCaptureResult missing CONTROL_AF_STATE. !!!!\n ");
     82         }
     83         return !missing;
     84     }
     85 
     86     /**
     87      * Complain if LENS_STATE is not present in result.
     88      * Could indicate bug in API implementation.
     89      */
     90     public static boolean checkLensState(CaptureResult result) {
     91         boolean missing = result.get(CaptureResult.LENS_STATE) == null;
     92         if (missing) {
     93             // throw new IllegalStateException("CaptureResult missing LENS_STATE.");
     94             Log.e(TAG, "\n!!!! TotalCaptureResult missing LENS_STATE. !!!!\n ");
     95         }
     96         return !missing;
     97     }
     98 
     99 
    100     public static void logExtraFocusInfo(CaptureResult result) {
    101         if(!checkControlAfState(result) || !checkLensState(result)) {
    102             return;
    103         }
    104 
    105         Object tag = result.getRequest().getTag();
    106 
    107         Log.v(TAG, String.format("af_state:%-17s  lens_foc_dist:%.3f  lens_state:%-10s  %s",
    108                 controlAFStateToString(result.get(CaptureResult.CONTROL_AF_STATE)),
    109                 result.get(CaptureResult.LENS_FOCUS_DISTANCE),
    110                 lensStateToString(result.get(CaptureResult.LENS_STATE)),
    111                 (tag == null) ? "" : "[" + tag +"]"
    112         ));
    113     }
    114 
    115     /** Compute 3A regions for a sensor-referenced touch coordinate.
    116      * Returns a MeteringRectangle[] with length 1.
    117      *
    118      * @param nx x coordinate of the touch point, in normalized portrait coordinates.
    119      * @param ny y coordinate of the touch point, in normalized portrait coordinates.
    120      * @param fraction Fraction in [0,1]. Multiplied by min(cropRegion.width(), cropRegion.height())
    121      *             to determine the side length of the square MeteringRectangle.
    122      * @param cropRegion Crop region of the image.
    123      * @param sensorOrientation sensor orientation as defined by
    124      *             CameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION).
    125      */
    126     private static MeteringRectangle[] regionsForNormalizedCoord(float nx, float ny,
    127         float fraction, final Rect cropRegion, int sensorOrientation) {
    128         // Compute half side length in pixels.
    129         int minCropEdge = Math.min(cropRegion.width(), cropRegion.height());
    130         int halfSideLength = (int) (0.5f * fraction * minCropEdge);
    131 
    132         // Compute the output MeteringRectangle in sensor space.
    133         // nx, ny is normalized to the screen.
    134         // Crop region itself is specified in sensor coordinates.
    135 
    136         // Normalized coordinates, now rotated into sensor space.
    137         PointF nsc = CameraUtil.normalizedSensorCoordsForNormalizedDisplayCoords(
    138             nx, ny, sensorOrientation);
    139 
    140         int xCenterSensor = (int)(cropRegion.left + nsc.x * cropRegion.width());
    141         int yCenterSensor = (int)(cropRegion.top + nsc.y * cropRegion.height());
    142 
    143         Rect meteringRegion = new Rect(xCenterSensor - halfSideLength,
    144             yCenterSensor - halfSideLength,
    145             xCenterSensor + halfSideLength,
    146             yCenterSensor + halfSideLength);
    147 
    148         // Clamp meteringRegion to cropRegion.
    149         meteringRegion.left = CameraUtil.clamp(meteringRegion.left, cropRegion.left, cropRegion.right);
    150         meteringRegion.top = CameraUtil.clamp(meteringRegion.top, cropRegion.top, cropRegion.bottom);
    151         meteringRegion.right = CameraUtil.clamp(meteringRegion.right, cropRegion.left, cropRegion.right);
    152         meteringRegion.bottom = CameraUtil.clamp(meteringRegion.bottom, cropRegion.top, cropRegion.bottom);
    153 
    154         return new MeteringRectangle[]{new MeteringRectangle(meteringRegion, CAMERA2_REGION_WEIGHT)};
    155     }
    156 
    157     /**
    158      * Return AF region(s) for a sensor-referenced touch coordinate.
    159      *
    160      * <p>
    161      * Normalized coordinates are referenced to portrait preview window with
    162      * (0, 0) top left and (1, 1) bottom right. Rotation has no effect.
    163      * </p>
    164      *
    165      * @return AF region(s).
    166      */
    167     public static MeteringRectangle[] afRegionsForNormalizedCoord(float nx,
    168         float ny, final Rect cropRegion, int sensorOrientation) {
    169         return regionsForNormalizedCoord(nx, ny, Settings3A.getAutoFocusRegionWidth(),
    170             cropRegion, sensorOrientation);
    171     }
    172 
    173     /**
    174      * Return AE region(s) for a sensor-referenced touch coordinate.
    175      *
    176      * <p>
    177      * Normalized coordinates are referenced to portrait preview window with
    178      * (0, 0) top left and (1, 1) bottom right. Rotation has no effect.
    179      * </p>
    180      *
    181      * @return AE region(s).
    182      */
    183     public static MeteringRectangle[] aeRegionsForNormalizedCoord(float nx,
    184         float ny, final Rect cropRegion, int sensorOrientation) {
    185         return regionsForNormalizedCoord(nx, ny, Settings3A.getMeteringRegionWidth(),
    186             cropRegion, sensorOrientation);
    187     }
    188 
    189     /**
    190      * [Gcam mode only]: Return AE region(s) for a sensor-referenced touch coordinate.
    191      *
    192      * <p>
    193      * Normalized coordinates are referenced to portrait preview window with
    194      * (0, 0) top left and (1, 1) bottom right. Rotation has no effect.
    195      * </p>
    196      *
    197      * @return AE region(s).
    198      */
    199     public static MeteringRectangle[] gcamAERegionsForNormalizedCoord(float nx,
    200         float ny, final Rect cropRegion, int sensorOrientation) {
    201         return regionsForNormalizedCoord(nx, ny, Settings3A.getGcamMeteringRegionFraction(),
    202             cropRegion, sensorOrientation);
    203     }
    204 
    205     /**
    206      * Calculates sensor crop region for a zoom level (zoom >= 1.0).
    207      *
    208      * @return Crop region.
    209      */
    210     public static Rect cropRegionForZoom(CameraCharacteristics characteristics, float zoom) {
    211         Rect sensor = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
    212         int xCenter = sensor.width() / 2;
    213         int yCenter = sensor.height() / 2;
    214         int xDelta = (int) (0.5f * sensor.width() / zoom);
    215         int yDelta = (int) (0.5f * sensor.height() / zoom);
    216         return new Rect(xCenter - xDelta, yCenter - yDelta, xCenter + xDelta, yCenter + yDelta);
    217     }
    218 
    219     /**
    220      * Utility function: converts CaptureResult.CONTROL_AF_STATE to String.
    221      */
    222     private static String controlAFStateToString(int controlAFState) {
    223         switch (controlAFState) {
    224             case CaptureResult.CONTROL_AF_STATE_INACTIVE:
    225                 return "inactive";
    226             case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
    227                 return "passive_scan";
    228             case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
    229                 return "passive_focused";
    230             case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
    231                 return "active_scan";
    232             case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
    233                 return "focus_locked";
    234             case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
    235                 return "not_focus_locked";
    236             case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
    237                 return "passive_unfocused";
    238             default:
    239                 return "unknown";
    240         }
    241     }
    242 
    243     /**
    244      * Utility function: converts CaptureResult.LENS_STATE to String.
    245      */
    246     private static String lensStateToString(int lensState) {
    247         switch (lensState) {
    248             case CaptureResult.LENS_STATE_MOVING:
    249                 return "moving";
    250             case CaptureResult.LENS_STATE_STATIONARY:
    251                 return "stationary";
    252             default:
    253                 return "unknown";
    254         }
    255     }
    256 
    257 }
    258