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.ex.camera2.portability; 18 19 import android.graphics.Matrix; 20 import android.graphics.RectF; 21 22 import com.android.ex.camera2.portability.debug.Log; 23 24 /** 25 * The device info for all attached cameras. 26 */ 27 public interface CameraDeviceInfo { 28 29 static final int NO_DEVICE = -1; 30 31 /** 32 * @param cameraId Which device to interrogate. 33 * @return The static characteristics of the specified device, or {@code null} on error. 34 */ getCharacteristics(int cameraId)35 Characteristics getCharacteristics(int cameraId); 36 37 /** 38 * @return The total number of the available camera devices. 39 */ getNumberOfCameras()40 int getNumberOfCameras(); 41 42 /** 43 * @return The first (lowest) ID of the back cameras or {@code NO_DEVICE} 44 * if not available. 45 */ getFirstBackCameraId()46 int getFirstBackCameraId(); 47 48 /** 49 * @return The first (lowest) ID of the front cameras or {@code NO_DEVICE} 50 * if not available. 51 */ getFirstFrontCameraId()52 int getFirstFrontCameraId(); 53 54 /** 55 * Device characteristics for a single camera. 56 */ 57 public abstract class Characteristics { 58 private static final Log.Tag TAG = new Log.Tag("CamDvcInfChar"); 59 60 /** 61 * @return Whether the camera faces the back of the device. 62 */ isFacingBack()63 public abstract boolean isFacingBack(); 64 65 /** 66 * @return Whether the camera faces the device's screen. 67 */ isFacingFront()68 public abstract boolean isFacingFront(); 69 70 /** 71 * @return The camera sensor orientation, or the counterclockwise angle 72 * from its natural position that the device must be held at 73 * for the sensor to be right side up (in degrees, always a 74 * multiple of 90, and between 0 and 270, inclusive). 75 */ getSensorOrientation()76 public abstract int getSensorOrientation(); 77 78 /** 79 * @param currentDisplayOrientation 80 * The current display orientation, measured counterclockwise 81 * from to the device's natural orientation (in degrees, always 82 * a multiple of 90, and between 0 and 270, inclusive). 83 * @return 84 * The relative preview image orientation, or the clockwise 85 * rotation angle that must be applied to display preview 86 * frames in the matching orientation, accounting for implicit 87 * mirroring, if applicable (in degrees, always a multiple of 88 * 90, and between 0 and 270, inclusive). 89 */ getPreviewOrientation(int currentDisplayOrientation)90 public int getPreviewOrientation(int currentDisplayOrientation) { 91 // Drivers tend to mirror the image during front camera preview. 92 return getRelativeImageOrientation(currentDisplayOrientation, true); 93 } 94 95 /** 96 * @param currentDisplayOrientation 97 * The current display orientation, measured counterclockwise 98 * from to the device's natural orientation (in degrees, always 99 * a multiple of 90, and between 0 and 270, inclusive). 100 * @return 101 * The relative capture image orientation, or the clockwise 102 * rotation angle that must be applied to display these frames 103 * in the matching orientation (in degrees, always a multiple 104 * of 90, and between 0 and 270, inclusive). 105 */ getJpegOrientation(int currentDisplayOrientation)106 public int getJpegOrientation(int currentDisplayOrientation) { 107 // Don't mirror during capture! 108 return getRelativeImageOrientation(currentDisplayOrientation, false); 109 } 110 111 /** 112 * @param currentDisplayOrientaiton 113 * {@link #getPreviewOrientation}, {@link #getJpegOrientation} 114 * @param compensateForMirroring 115 * Whether to account for mirroring in the case of front-facing 116 * cameras, which is necessary iff the OS/driver is 117 * automatically reflecting the image. 118 * @return 119 * {@link #getPreviewOrientation}, {@link #getJpegOrientation} 120 * 121 * @see android.hardware.Camera.setDisplayOrientation 122 */ getRelativeImageOrientation(int currentDisplayOrientation, boolean compensateForMirroring)123 protected int getRelativeImageOrientation(int currentDisplayOrientation, 124 boolean compensateForMirroring) { 125 if (!orientationIsValid(currentDisplayOrientation)) { 126 return 0; 127 } 128 129 int result = 0; 130 if (isFacingFront()) { 131 result = (getSensorOrientation() + currentDisplayOrientation) % 360; 132 if (compensateForMirroring) { 133 result = (360 - result) % 360; 134 } 135 } else if (isFacingBack()) { 136 result = (getSensorOrientation() - currentDisplayOrientation + 360) % 360; 137 } else { 138 Log.e(TAG, "Camera is facing unhandled direction"); 139 } 140 return result; 141 } 142 143 /** 144 * @param currentDisplayOrientation 145 * The current display orientation, measured counterclockwise 146 * from to the device's natural orientation (in degrees, always 147 * a multiple of 90, and between 0 and 270, inclusive). 148 * @param surfaceDimensions 149 * The dimensions of the {@link android.view.Surface} on which 150 * the preview image is being rendered. It usually only makes 151 * sense for the upper-left corner to be at the origin. 152 * @return 153 * The transform matrix that should be applied to the 154 * {@link android.view.Surface} in order for the image to 155 * display properly in the device's current orientation. 156 */ getPreviewTransform(int currentDisplayOrientation, RectF surfaceDimensions)157 public Matrix getPreviewTransform(int currentDisplayOrientation, RectF surfaceDimensions) { 158 return getPreviewTransform(currentDisplayOrientation, surfaceDimensions, 159 new RectF(surfaceDimensions)); 160 } 161 162 /** 163 * @param currentDisplayOrientation 164 * The current display orientation, measured counterclockwise 165 * from to the device's natural orientation (in degrees, always 166 * a multiple of 90, and between 0 and 270, inclusive). 167 * @param surfaceDimensions 168 * The dimensions of the {@link android.view.Surface} on which 169 * the preview image is being rendered. It usually only makes 170 * sense for the upper-left corner to be at the origin. 171 * @param desiredBounds 172 * The boundaries within the {@link android.view.Surface} where 173 * the final image should appear. These can be used to 174 * translate and scale the output, but note that the image will 175 * be stretched to fit, possibly changing its aspect ratio. 176 * @return 177 * The transform matrix that should be applied to the 178 * {@link android.view.Surface} in order for the image to 179 * display properly in the device's current orientation. 180 */ getPreviewTransform(int currentDisplayOrientation, RectF surfaceDimensions, RectF desiredBounds)181 public Matrix getPreviewTransform(int currentDisplayOrientation, RectF surfaceDimensions, 182 RectF desiredBounds) { 183 if (!orientationIsValid(currentDisplayOrientation) || 184 surfaceDimensions.equals(desiredBounds)) { 185 return new Matrix(); 186 } 187 188 Matrix transform = new Matrix(); 189 transform.setRectToRect(surfaceDimensions, desiredBounds, Matrix.ScaleToFit.FILL); 190 return transform; 191 } 192 193 /** 194 * @return Whether the shutter sound can be disabled. 195 */ canDisableShutterSound()196 public abstract boolean canDisableShutterSound(); 197 orientationIsValid(int angle)198 protected static boolean orientationIsValid(int angle) { 199 if (angle % 90 != 0) { 200 Log.e(TAG, "Provided display orientation is not divisible by 90"); 201 return false; 202 } 203 if (angle < 0 || angle > 270) { 204 Log.e(TAG, "Provided display orientation is outside expected range"); 205 return false; 206 } 207 return true; 208 } 209 } 210 } 211