summaryrefslogtreecommitdiffstats
path: root/camera2
diff options
context:
space:
mode:
authorAngus Kong <shkong@google.com>2014-04-22 16:39:42 -0700
committerEd Heyl <edheyl@google.com>2014-06-18 10:24:45 -0700
commitc36e3c983c232dc45ed31f3d8e98d8cdd7ac14ba (patch)
tree2a08cc88067dafb4fc0c4b96955c69cf4a3149b8 /camera2
parent60520c4df78e595964605cf8acfa21bbafaeba84 (diff)
downloadandroid_frameworks_ex-c36e3c983c232dc45ed31f3d8e98d8cdd7ac14ba.tar.gz
android_frameworks_ex-c36e3c983c232dc45ed31f3d8e98d8cdd7ac14ba.tar.bz2
android_frameworks_ex-c36e3c983c232dc45ed31f3d8e98d8cdd7ac14ba.zip
First Step: CameraCapabilities intead of Parameter
To get rid of Camera.Parameters, we need to provide our own interfaces. Camera.Parameters actually consists of 2 parts: capabilities and settings. We'll provide two interfaces and will just use Camera.Parameters inside of CameraManager implementations. Change-Id: I53922b6d740835412d74365374a6a0382129564e
Diffstat (limited to 'camera2')
-rw-r--r--camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java451
-rw-r--r--camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraManagerImpl.java18
-rw-r--r--camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java537
-rw-r--r--camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilitiesFactory.java34
-rw-r--r--camera2/portability/src/com/android/ex/camera2/portability/CameraManager.java13
5 files changed, 1044 insertions, 9 deletions
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java
new file mode 100644
index 0000000..38e3f36
--- /dev/null
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java
@@ -0,0 +1,451 @@
+/*
+ * 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.ex.camera2.portability;
+
+import android.graphics.Point;
+import android.hardware.Camera;
+
+import com.android.ex.camera2.portability.debug.Log;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * The subclass of {@link CameraCapabilities} for Android Camera 1 API.
+ */
+public class AndroidCameraCapabilities extends CameraCapabilities {
+
+ private static Log.Tag TAG = new Log.Tag("AndroidCameraCapabilities");
+
+ private FpsComparator mFpsComparator = new FpsComparator();
+ private SizeComparator mSizeComparator = new SizeComparator();
+
+ AndroidCameraCapabilities(Camera.Parameters p) {
+ super(new AndroidCameraCapabilityStringifier());
+ mMaxExposureCompensation = p.getMaxExposureCompensation();
+ mMinExposureCompensation = p.getMinExposureCompensation();
+ mExposureCompensationStep = p.getExposureCompensationStep();
+ mMaxNumOfFacesSupported = p.getMaxNumDetectedFaces();
+ mMaxNumOfMeteringArea = p.getMaxNumMeteringAreas();
+ mSupportedPreviewFormats.addAll(p.getSupportedPreviewFormats());
+ mSupportedPictureFormats.addAll(p.getSupportedPictureFormats());
+ buildPreviewFpsRange(p);
+ buildPreviewSizes(p);
+ buildVideoSizes(p);
+ buildPictureSizes(p);
+ buildSceneModes(p);
+ buildFlashModes(p);
+ buildFocusModes(p);
+ buildWhiteBalances(p);
+
+ if (p.isZoomSupported()) {
+ mSupportedFeatures.add(Feature.ZOOM);
+ }
+ if (p.isVideoSnapshotSupported()) {
+ mSupportedFeatures.add(Feature.VIDEO_SNAPSHOT);
+ }
+ if (p.isAutoExposureLockSupported()) {
+ mSupportedFeatures.add(Feature.AUTO_EXPOSURE_LOCK);
+ }
+ if (p.isAutoWhiteBalanceLockSupported()) {
+ mSupportedFeatures.add(Feature.AUTO_WHITE_BALANCE_LOCK);
+ }
+ if (supports(FocusMode.AUTO)) {
+ mMaxNumOfFocusAreas = p.getMaxNumFocusAreas();
+ if (mMaxNumOfFocusAreas > 0) {
+ mSupportedFeatures.add(Feature.FOCUS_AREA);
+ }
+ }
+ if (mMaxNumOfMeteringArea > 0) {
+ mSupportedFeatures.add(Feature.METERING_AREA);
+ }
+ }
+
+ AndroidCameraCapabilities(AndroidCameraCapabilities src) {
+ super(src);
+ }
+
+ private void buildPreviewFpsRange(Camera.Parameters p) {
+ List<int[]> supportedPreviewFpsRange = p.getSupportedPreviewFpsRange();
+ if (supportedPreviewFpsRange != null) {
+ mSupportedPreviewFpsRange.addAll(supportedPreviewFpsRange);
+ }
+ Collections.sort(mSupportedPreviewFpsRange, mFpsComparator);
+ }
+
+ private void buildPreviewSizes(Camera.Parameters p) {
+ List<Camera.Size> supportedPreviewSizes = p.getSupportedPreviewSizes();
+ if (supportedPreviewSizes != null) {
+ for (Camera.Size s : supportedPreviewSizes) {
+ mSupportedPreviewSizes.add(new Point(s.width, s.height));
+ }
+ }
+ Collections.sort(mSupportedPreviewSizes, mSizeComparator);
+ }
+
+ private void buildVideoSizes(Camera.Parameters p) {
+ List<Camera.Size> supportedVideoSizes = p.getSupportedVideoSizes();
+ if (supportedVideoSizes != null) {
+ for (Camera.Size s : supportedVideoSizes) {
+ mSupportedVideoSizes.add(new Point(s.width, s.height));
+ }
+ }
+ Collections.sort(mSupportedVideoSizes, mSizeComparator);
+ }
+
+ private void buildPictureSizes(Camera.Parameters p) {
+ List<Camera.Size> supportedPictureSizes = p.getSupportedPictureSizes();
+ if (supportedPictureSizes != null) {
+ for (Camera.Size s : supportedPictureSizes) {
+ mSupportedPictureSizes.add(new Point(s.width, s.height));
+ }
+ }
+ Collections.sort(mSupportedPictureSizes, mSizeComparator);
+
+ }
+
+ private void buildSceneModes(Camera.Parameters p) {
+ List<String> supportedSceneModes = p.getSupportedSceneModes();
+ if (supportedSceneModes != null) {
+ for (String scene : supportedSceneModes) {
+ if (Camera.Parameters.SCENE_MODE_AUTO.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.AUTO);
+ } else if (Camera.Parameters.SCENE_MODE_ACTION.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.ACTION);
+ } else if (Camera.Parameters.SCENE_MODE_BARCODE.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.BARCODE);
+ } else if (Camera.Parameters.SCENE_MODE_BEACH.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.BEACH);
+ } else if (Camera.Parameters.SCENE_MODE_CANDLELIGHT.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.CANDLELIGHT);
+ } else if (Camera.Parameters.SCENE_MODE_FIREWORKS.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.FIREWORKS);
+ } else if (Camera.Parameters.SCENE_MODE_HDR.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.HDR);
+ } else if (Camera.Parameters.SCENE_MODE_LANDSCAPE.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.LANDSCAPE);
+ } else if (Camera.Parameters.SCENE_MODE_NIGHT.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.NIGHT);
+ } else if (Camera.Parameters.SCENE_MODE_NIGHT_PORTRAIT.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.NIGHT_PORTRAIT);
+ } else if (Camera.Parameters.SCENE_MODE_PARTY.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.PARTY);
+ } else if (Camera.Parameters.SCENE_MODE_PORTRAIT.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.PORTRAIT);
+ } else if (Camera.Parameters.SCENE_MODE_SNOW.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.SNOW);
+ } else if (Camera.Parameters.SCENE_MODE_SPORTS.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.SPORTS);
+ } else if (Camera.Parameters.SCENE_MODE_STEADYPHOTO.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.STEADYPHOTO);
+ } else if (Camera.Parameters.SCENE_MODE_SUNSET.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.SUNSET);
+ } else if (Camera.Parameters.SCENE_MODE_THEATRE.equals(scene)) {
+ mSupportedSceneModes.add(SceneMode.THEATRE);
+ }
+ }
+ }
+ }
+
+ private void buildFlashModes(Camera.Parameters p) {
+ List<String> supportedFlashModes = p.getSupportedFlashModes();
+ if (supportedFlashModes != null) {
+ for (String flash : supportedFlashModes) {
+ if (Camera.Parameters.FLASH_MODE_AUTO.equals(flash)) {
+ mSupportedFlashModes.add(FlashMode.AUTO);
+ } else if (Camera.Parameters.FLASH_MODE_OFF.equals(flash)) {
+ mSupportedFlashModes.add(FlashMode.OFF);
+ } else if (Camera.Parameters.FLASH_MODE_ON.equals(flash)) {
+ mSupportedFlashModes.add(FlashMode.ON);
+ } else if (Camera.Parameters.FLASH_MODE_RED_EYE.equals(flash)) {
+ mSupportedFlashModes.add(FlashMode.RED_EYE);
+ }
+ }
+ }
+ }
+
+ private void buildFocusModes(Camera.Parameters p) {
+ List<String> supportedFocusModes = p.getSupportedFocusModes();
+ if (supportedFocusModes != null) {
+ for (String focus : supportedFocusModes) {
+ if (Camera.Parameters.FOCUS_MODE_AUTO.equals(focus)) {
+ mSupportedFocusModes.add(FocusMode.AUTO);
+ } else if (Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(focus)) {
+ mSupportedFocusModes.add(FocusMode.CONTINUOUS_PICTURE);
+ } else if (Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO.equals(focus)) {
+ mSupportedFocusModes.add(FocusMode.CONTINUOUS_VIDEO);
+ } else if (Camera.Parameters.FOCUS_MODE_EDOF.equals(focus)) {
+ mSupportedFocusModes.add(FocusMode.EXTENDED_DOF);
+ } else if (Camera.Parameters.FOCUS_MODE_FIXED.equals(focus)) {
+ mSupportedFocusModes.add(FocusMode.FIXED);
+ } else if (Camera.Parameters.FOCUS_MODE_INFINITY.equals(focus)) {
+ mSupportedFocusModes.add(FocusMode.INFINITY);
+ } else if (Camera.Parameters.FOCUS_MODE_MACRO.equals(focus)) {
+ mSupportedFocusModes.add(FocusMode.MACRO);
+ }
+ }
+ }
+ }
+
+ private void buildWhiteBalances(Camera.Parameters p) {
+ List<String> supportedWhiteBalances = p.getSupportedFocusModes();
+ if (supportedWhiteBalances != null) {
+ for (String wb : supportedWhiteBalances) {
+ if (Camera.Parameters.WHITE_BALANCE_AUTO.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.AUTO);
+ } else if (Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.CLOUDY_DAYLIGHT);
+ } else if (Camera.Parameters.WHITE_BALANCE_DAYLIGHT.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.DAYLIGHT);
+ } else if (Camera.Parameters.WHITE_BALANCE_FLUORESCENT.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.FLUORESCENT);
+ } else if (Camera.Parameters.WHITE_BALANCE_INCANDESCENT.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.INCANDESCENT);
+ } else if (Camera.Parameters.WHITE_BALANCE_SHADE.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.SHADE);
+ } else if (Camera.Parameters.WHITE_BALANCE_TWILIGHT.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.TWILIGHT);
+ } else if (Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT.equals(wb)) {
+ mSupportedWhiteBalances.add(WhiteBalance.WARM_FLUORESCENT);
+ }
+ }
+ }
+ }
+
+ private static class FpsComparator implements Comparator<int[]> {
+ @Override
+ public int compare(int[] fps1, int[] fps2) {
+ return (fps1[0] == fps2[0] ? fps1[1] - fps2[1] : fps1[0] - fps2[0]);
+ }
+ }
+
+ private static class SizeComparator implements Comparator<Point> {
+
+ @Override
+ public int compare(Point size1, Point size2) {
+ return (size1.x == size2.x ? size1.y - size2.y : size1.x - size2.x);
+ }
+ }
+
+ private static class AndroidCameraCapabilityStringifier implements Stringifier {
+
+ @Override
+ public String stringify(FocusMode focus) {
+ switch (focus) {
+ case AUTO:
+ return Camera.Parameters.FOCUS_MODE_AUTO;
+ case CONTINUOUS_PICTURE:
+ return Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
+ case CONTINUOUS_VIDEO:
+ return Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO;
+ case EXTENDED_DOF:
+ return Camera.Parameters.FOCUS_MODE_EDOF;
+ case FIXED:
+ return Camera.Parameters.FOCUS_MODE_FIXED;
+ case INFINITY:
+ return Camera.Parameters.FOCUS_MODE_INFINITY;
+ case MACRO:
+ return Camera.Parameters.FOCUS_MODE_MACRO;
+ }
+ return null;
+ }
+
+ @Override
+ public FocusMode focusModeFromString(String val) {
+ if (val.equals(Camera.Parameters.FOCUS_MODE_AUTO)) {
+ return FocusMode.AUTO;
+ } else if (val.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
+ return FocusMode.CONTINUOUS_PICTURE;
+ } else if (val.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
+ return FocusMode.CONTINUOUS_VIDEO;
+ } else if (val.equals(Camera.Parameters.FOCUS_MODE_EDOF)) {
+ return FocusMode.EXTENDED_DOF;
+ } else if (val.equals(Camera.Parameters.FOCUS_MODE_FIXED)) {
+ return FocusMode.FIXED;
+ } else if (val.equals(Camera.Parameters.FOCUS_MODE_INFINITY)) {
+ return FocusMode.INFINITY;
+ } else if (val.equals(Camera.Parameters.FOCUS_MODE_MACRO)) {
+ return FocusMode.MACRO;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String stringify(FlashMode flash) {
+ switch (flash) {
+ case AUTO:
+ return Camera.Parameters.FLASH_MODE_AUTO;
+ case OFF:
+ return Camera.Parameters.FLASH_MODE_OFF;
+ case ON:
+ return Camera.Parameters.FLASH_MODE_ON;
+ case TORCH:
+ return Camera.Parameters.FLASH_MODE_TORCH;
+ case RED_EYE:
+ return Camera.Parameters.FLASH_MODE_RED_EYE;
+ }
+ return null;
+ }
+
+ @Override
+ public FlashMode flashModeFromString(String val) {
+ if (val.equals(Camera.Parameters.FLASH_MODE_AUTO)) {
+ return FlashMode.AUTO;
+ } else if (val.equals(Camera.Parameters.FLASH_MODE_OFF)) {
+ return FlashMode.OFF;
+ } else if (val.equals(Camera.Parameters.FLASH_MODE_ON)) {
+ return FlashMode.ON;
+ } else if (val.equals(Camera.Parameters.FLASH_MODE_TORCH)) {
+ return FlashMode.TORCH;
+ } else if (val.equals(Camera.Parameters.FLASH_MODE_RED_EYE)) {
+ return FlashMode.RED_EYE;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String stringify(SceneMode scene) {
+ switch (scene) {
+ case AUTO:
+ return Camera.Parameters.SCENE_MODE_AUTO;
+ case ACTION:
+ return Camera.Parameters.SCENE_MODE_ACTION;
+ case BARCODE:
+ return Camera.Parameters.SCENE_MODE_BARCODE;
+ case BEACH:
+ return Camera.Parameters.SCENE_MODE_BEACH;
+ case CANDLELIGHT:
+ return Camera.Parameters.SCENE_MODE_CANDLELIGHT;
+ case FIREWORKS:
+ return Camera.Parameters.SCENE_MODE_FIREWORKS;
+ case HDR:
+ return Camera.Parameters.SCENE_MODE_HDR;
+ case LANDSCAPE:
+ return Camera.Parameters.SCENE_MODE_LANDSCAPE;
+ case NIGHT:
+ return Camera.Parameters.SCENE_MODE_NIGHT;
+ case NIGHT_PORTRAIT:
+ return Camera.Parameters.SCENE_MODE_NIGHT_PORTRAIT;
+ case PARTY:
+ return Camera.Parameters.SCENE_MODE_PARTY;
+ case PORTRAIT:
+ return Camera.Parameters.SCENE_MODE_PORTRAIT;
+ case SNOW:
+ return Camera.Parameters.SCENE_MODE_SNOW;
+ case SPORTS:
+ return Camera.Parameters.SCENE_MODE_SPORTS;
+ case STEADYPHOTO:
+ return Camera.Parameters.SCENE_MODE_STEADYPHOTO;
+ case SUNSET:
+ return Camera.Parameters.SCENE_MODE_SUNSET;
+ case THEATRE:
+ return Camera.Parameters.SCENE_MODE_THEATRE;
+ }
+ return null;
+ }
+
+ @Override
+ public SceneMode sceneModeFromString(String val) {
+ if (val.equals(Camera.Parameters.SCENE_MODE_AUTO)) {
+ return SceneMode.AUTO;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_ACTION)) {
+ return SceneMode.ACTION;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_BARCODE)) {
+ return SceneMode.BARCODE;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_BEACH)) {
+ return SceneMode.BEACH;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_CANDLELIGHT)) {
+ return SceneMode.CANDLELIGHT;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_FIREWORKS)) {
+ return SceneMode.FIREWORKS;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_HDR)) {
+ return SceneMode.HDR;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_LANDSCAPE)) {
+ return SceneMode.LANDSCAPE;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_NIGHT)) {
+ return SceneMode.NIGHT;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_NIGHT_PORTRAIT)) {
+ return SceneMode.NIGHT_PORTRAIT;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_PARTY)) {
+ return SceneMode.PARTY;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_PORTRAIT)) {
+ return SceneMode.PORTRAIT;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_SNOW)) {
+ return SceneMode.SNOW;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_SPORTS)) {
+ return SceneMode.SPORTS;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_STEADYPHOTO)) {
+ return SceneMode.STEADYPHOTO;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_SUNSET)) {
+ return SceneMode.SUNSET;
+ } else if (val.equals(Camera.Parameters.SCENE_MODE_THEATRE)) {
+ return SceneMode.THEATRE;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String stringify(WhiteBalance wb) {
+ switch (wb) {
+ case AUTO:
+ return Camera.Parameters.WHITE_BALANCE_AUTO;
+ case CLOUDY_DAYLIGHT:
+ return Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT;
+ case DAYLIGHT:
+ return Camera.Parameters.WHITE_BALANCE_DAYLIGHT;
+ case FLUORESCENT:
+ return Camera.Parameters.WHITE_BALANCE_FLUORESCENT;
+ case INCANDESCENT:
+ return Camera.Parameters.WHITE_BALANCE_INCANDESCENT;
+ case SHADE:
+ return Camera.Parameters.WHITE_BALANCE_SHADE;
+ case TWILIGHT:
+ return Camera.Parameters.WHITE_BALANCE_TWILIGHT;
+ case WARM_FLUORESCENT:
+ return Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT;
+ }
+ return null;
+ }
+
+ @Override
+ public WhiteBalance whiteBalanceFromString(String val) {
+ if (val.equals(Camera.Parameters.WHITE_BALANCE_AUTO)) {
+ return WhiteBalance.AUTO;
+ } else if (val.equals(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT)) {
+ return WhiteBalance.CLOUDY_DAYLIGHT;
+ } else if (val.equals(Camera.Parameters.WHITE_BALANCE_DAYLIGHT)) {
+ return WhiteBalance.DAYLIGHT;
+ } else if (val.equals(Camera.Parameters.WHITE_BALANCE_FLUORESCENT)) {
+ return WhiteBalance.FLUORESCENT;
+ } else if (val.equals(Camera.Parameters.WHITE_BALANCE_INCANDESCENT)) {
+ return WhiteBalance.INCANDESCENT;
+ } else if (val.equals(Camera.Parameters.WHITE_BALANCE_SHADE)) {
+ return WhiteBalance.SHADE;
+ } else if (val.equals(Camera.Parameters.WHITE_BALANCE_TWILIGHT)) {
+ return WhiteBalance.TWILIGHT;
+ } else if (val.equals(Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT)) {
+ return WhiteBalance.WARM_FLUORESCENT;
+ } else {
+ return null;
+ }
+ }
+ }
+}
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraManagerImpl.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraManagerImpl.java
index a46d37a..9fa7436 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraManagerImpl.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraManagerImpl.java
@@ -362,7 +362,9 @@ class AndroidCameraManagerImpl implements CameraManager {
mCameraState.setState(CAMERA_IDLE);
if (openCallback != null) {
openCallback.onCameraOpened(
- new AndroidCameraProxyImpl(cameraId, mCamera));
+ new AndroidCameraProxyImpl(cameraId, mCamera,
+ new AndroidCameraCapabilities(mParamsToSet))
+ );
}
} else {
if (openCallback != null) {
@@ -399,7 +401,8 @@ class AndroidCameraManagerImpl implements CameraManager {
mCameraState.setState(CAMERA_IDLE);
if (cbForward != null) {
- cbForward.onCameraOpened(new AndroidCameraProxyImpl(cameraId, mCamera));
+ cbForward.onCameraOpened(new AndroidCameraProxyImpl(cameraId, mCamera,
+ new AndroidCameraCapabilities(mParamsToSet)));
}
break;
}
@@ -748,10 +751,13 @@ class AndroidCameraManagerImpl implements CameraManager {
private final int mCameraId;
/* TODO: remove this Camera instance. */
private final Camera mCamera;
+ private final AndroidCameraCapabilities mCapabilities;
- private AndroidCameraProxyImpl(int cameraId, Camera camera) {
+ private AndroidCameraProxyImpl(int cameraId, Camera camera,
+ AndroidCameraCapabilities capabilities) {
mCamera = camera;
mCameraId = cameraId;
+ mCapabilities = capabilities;
}
@Override
@@ -765,6 +771,11 @@ class AndroidCameraManagerImpl implements CameraManager {
}
@Override
+ public CameraCapabilities getCapabilities() {
+ return new AndroidCameraCapabilities(mCapabilities);
+ }
+
+ @Override
public void reconnect(final Handler handler, final CameraOpenCallback cb) {
mDispatchThread.runJob(new Runnable() {
@Override
@@ -1122,7 +1133,6 @@ class AndroidCameraManagerImpl implements CameraManager {
}
});
}
-
}
private static class WaitDoneBundle {
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java b/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java
new file mode 100644
index 0000000..bcc97e5
--- /dev/null
+++ b/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java
@@ -0,0 +1,537 @@
+/*
+ * 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.ex.camera2.portability;
+
+import android.graphics.Point;
+
+import com.android.ex.camera2.portability.debug.Log;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class CameraCapabilities {
+
+ private static Log.Tag TAG = new Log.Tag("CameraCapabilities");
+
+ protected final ArrayList<int[]> mSupportedPreviewFpsRange = new ArrayList<int[]>();
+ protected final ArrayList<Point> mSupportedPreviewSizes = new ArrayList<Point>();
+ protected final TreeSet<Integer> mSupportedPreviewFormats = new TreeSet<Integer>();
+ protected final ArrayList<Point> mSupportedVideoSizes = new ArrayList<Point>();
+ protected final ArrayList<Point> mSupportedPictureSizes = new ArrayList<Point>();
+ protected final TreeSet<Integer> mSupportedPictureFormats = new TreeSet<Integer>();
+ protected final EnumSet<SceneMode> mSupportedSceneModes = EnumSet.noneOf(SceneMode.class);
+ protected final EnumSet<FlashMode> mSupportedFlashModes = EnumSet.noneOf(FlashMode.class);
+ protected final EnumSet<FocusMode> mSupportedFocusModes = EnumSet.noneOf(FocusMode.class);
+ protected final EnumSet<WhiteBalance> mSupportedWhiteBalances =
+ EnumSet.noneOf(WhiteBalance.class);
+ protected final EnumSet<Feature> mSupportedFeatures = EnumSet.noneOf(Feature.class);
+ protected int mMinExposureCompensation;
+ protected int mMaxExposureCompensation;
+ protected float mExposureCompensationStep;
+ protected int mMaxNumOfFacesSupported;
+ protected int mMaxNumOfFocusAreas;
+ protected int mMaxNumOfMeteringArea;
+ private final Stringifier mStringifier;
+
+ // Focus modes.
+ public enum FocusMode {
+ /**
+ * Continuous auto focus mode intended for taking pictures.
+ * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_AUTO}.
+ */
+ AUTO,
+ /**
+ * Continuous auto focus mode intended for taking pictures.
+ * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_CONTINUOUS_PICTURE}.
+ */
+ CONTINUOUS_PICTURE,
+ /**
+ * Continuous auto focus mode intended for video recording.
+ * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_CONTINUOUS_VIDEO}.
+ */
+ CONTINUOUS_VIDEO,
+ /**
+ * Extended depth of field (EDOF).
+ * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_EDOF}.
+ */
+ EXTENDED_DOF,
+ /**
+ * Focus is fixed.
+ * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_FIXED}.
+ */
+ FIXED,
+ /**
+ * Focus is set at infinity.
+ * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_INFINITY}.
+ */
+ INFINITY,
+ /**
+ * Macro (close-up) focus mode.
+ * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_MACRO}.
+ */
+ MACRO,
+ }
+
+ // Flash modes.
+ public enum FlashMode {
+ /**
+ * Flash will be fired automatically when required.
+ * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}.
+ */
+ AUTO,
+ /**
+ * Flash will not be fired.
+ * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}.
+ */
+ OFF,
+ /**
+ * Flash will always be fired during snapshot.
+ * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_ON}.
+ */
+ ON,
+ /**
+ * Constant emission of light during preview, auto-focus and snapshot.
+ * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_TORCH}.
+ */
+ TORCH,
+ /**
+ * Flash will be fired in red-eye reduction mode.
+ * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_RED_EYE}.
+ */
+ RED_EYE,
+ }
+
+ public enum SceneMode {
+ /**
+ * Scene mode is off.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_AUTO}.
+ */
+ AUTO,
+ /**
+ * Take photos of fast moving objects.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_ACTION}.
+ */
+ ACTION,
+ /**
+ * Applications are looking for a barcode.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_BARCODE}.
+ */
+ BARCODE,
+ /**
+ * Take pictures on the beach.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_BEACH}.
+ */
+ BEACH,
+ /**
+ * Capture the naturally warm color of scenes lit by candles.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_CANDLELIGHT}.
+ */
+ CANDLELIGHT,
+ /**
+ * For shooting firework displays.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_FIREWORKS}.
+ */
+ FIREWORKS,
+ /**
+ * Capture a scene using high dynamic range imaging techniques.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_HDR}.
+ */
+ HDR,
+ /**
+ * Take pictures on distant objects.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_LANDSCAPE}.
+ */
+ LANDSCAPE,
+ /**
+ * Take photos at night.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_NIGHT}.
+ */
+ NIGHT,
+ /**
+ * Take people pictures at night.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_NIGHT_PORTRAIT}.
+ */
+ NIGHT_PORTRAIT,
+ /**
+ * Take indoor low-light shot.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_PARTY}.
+ */
+ PARTY,
+ /**
+ * Take people pictures.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_PORTRAIT}.
+ */
+ PORTRAIT,
+ /**
+ * Take pictures on the snow.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_SNOW}.
+ */
+ SNOW,
+ /**
+ * Take photos of fast moving objects.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_SPORTS}.
+ */
+ SPORTS,
+ /**
+ * Avoid blurry pictures (for example, due to hand shake).
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_STEADYPHOTO}.
+ */
+ STEADYPHOTO,
+ /**
+ * Take sunset photos.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_SUNSET}.
+ */
+ SUNSET,
+ /**
+ * Take photos in a theater.
+ * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_THEATRE}.
+ */
+ THEATRE,
+ }
+
+ // White balances.
+ public enum WhiteBalance {
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_AUTO}.
+ */
+ AUTO,
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_CLOUDY_DAYLIGHT}.
+ */
+ CLOUDY_DAYLIGHT,
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_DAYLIGHT}.
+ */
+ DAYLIGHT,
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_FLUORESCENT}.
+ */
+ FLUORESCENT,
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_INCANDESCENT}.
+ */
+ INCANDESCENT,
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_SHADE}.
+ */
+ SHADE,
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_TWILIGHT}.
+ */
+ TWILIGHT,
+ /**
+ * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_WARM_FLUORESCENT}.
+ */
+ WARM_FLUORESCENT,
+ }
+
+ public enum Feature {
+ /**
+ * Support zoom-related methods.
+ */
+ ZOOM,
+ /**
+ * Support for photo capturing during video recording.
+ */
+ VIDEO_SNAPSHOT,
+ /**
+ * Support for focus area settings.
+ */
+ FOCUS_AREA,
+ /**
+ * Support for metering area settings.
+ */
+ METERING_AREA,
+ /**
+ * Support for automatic exposure lock.
+ */
+ AUTO_EXPOSURE_LOCK,
+ /**
+ * Support for automatic white balance lock.
+ */
+ AUTO_WHITE_BALANCE_LOCK,
+ }
+
+ /**
+ * A interface stringifier to convert abstract representations to API
+ * related string representation.
+ */
+ public interface Stringifier {
+ /**
+ * Converts the focus mode to API-related string representation.
+ *
+ * @param focus The focus mode to convert.
+ * @return The string used by the camera framework API to represent the
+ * focus mode.
+ */
+ String stringify(FocusMode focus);
+
+ /**
+ * Converts the API-related string representation of the focus mode to the
+ * abstract representation.
+ *
+ * @param val The string representation.
+ * @return The focus mode represented by the input string.
+ */
+ FocusMode focusModeFromString(String val);
+
+ /**
+ * Converts the flash mode to API-related string representation.
+ *
+ * @param flash The focus mode to convert.
+ * @return The string used by the camera framework API to represent the
+ * flash mode.
+ */
+ String stringify(FlashMode flash);
+
+ /**
+ * Converts the API-related string representation of the flash mode to the
+ * abstract representation.
+ *
+ * @param val The string representation.
+ * @return The flash mode represented by the input string.
+ */
+ FlashMode flashModeFromString(String val);
+
+ /**
+ * Converts the scene mode to API-related string representation.
+ *
+ * @param scene The focus mode to convert.
+ * @return The string used by the camera framework API to represent the
+ * scene mode.
+ */
+ String stringify(SceneMode scene);
+
+ /**
+ * Converts the API-related string representation of the scene mode to the
+ * abstract representation.
+ *
+ * @param val The string representation.
+ * @return The scene mode represented by the input string.
+ */
+ SceneMode sceneModeFromString(String val);
+
+ /**
+ * Converts the white balance to API-related string representation.
+ *
+ * @param wb The focus mode to convert.
+ * @return The string used by the camera framework API to represent the
+ * white balance.
+ */
+ String stringify(WhiteBalance wb);
+
+ /**
+ * Converts the API-related string representation of the white balance to
+ * the abstract representation.
+ *
+ * @param val The string representation.
+ * @return The white balance represented by the input string.
+ */
+ WhiteBalance whiteBalanceFromString(String val);
+ }
+
+ /**
+ * constructor.
+ * @param mStringifier The stringifier used by this instance.
+ */
+ CameraCapabilities(Stringifier mStringifier) {
+ this.mStringifier = mStringifier;
+ }
+
+ /**
+ * Copy constructor.
+ * @param src The source instance.
+ */
+ public CameraCapabilities(CameraCapabilities src) {
+ mSupportedPreviewFpsRange.addAll(src.mSupportedPreviewFpsRange);
+ mSupportedPreviewSizes.addAll(src.mSupportedPreviewSizes);
+ mSupportedPreviewFormats.addAll(src.mSupportedPreviewFormats);
+ mSupportedVideoSizes.addAll(src.mSupportedVideoSizes);
+ mSupportedPictureSizes.addAll(src.mSupportedPictureSizes);
+ mSupportedPictureFormats.addAll(src.mSupportedPictureFormats);
+ mSupportedSceneModes.addAll(src.mSupportedSceneModes);
+ mSupportedFlashModes.addAll(src.mSupportedFlashModes);
+ mSupportedFocusModes.addAll(src.mSupportedFocusModes);
+ mSupportedWhiteBalances.addAll(src.mSupportedWhiteBalances);
+ mSupportedFeatures.addAll(src.mSupportedFeatures);
+ mMaxExposureCompensation = src.mMaxExposureCompensation;
+ mMinExposureCompensation = src.mMinExposureCompensation;
+ mExposureCompensationStep = src.mExposureCompensationStep;
+ mMaxNumOfFacesSupported = src.mMaxNumOfFacesSupported;
+ mMaxNumOfFocusAreas = src.mMaxNumOfFocusAreas;
+ mStringifier = src.mStringifier;
+ }
+
+ /**
+ * @return the supported picture formats. See {@link android.graphics.ImageFormat}.
+ */
+ public Set<Integer> getSupportedPictureFormats() {
+ return new TreeSet<Integer>(mSupportedPictureFormats);
+ }
+
+ /**
+ * Gets the supported preview formats.
+ * @return The supported preview {@link android.graphics.ImageFormat}s.
+ */
+ public Set<Integer> getSupportedPreviewFormats() {
+ return new TreeSet<Integer>(mSupportedPreviewFormats);
+ }
+
+ /**
+ * Gets the supported picture sizes.
+ */
+ public List<Point> getSupportedPictureSizes() {
+ return new ArrayList<Point>(mSupportedPictureSizes);
+ }
+
+
+ /**
+ * @return The supported preview fps (frame-per-second) ranges. The returned
+ * list is sorted by maximum fps then minimum fps in a descending order.
+ * The values are multiplied by 1000.
+ */
+ public final List<int[]> getSupportedPreviewFpsRange() {
+ return new ArrayList<int[]>(mSupportedPreviewFpsRange);
+ }
+
+ /**
+ * @return The supported preview sizes. The width and height are stored in
+ * Point.x and Point.y respectively and the list is sorted by width then
+ * height in a descending order.
+ */
+ public final List<Point> getSupportedPreviewSizes() {
+ return new ArrayList<Point>(mSupportedPreviewSizes);
+ }
+
+ /**
+ * @return The supported video frame sizes that can be used by MediaRecorder.
+ * The width and height are stored in Point.x and Point.y respectively and
+ * the list is sorted by width then height in a descending order.
+ */
+ public final List<Point> getSupportedVideoSizes() {
+ return new ArrayList<Point>(mSupportedVideoSizes);
+ }
+
+ /**
+ * @return The supported scene modes.
+ */
+ public final Set<SceneMode> getSupportedSceneModes() {
+ return new HashSet<SceneMode>(mSupportedSceneModes);
+ }
+
+ /**
+ * @return Whether the scene mode is supported.
+ */
+ public final boolean supports(SceneMode scene) {
+ return (scene != null && mSupportedSceneModes.contains(scene));
+ }
+
+ /**
+ * @return The supported flash modes.
+ */
+ public final Set<FlashMode> getSupportedFlashModes() {
+ return new HashSet<FlashMode>(mSupportedFlashModes);
+ }
+
+ /**
+ * @return Whether the flash mode is supported.
+ */
+ public final boolean supports(FlashMode flash) {
+ return (flash != null && mSupportedFlashModes.contains(flash));
+ }
+
+ /**
+ * @return The supported focus modes.
+ */
+ public final Set<FocusMode> getSupportedFocusModes() {
+ return new HashSet<FocusMode>(mSupportedFocusModes);
+ }
+
+ /**
+ * @return Whether the focus mode is supported.
+ */
+ public final boolean supports(FocusMode focus) {
+ return (focus != null && mSupportedFocusModes.contains(focus));
+ }
+
+ /**
+ * @return The supported white balanceas.
+ */
+ public final Set<WhiteBalance> getSupportedWhiteBalance() {
+ return new HashSet<WhiteBalance>(mSupportedWhiteBalances);
+ }
+
+ /**
+ * @return Whether the white balance is supported.
+ */
+ public boolean supports(WhiteBalance wb) {
+ return (wb != null && mSupportedWhiteBalances.contains(wb));
+ }
+
+ public final Set<Feature> getSupportedFeature() {
+ return new HashSet<Feature>(mSupportedFeatures);
+ }
+
+ public boolean supports(Feature ft) {
+ return (ft != null && mSupportedFeatures.contains(ft));
+ }
+
+ /**
+ * @return The min exposure compensation index. The EV is the compensation
+ * index multiplied by the step value. If unsupported, both this method and
+ * {@link #getMaxExposureCompensation()} return 0.
+ */
+ public final int getMinExposureCompensation() {
+ return mMinExposureCompensation;
+ }
+
+ /**
+ * @return The max exposure compensation index. The EV is the compensation
+ * index multiplied by the step value. If unsupported, both this method and
+ * {@link #getMinExposureCompensation()} return 0.
+ */
+ public final int getMaxExposureCompensation() {
+ return mMaxExposureCompensation;
+ }
+
+ /**
+ * @return The exposure compensation step. The EV is the compensation index
+ * multiplied by the step value.
+ */
+ public final float getExposureCompensationStep() {
+ return mExposureCompensationStep;
+ }
+
+ /**
+ * @return The max number of faces supported by the face detection. 0 if
+ * unsupported.
+ */
+ public final int getMaxNumOfFacesSupported() {
+ return mMaxNumOfFacesSupported;
+ }
+
+ /**
+ * @return The stringifier used by this instance.
+ */
+ public Stringifier getStringifier() {
+ return mStringifier;
+ }
+}
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilitiesFactory.java b/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilitiesFactory.java
new file mode 100644
index 0000000..80765d3
--- /dev/null
+++ b/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilitiesFactory.java
@@ -0,0 +1,34 @@
+/*
+ * 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.ex.camera2.portability;
+
+import android.hardware.Camera;
+
+import com.android.ex.camera2.portability.debug.Log;
+
+public class CameraCapabilitiesFactory {
+
+ private static Log.Tag TAG = new Log.Tag("CapabilitiesFactory");
+
+ public static CameraCapabilities createFrom(Camera.Parameters p) {
+ if (p == null) {
+ Log.w(TAG, "Null parameter passed in.");
+ return null;
+ }
+ return new AndroidCameraCapabilities(p);
+ }
+}
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/CameraManager.java b/camera2/portability/src/com/android/ex/camera2/portability/CameraManager.java
index a7bddcb..b5707b6 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/CameraManager.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/CameraManager.java
@@ -20,7 +20,6 @@ import android.annotation.TargetApi;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.OnZoomChangeListener;
-import android.hardware.Camera.Parameters;
import android.os.Build;
import android.os.Handler;
import android.view.SurfaceHolder;
@@ -197,13 +196,17 @@ public interface CameraManager {
public android.hardware.Camera getCamera();
/**
- * Returns the camera ID associated to by this
+ * @return The camera ID associated to by this
* {@link CameraManager.CameraProxy}.
- * @return
*/
public int getCameraId();
/**
+ * @return The camera capabilities.
+ */
+ public CameraCapabilities getCapabilities();
+
+ /**
* Reconnects to the camera device. On success, the camera device will
* be returned through {@link CameraManager
* .CameraOpenCallback#onCameraOpened(com.android.camera.cameradevice.CameraManager
@@ -392,7 +395,7 @@ public interface CameraManager {
*
* @param params The camera parameters to use.
*/
- public void setParameters(Parameters params);
+ public void setParameters(Camera.Parameters params);
/**
* Gets the current camera parameters synchronously. This method is
@@ -400,7 +403,7 @@ public interface CameraManager {
* the parameters. If the parameters are already cached, it returns
* immediately.
*/
- public Parameters getParameters();
+ public Camera.Parameters getParameters();
/**
* Forces {@code CameraProxy} to update the cached version of the camera