summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/one/v2/AutoFocusHelper.java
blob: f0e7f85747dec127b9766bac25cb2b06425b81d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.camera.one.v2;

import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.params.MeteringRectangle;

import com.android.camera.debug.Log;
import com.android.camera.one.OneCamera;
import com.android.camera.one.Settings3A;

/**
 * Helper class to implement auto focus and 3A in camera2-based
 * {@link com.android.camera.one.OneCamera} implementations.
 */
public class AutoFocusHelper {
    private static final Log.Tag TAG = new Log.Tag("OneCameraAFHelp");

    /** camera2 API metering region weight. */
    private static final int CAMERA2_REGION_WEIGHT = (int)
            (((1 - Settings3A.getMeteringRegionWeight()) * MeteringRectangle.METERING_WEIGHT_MIN +
                    Settings3A.getMeteringRegionWeight() * MeteringRectangle.METERING_WEIGHT_MAX));

    /** Zero weight 3A region, to reset regions per API. */
    private static final MeteringRectangle[] ZERO_WEIGHT_3A_REGION = new MeteringRectangle[]{
            new MeteringRectangle(0, 0, 0, 0, 0)
    };

    public static MeteringRectangle[] getZeroWeightRegion() {
        return ZERO_WEIGHT_3A_REGION;
    }

    /**
     * Convert reported camera2 AF state to OneCamera AutoFocusState.
     */
    public static OneCamera.AutoFocusState stateFromCamera2State(int state) {
        switch (state) {
            case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
                return OneCamera.AutoFocusState.ACTIVE_SCAN;
            case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
                return OneCamera.AutoFocusState.PASSIVE_SCAN;
            case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
                return OneCamera.AutoFocusState.PASSIVE_FOCUSED;
            case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
                return OneCamera.AutoFocusState.ACTIVE_FOCUSED;
            case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
                return OneCamera.AutoFocusState.PASSIVE_UNFOCUSED;
            case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
                return OneCamera.AutoFocusState.ACTIVE_UNFOCUSED;
            default:
                return OneCamera.AutoFocusState.INACTIVE;
        }
    }

    /**
     * Complain if CONTROL_AF_STATE is not present in result.
     * Could indicate bug in API implementation.
     */
    public static boolean checkControlAfState(CaptureResult result) {
        boolean missing = result.get(CaptureResult.CONTROL_AF_STATE) == null;
        if (missing) {
            // throw new IllegalStateException("CaptureResult missing CONTROL_AF_STATE.");
            Log.e(TAG, "\n!!!! TotalCaptureResult missing CONTROL_AF_STATE. !!!!\n ");
        }
        return !missing;
    }

    /**
     * Complain if LENS_STATE is not present in result.
     * Could indicate bug in API implementation.
     */
    public static boolean checkLensState(CaptureResult result) {
        boolean missing = result.get(CaptureResult.LENS_STATE) == null;
        if (missing) {
            // throw new IllegalStateException("CaptureResult missing LENS_STATE.");
            Log.e(TAG, "\n!!!! TotalCaptureResult missing LENS_STATE. !!!!\n ");
        }
        return !missing;
    }


    public static void logExtraFocusInfo(CaptureResult result) {
        if(!checkControlAfState(result) || !checkLensState(result)) {
            return;
        }

        Object tag = result.getRequest().getTag();

        Log.v(TAG, String.format("af_state:%-17s  lens_foc_dist:%.3f  lens_state:%-10s  %s",
                controlAFStateToString(result.get(CaptureResult.CONTROL_AF_STATE)),
                result.get(CaptureResult.LENS_FOCUS_DISTANCE),
                lensStateToString(result.get(CaptureResult.LENS_STATE)),
                (tag == null) ? "" : "[" + tag +"]"
        ));
    }

    /** Compute 3A regions for a sensor-referenced touch coordinate. */
    private static MeteringRectangle[] regionsForSensorCoord(int xc, int yc, float width,
                                                             Rect cropRegion) {
        float minCropEdge = (float) Math.min(cropRegion.width(), cropRegion.height());
        int delta = (int) (0.5 * width * minCropEdge);
        Rect region = new Rect(xc - delta, yc - delta, xc + delta, yc + delta);
        // Make sure region is inside the sensor area.
        if (!region.intersect(cropRegion)) {
            region = cropRegion;
        }
        return new MeteringRectangle[]{new MeteringRectangle(region, CAMERA2_REGION_WEIGHT)};
    }

    /**
     * Return AF region(s) for a sensor-referenced touch coordinate.
     *
     * @return AF region(s).
     */
    public static MeteringRectangle[] afRegionsForSensorCoord(int xc, int yc, Rect cropRegion) {
        return regionsForSensorCoord(xc, yc, Settings3A.getAutoFocusRegionWidth(), cropRegion);
    }

    /**
     * Return AE region(s) for a sensor-referenced touch coordinate.
     *
     * @return AE region(s).
     */
    public static MeteringRectangle[] aeRegionsForSensorCoord(int xc, int yc, Rect cropRegion) {
        return regionsForSensorCoord(xc, yc, Settings3A.getMeteringRegionWidth(), cropRegion);
    }

    /**
     * Calculates sensor crop region for a zoom level (zoom >= 1.0).
     *
     * @return Crop region.
     */
    public static Rect cropRegionForZoom(CameraCharacteristics characteristics, float zoom) {
        Rect sensor = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
        int xCenter = sensor.width() / 2;
        int yCenter = sensor.height() / 2;
        int xDelta = (int) (0.5f * sensor.width() / zoom);
        int yDelta = (int) (0.5f * sensor.height() / zoom);
        return new Rect(xCenter - xDelta, yCenter - yDelta, xCenter + xDelta, yCenter + yDelta);
    }

    /**
     * Utility function: converts CaptureResult.CONTROL_AF_STATE to String.
     */
    private static String controlAFStateToString(int controlAFState) {
        switch (controlAFState) {
            case CaptureResult.CONTROL_AF_STATE_INACTIVE:
                return "inactive";
            case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
                return "passive_scan";
            case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
                return "passive_focused";
            case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
                return "active_scan";
            case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
                return "focus_locked";
            case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
                return "not_focus_locked";
            case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
                return "passive_unfocused";
            default:
                return "unknown";
        }
    }

    /**
     * Utility function: converts CaptureResult.LENS_STATE to String.
     */
    private static String lensStateToString(int lensState) {
        switch (lensState) {
            case CaptureResult.LENS_STATE_MOVING:
                return "moving";
            case CaptureResult.LENS_STATE_STATIONARY:
                return "stationary";
            default:
                return "unknown";
        }
    }

}