1de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher/* 2de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Copyright (C) 2014 The Android Open Source Project 3de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 4de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Licensed under the Apache License, Version 2.0 (the "License"); 5de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * you may not use this file except in compliance with the License. 6de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * You may obtain a copy of the License at 7de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 8de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * http://www.apache.org/licenses/LICENSE-2.0 9de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 10de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Unless required by applicable law or agreed to in writing, software 11de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * distributed under the License is distributed on an "AS IS" BASIS, 12de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * See the License for the specific language governing permissions and 14de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * limitations under the License. 15de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 16de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 177e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kongpackage com.android.ex.camera2.portability; 187e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong 19f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucherimport android.graphics.Matrix; 20f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucherimport android.graphics.RectF; 217e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong 22de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.portability.debug.Log; 23de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 247e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong/** 25b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher * The device info for all attached cameras. 267e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong */ 277e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kongpublic interface CameraDeviceInfo { 287e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong 297e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong static final int NO_DEVICE = -1; 307e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong 317e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong /** 32b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher * @param cameraId Which device to interrogate. 33b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher * @return The static characteristics of the specified device, or {@code null} on error. 347e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong */ 35b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher Characteristics getCharacteristics(int cameraId); 367e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong 377e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong /** 387e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong * @return The total number of the available camera devices. 397e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong */ 407e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong int getNumberOfCameras(); 417e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong 427e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong /** 437e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong * @return The first (lowest) ID of the back cameras or {@code NO_DEVICE} 447e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong * if not available. 457e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong */ 467e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong int getFirstBackCameraId(); 477e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong 487e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong /** 497e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong * @return The first (lowest) ID of the front cameras or {@code NO_DEVICE} 507e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong * if not available. 517e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong */ 527e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong int getFirstFrontCameraId(); 53b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher 54b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher /** 55b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher * Device characteristics for a single camera. 56b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher */ 57de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public abstract class Characteristics { 58de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private static final Log.Tag TAG = new Log.Tag("CamDvcInfChar"); 59de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 60b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher /** 61b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher * @return Whether the camera faces the back of the device. 62b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher */ 63de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public abstract boolean isFacingBack(); 64b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher 65b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher /** 66b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher * @return Whether the camera faces the device's screen. 67b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher */ 68de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public abstract boolean isFacingFront(); 69b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher 70b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher /** 71f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @return The camera sensor orientation, or the counterclockwise angle 72f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * from its natural position that the device must be held at 73f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * for the sensor to be right side up (in degrees, always a 74f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * multiple of 90, and between 0 and 270, inclusive). 75de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 76de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public abstract int getSensorOrientation(); 77de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 78de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 79de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param currentDisplayOrientation 80f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The current display orientation, measured counterclockwise 81f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * from to the device's natural orientation (in degrees, always 82f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * a multiple of 90, and between 0 and 270, inclusive). 83de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @return 84de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * The relative preview image orientation, or the clockwise 85de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * rotation angle that must be applied to display preview 86de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * frames in the matching orientation, accounting for implicit 87de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * mirroring, if applicable (in degrees, always a multiple of 88de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 90, and between 0 and 270, inclusive). 89b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher */ 90de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public int getPreviewOrientation(int currentDisplayOrientation) { 91de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Drivers tend to mirror the image during front camera preview. 92de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return getRelativeImageOrientation(currentDisplayOrientation, true); 93de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 94de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 95de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 96de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param currentDisplayOrientation 97f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The current display orientation, measured counterclockwise 98f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * from to the device's natural orientation (in degrees, always 99f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * a multiple of 90, and between 0 and 270, inclusive). 100de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @return 101de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * The relative capture image orientation, or the clockwise 102de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * rotation angle that must be applied to display these frames 103de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * in the matching orientation (in degrees, always a multiple 104de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * of 90, and between 0 and 270, inclusive). 105de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 106de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public int getJpegOrientation(int currentDisplayOrientation) { 107de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Don't mirror during capture! 108de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return getRelativeImageOrientation(currentDisplayOrientation, false); 109de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 110de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 111de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 112de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param currentDisplayOrientaiton 113de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * {@link #getPreviewOrientation}, {@link #getJpegOrientation} 114de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param compensateForMirroring 115de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Whether to account for mirroring in the case of front-facing 116de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * cameras, which is necessary iff the OS/driver is 117de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * automatically reflecting the image. 118de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @return 119de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * {@link #getPreviewOrientation}, {@link #getJpegOrientation} 120de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 121de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @see android.hardware.Camera.setDisplayOrientation 122de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 123de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher protected int getRelativeImageOrientation(int currentDisplayOrientation, 124de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher boolean compensateForMirroring) { 125f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (!orientationIsValid(currentDisplayOrientation)) { 126f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return 0; 127de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 128de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 129de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher int result = 0; 130de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (isFacingFront()) { 131de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher result = (getSensorOrientation() + currentDisplayOrientation) % 360; 132de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (compensateForMirroring) { 133de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher result = (360 - result) % 360; 134de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 135de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } else if (isFacingBack()) { 136de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher result = (getSensorOrientation() - currentDisplayOrientation + 360) % 360; 137de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } else { 138de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Camera is facing unhandled direction"); 139de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 140de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return result; 141de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 142b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher 143b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher /** 144f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param currentDisplayOrientation 145f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The current display orientation, measured counterclockwise 146f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * from to the device's natural orientation (in degrees, always 147f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * a multiple of 90, and between 0 and 270, inclusive). 148f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param surfaceDimensions 149f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The dimensions of the {@link android.view.Surface} on which 150f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * the preview image is being rendered. It usually only makes 151f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * sense for the upper-left corner to be at the origin. 152f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @return 153f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The transform matrix that should be applied to the 154f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * {@link android.view.Surface} in order for the image to 155f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * display properly in the device's current orientation. 156f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher */ 157f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher public Matrix getPreviewTransform(int currentDisplayOrientation, RectF surfaceDimensions) { 158f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return getPreviewTransform(currentDisplayOrientation, surfaceDimensions, 159f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher new RectF(surfaceDimensions)); 160f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 161f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 162f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher /** 163f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param currentDisplayOrientation 164f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The current display orientation, measured counterclockwise 165f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * from to the device's natural orientation (in degrees, always 166f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * a multiple of 90, and between 0 and 270, inclusive). 167f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param surfaceDimensions 168f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The dimensions of the {@link android.view.Surface} on which 169f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * the preview image is being rendered. It usually only makes 170f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * sense for the upper-left corner to be at the origin. 171f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param desiredBounds 172f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The boundaries within the {@link android.view.Surface} where 173f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * the final image should appear. These can be used to 174f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * translate and scale the output, but note that the image will 175f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * be stretched to fit, possibly changing its aspect ratio. 176f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @return 177f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * The transform matrix that should be applied to the 178f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * {@link android.view.Surface} in order for the image to 179f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * display properly in the device's current orientation. 180f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher */ 181f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher public Matrix getPreviewTransform(int currentDisplayOrientation, RectF surfaceDimensions, 182f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher RectF desiredBounds) { 183f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (!orientationIsValid(currentDisplayOrientation) || 184f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher surfaceDimensions.equals(desiredBounds)) { 185f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return new Matrix(); 186f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 187f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 188f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher Matrix transform = new Matrix(); 189f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher transform.setRectToRect(surfaceDimensions, desiredBounds, Matrix.ScaleToFit.FILL); 190f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return transform; 191f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 192f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 193f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher /** 194b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher * @return Whether the shutter sound can be disabled. 195b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher */ 196de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public abstract boolean canDisableShutterSound(); 197f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 198f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher protected static boolean orientationIsValid(int angle) { 199f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (angle % 90 != 0) { 200f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher Log.e(TAG, "Provided display orientation is not divisible by 90"); 201f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return false; 202f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 203f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (angle < 0 || angle > 270) { 204f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher Log.e(TAG, "Provided display orientation is outside expected range"); 205f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return false; 206f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 207f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return true; 208f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 209b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher } 2107e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong} 211