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
17package com.android.ex.camera2.portability;
18
19import android.hardware.Camera;
20
21import com.android.ex.camera2.portability.debug.Log;
22
23import java.util.Collections;
24import java.util.Comparator;
25import java.util.List;
26
27/**
28 * The subclass of {@link CameraCapabilities} for Android Camera 1 API.
29 */
30class AndroidCameraCapabilities extends CameraCapabilities {
31
32    private static Log.Tag TAG = new Log.Tag("AndCamCapabs");
33
34    /** Conversion from ratios to percentages. */
35    public static final float ZOOM_MULTIPLIER = 100f;
36
37    private FpsComparator mFpsComparator = new FpsComparator();
38    private SizeComparator mSizeComparator = new SizeComparator();
39
40    AndroidCameraCapabilities(Camera.Parameters p) {
41        super(new Stringifier());
42        mMaxExposureCompensation = p.getMaxExposureCompensation();
43        mMinExposureCompensation = p.getMinExposureCompensation();
44        mExposureCompensationStep = p.getExposureCompensationStep();
45        mMaxNumOfFacesSupported = p.getMaxNumDetectedFaces();
46        mMaxNumOfMeteringArea = p.getMaxNumMeteringAreas();
47        mPreferredPreviewSizeForVideo = new Size(p.getPreferredPreviewSizeForVideo());
48        mSupportedPreviewFormats.addAll(p.getSupportedPreviewFormats());
49        mSupportedPhotoFormats.addAll(p.getSupportedPictureFormats());
50        mHorizontalViewAngle = p.getHorizontalViewAngle();
51        mVerticalViewAngle = p.getVerticalViewAngle();
52        buildPreviewFpsRange(p);
53        buildPreviewSizes(p);
54        buildVideoSizes(p);
55        buildPictureSizes(p);
56        buildSceneModes(p);
57        buildFlashModes(p);
58        buildFocusModes(p);
59        buildWhiteBalances(p);
60
61        if (p.isZoomSupported()) {
62            mMaxZoomRatio = p.getZoomRatios().get(p.getMaxZoom()) / ZOOM_MULTIPLIER;
63            mSupportedFeatures.add(Feature.ZOOM);
64        }
65        if (p.isVideoSnapshotSupported()) {
66            mSupportedFeatures.add(Feature.VIDEO_SNAPSHOT);
67        }
68        if (p.isAutoExposureLockSupported()) {
69            mSupportedFeatures.add(Feature.AUTO_EXPOSURE_LOCK);
70        }
71        if (p.isAutoWhiteBalanceLockSupported()) {
72            mSupportedFeatures.add(Feature.AUTO_WHITE_BALANCE_LOCK);
73        }
74        if (supports(FocusMode.AUTO)) {
75            mMaxNumOfFocusAreas = p.getMaxNumFocusAreas();
76            if (mMaxNumOfFocusAreas > 0) {
77                mSupportedFeatures.add(Feature.FOCUS_AREA);
78            }
79        }
80        if (mMaxNumOfMeteringArea > 0) {
81            mSupportedFeatures.add(Feature.METERING_AREA);
82        }
83    }
84
85    AndroidCameraCapabilities(AndroidCameraCapabilities src) {
86        super(src);
87    }
88
89    private void buildPreviewFpsRange(Camera.Parameters p) {
90        List<int[]> supportedPreviewFpsRange = p.getSupportedPreviewFpsRange();
91        if (supportedPreviewFpsRange != null) {
92            mSupportedPreviewFpsRange.addAll(supportedPreviewFpsRange);
93        }
94        Collections.sort(mSupportedPreviewFpsRange, mFpsComparator);
95    }
96
97    private void buildPreviewSizes(Camera.Parameters p) {
98        List<Camera.Size> supportedPreviewSizes = p.getSupportedPreviewSizes();
99        if (supportedPreviewSizes != null) {
100            for (Camera.Size s : supportedPreviewSizes) {
101                mSupportedPreviewSizes.add(new Size(s.width, s.height));
102            }
103        }
104        Collections.sort(mSupportedPreviewSizes, mSizeComparator);
105    }
106
107    private void buildVideoSizes(Camera.Parameters p) {
108        List<Camera.Size> supportedVideoSizes = p.getSupportedVideoSizes();
109        if (supportedVideoSizes != null) {
110            for (Camera.Size s : supportedVideoSizes) {
111                mSupportedVideoSizes.add(new Size(s.width, s.height));
112            }
113        }
114        Collections.sort(mSupportedVideoSizes, mSizeComparator);
115    }
116
117    private void buildPictureSizes(Camera.Parameters p) {
118        List<Camera.Size> supportedPictureSizes = p.getSupportedPictureSizes();
119        if (supportedPictureSizes != null) {
120            for (Camera.Size s : supportedPictureSizes) {
121                mSupportedPhotoSizes.add(new Size(s.width, s.height));
122            }
123        }
124        Collections.sort(mSupportedPhotoSizes, mSizeComparator);
125
126    }
127
128    private void buildSceneModes(Camera.Parameters p) {
129        List<String> supportedSceneModes = p.getSupportedSceneModes();
130        if (supportedSceneModes != null) {
131            for (String scene : supportedSceneModes) {
132                if (Camera.Parameters.SCENE_MODE_AUTO.equals(scene)) {
133                    mSupportedSceneModes.add(SceneMode.AUTO);
134                } else if (Camera.Parameters.SCENE_MODE_ACTION.equals(scene)) {
135                    mSupportedSceneModes.add(SceneMode.ACTION);
136                } else if (Camera.Parameters.SCENE_MODE_BARCODE.equals(scene)) {
137                    mSupportedSceneModes.add(SceneMode.BARCODE);
138                } else if (Camera.Parameters.SCENE_MODE_BEACH.equals(scene)) {
139                    mSupportedSceneModes.add(SceneMode.BEACH);
140                } else if (Camera.Parameters.SCENE_MODE_CANDLELIGHT.equals(scene)) {
141                    mSupportedSceneModes.add(SceneMode.CANDLELIGHT);
142                } else if (Camera.Parameters.SCENE_MODE_FIREWORKS.equals(scene)) {
143                    mSupportedSceneModes.add(SceneMode.FIREWORKS);
144                } else if (Camera.Parameters.SCENE_MODE_HDR.equals(scene)) {
145                    mSupportedSceneModes.add(SceneMode.HDR);
146                } else if (Camera.Parameters.SCENE_MODE_LANDSCAPE.equals(scene)) {
147                    mSupportedSceneModes.add(SceneMode.LANDSCAPE);
148                } else if (Camera.Parameters.SCENE_MODE_NIGHT.equals(scene)) {
149                    mSupportedSceneModes.add(SceneMode.NIGHT);
150                } else if (Camera.Parameters.SCENE_MODE_NIGHT_PORTRAIT.equals(scene)) {
151                    mSupportedSceneModes.add(SceneMode.NIGHT_PORTRAIT);
152                } else if (Camera.Parameters.SCENE_MODE_PARTY.equals(scene)) {
153                    mSupportedSceneModes.add(SceneMode.PARTY);
154                } else if (Camera.Parameters.SCENE_MODE_PORTRAIT.equals(scene)) {
155                    mSupportedSceneModes.add(SceneMode.PORTRAIT);
156                } else if (Camera.Parameters.SCENE_MODE_SNOW.equals(scene)) {
157                    mSupportedSceneModes.add(SceneMode.SNOW);
158                } else if (Camera.Parameters.SCENE_MODE_SPORTS.equals(scene)) {
159                    mSupportedSceneModes.add(SceneMode.SPORTS);
160                } else if (Camera.Parameters.SCENE_MODE_STEADYPHOTO.equals(scene)) {
161                    mSupportedSceneModes.add(SceneMode.STEADYPHOTO);
162                } else if (Camera.Parameters.SCENE_MODE_SUNSET.equals(scene)) {
163                    mSupportedSceneModes.add(SceneMode.SUNSET);
164                } else if (Camera.Parameters.SCENE_MODE_THEATRE.equals(scene)) {
165                    mSupportedSceneModes.add(SceneMode.THEATRE);
166                }
167            }
168        }
169    }
170
171    private void buildFlashModes(Camera.Parameters p) {
172        List<String> supportedFlashModes = p.getSupportedFlashModes();
173        if (supportedFlashModes == null) {
174            // Camera 1 will return NULL if no flash mode is supported.
175            mSupportedFlashModes.add(FlashMode.NO_FLASH);
176        } else {
177            for (String flash : supportedFlashModes) {
178                if (Camera.Parameters.FLASH_MODE_AUTO.equals(flash)) {
179                    mSupportedFlashModes.add(FlashMode.AUTO);
180                } else if (Camera.Parameters.FLASH_MODE_OFF.equals(flash)) {
181                    mSupportedFlashModes.add(FlashMode.OFF);
182                } else if (Camera.Parameters.FLASH_MODE_ON.equals(flash)) {
183                    mSupportedFlashModes.add(FlashMode.ON);
184                } else if (Camera.Parameters.FLASH_MODE_RED_EYE.equals(flash)) {
185                    mSupportedFlashModes.add(FlashMode.RED_EYE);
186                } else if (Camera.Parameters.FLASH_MODE_TORCH.equals(flash)) {
187                    mSupportedFlashModes.add(FlashMode.TORCH);
188                }
189            }
190        }
191    }
192
193    private void buildFocusModes(Camera.Parameters p) {
194        List<String> supportedFocusModes = p.getSupportedFocusModes();
195        if (supportedFocusModes != null) {
196            for (String focus : supportedFocusModes) {
197                if (Camera.Parameters.FOCUS_MODE_AUTO.equals(focus)) {
198                    mSupportedFocusModes.add(FocusMode.AUTO);
199                } else if (Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(focus)) {
200                    mSupportedFocusModes.add(FocusMode.CONTINUOUS_PICTURE);
201                } else if (Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO.equals(focus)) {
202                    mSupportedFocusModes.add(FocusMode.CONTINUOUS_VIDEO);
203                } else if (Camera.Parameters.FOCUS_MODE_EDOF.equals(focus)) {
204                    mSupportedFocusModes.add(FocusMode.EXTENDED_DOF);
205                } else if (Camera.Parameters.FOCUS_MODE_FIXED.equals(focus)) {
206                    mSupportedFocusModes.add(FocusMode.FIXED);
207                } else if (Camera.Parameters.FOCUS_MODE_INFINITY.equals(focus)) {
208                    mSupportedFocusModes.add(FocusMode.INFINITY);
209                } else if (Camera.Parameters.FOCUS_MODE_MACRO.equals(focus)) {
210                    mSupportedFocusModes.add(FocusMode.MACRO);
211                }
212            }
213        }
214    }
215
216    private void buildWhiteBalances(Camera.Parameters p) {
217        List<String> supportedWhiteBalances = p.getSupportedWhiteBalance();
218        if (supportedWhiteBalances != null) {
219            for (String wb : supportedWhiteBalances) {
220                if (Camera.Parameters.WHITE_BALANCE_AUTO.equals(wb)) {
221                    mSupportedWhiteBalances.add(WhiteBalance.AUTO);
222                } else if (Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT.equals(wb)) {
223                    mSupportedWhiteBalances.add(WhiteBalance.CLOUDY_DAYLIGHT);
224                } else if (Camera.Parameters.WHITE_BALANCE_DAYLIGHT.equals(wb)) {
225                    mSupportedWhiteBalances.add(WhiteBalance.DAYLIGHT);
226                } else if (Camera.Parameters.WHITE_BALANCE_FLUORESCENT.equals(wb)) {
227                    mSupportedWhiteBalances.add(WhiteBalance.FLUORESCENT);
228                } else if (Camera.Parameters.WHITE_BALANCE_INCANDESCENT.equals(wb)) {
229                    mSupportedWhiteBalances.add(WhiteBalance.INCANDESCENT);
230                } else if (Camera.Parameters.WHITE_BALANCE_SHADE.equals(wb)) {
231                    mSupportedWhiteBalances.add(WhiteBalance.SHADE);
232                } else if (Camera.Parameters.WHITE_BALANCE_TWILIGHT.equals(wb)) {
233                    mSupportedWhiteBalances.add(WhiteBalance.TWILIGHT);
234                } else if (Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT.equals(wb)) {
235                    mSupportedWhiteBalances.add(WhiteBalance.WARM_FLUORESCENT);
236                }
237            }
238        }
239    }
240
241    private static class FpsComparator implements Comparator<int[]> {
242        @Override
243        public int compare(int[] fps1, int[] fps2) {
244            return (fps1[0] == fps2[0] ? fps1[1] - fps2[1] : fps1[0] - fps2[0]);
245        }
246    }
247
248    private static class SizeComparator implements Comparator<Size> {
249
250        @Override
251        public int compare(Size size1, Size size2) {
252            return (size1.width() == size2.width() ? size1.height() - size2.height() :
253                    size1.width() - size2.width());
254        }
255    }
256}
257