| /* | |
| * Copyright 2015 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| package org.webrtc; | |
| import android.os.SystemClock; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| import javax.annotation.Nullable; | |
| import org.webrtc.CameraEnumerationAndroid.CaptureFormat; | |
| @SuppressWarnings("deprecation") | |
| public class Camera1Enumerator implements CameraEnumerator { | |
| private final static String TAG = "Camera1Enumerator"; | |
| // Each entry contains the supported formats for corresponding camera index. The formats for all | |
| // cameras are enumerated on the first call to getSupportedFormats(), and cached for future | |
| // reference. | |
| private static List<List<CaptureFormat>> cachedSupportedFormats; | |
| private final boolean captureToTexture; | |
| public Camera1Enumerator() { | |
| this(true /* captureToTexture */); | |
| } | |
| public Camera1Enumerator(boolean captureToTexture) { | |
| this.captureToTexture = captureToTexture; | |
| } | |
| // Returns device names that can be used to create a new VideoCapturerAndroid. | |
| @Override | |
| public String[] getDeviceNames() { | |
| ArrayList<String> namesList = new ArrayList<>(); | |
| for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) { | |
| String name = getDeviceName(i); | |
| if (name != null) { | |
| namesList.add(name); | |
| Logging.d(TAG, "Index: " + i + ". " + name); | |
| } else { | |
| Logging.e(TAG, "Index: " + i + ". Failed to query camera name."); | |
| } | |
| } | |
| String[] namesArray = new String[namesList.size()]; | |
| return namesList.toArray(namesArray); | |
| } | |
| @Override | |
| public boolean isFrontFacing(String deviceName) { | |
| android.hardware.Camera.CameraInfo info = getCameraInfo(getCameraIndex(deviceName)); | |
| return info != null && info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT; | |
| } | |
| @Override | |
| public boolean isBackFacing(String deviceName) { | |
| android.hardware.Camera.CameraInfo info = getCameraInfo(getCameraIndex(deviceName)); | |
| return info != null && info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK; | |
| } | |
| @Override | |
| public List<CaptureFormat> getSupportedFormats(String deviceName) { | |
| return getSupportedFormats(getCameraIndex(deviceName)); | |
| } | |
| @Override | |
| public CameraVideoCapturer createCapturer( | |
| String deviceName, CameraVideoCapturer.CameraEventsHandler eventsHandler) { | |
| return new Camera1Capturer(deviceName, eventsHandler, captureToTexture); | |
| } | |
| private static @Nullable android.hardware.Camera.CameraInfo getCameraInfo(int index) { | |
| android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); | |
| try { | |
| android.hardware.Camera.getCameraInfo(index, info); | |
| } catch (Exception e) { | |
| Logging.e(TAG, "getCameraInfo failed on index " + index, e); | |
| return null; | |
| } | |
| return info; | |
| } | |
| static synchronized List<CaptureFormat> getSupportedFormats(int cameraId) { | |
| if (cachedSupportedFormats == null) { | |
| cachedSupportedFormats = new ArrayList<List<CaptureFormat>>(); | |
| for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) { | |
| cachedSupportedFormats.add(enumerateFormats(i)); | |
| } | |
| } | |
| return cachedSupportedFormats.get(cameraId); | |
| } | |
| private static List<CaptureFormat> enumerateFormats(int cameraId) { | |
| Logging.d(TAG, "Get supported formats for camera index " + cameraId + "."); | |
| final long startTimeMs = SystemClock.elapsedRealtime(); | |
| final android.hardware.Camera.Parameters parameters; | |
| android.hardware.Camera camera = null; | |
| try { | |
| Logging.d(TAG, "Opening camera with index " + cameraId); | |
| camera = android.hardware.Camera.open(cameraId); | |
| parameters = camera.getParameters(); | |
| } catch (RuntimeException e) { | |
| Logging.e(TAG, "Open camera failed on camera index " + cameraId, e); | |
| return new ArrayList<CaptureFormat>(); | |
| } finally { | |
| if (camera != null) { | |
| camera.release(); | |
| } | |
| } | |
| final List<CaptureFormat> formatList = new ArrayList<CaptureFormat>(); | |
| try { | |
| int minFps = 0; | |
| int maxFps = 0; | |
| final List<int[]> listFpsRange = parameters.getSupportedPreviewFpsRange(); | |
| if (listFpsRange != null) { | |
| // getSupportedPreviewFpsRange() returns a sorted list. Take the fps range | |
| // corresponding to the highest fps. | |
| final int[] range = listFpsRange.get(listFpsRange.size() - 1); | |
| minFps = range[android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX]; | |
| maxFps = range[android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX]; | |
| } | |
| for (android.hardware.Camera.Size size : parameters.getSupportedPreviewSizes()) { | |
| formatList.add(new CaptureFormat(size.width, size.height, minFps, maxFps)); | |
| } | |
| } catch (Exception e) { | |
| Logging.e(TAG, "getSupportedFormats() failed on camera index " + cameraId, e); | |
| } | |
| final long endTimeMs = SystemClock.elapsedRealtime(); | |
| Logging.d(TAG, "Get supported formats for camera index " + cameraId + " done." | |
| + " Time spent: " + (endTimeMs - startTimeMs) + " ms."); | |
| return formatList; | |
| } | |
| // Convert from android.hardware.Camera.Size to Size. | |
| static List<Size> convertSizes(List<android.hardware.Camera.Size> cameraSizes) { | |
| final List<Size> sizes = new ArrayList<Size>(); | |
| for (android.hardware.Camera.Size size : cameraSizes) { | |
| sizes.add(new Size(size.width, size.height)); | |
| } | |
| return sizes; | |
| } | |
| // Convert from int[2] to CaptureFormat.FramerateRange. | |
| static List<CaptureFormat.FramerateRange> convertFramerates(List<int[]> arrayRanges) { | |
| final List<CaptureFormat.FramerateRange> ranges = new ArrayList<CaptureFormat.FramerateRange>(); | |
| for (int[] range : arrayRanges) { | |
| ranges.add(new CaptureFormat.FramerateRange( | |
| range[android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX], | |
| range[android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX])); | |
| } | |
| return ranges; | |
| } | |
| // Returns the camera index for camera with name |deviceName|, or throws IllegalArgumentException | |
| // if no such camera can be found. | |
| static int getCameraIndex(String deviceName) { | |
| Logging.d(TAG, "getCameraIndex: " + deviceName); | |
| for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) { | |
| if (deviceName.equals(getDeviceName(i))) { | |
| return i; | |
| } | |
| } | |
| throw new IllegalArgumentException("No such camera: " + deviceName); | |
| } | |
| // Returns the name of the camera with camera index. Returns null if the | |
| // camera can not be used. | |
| static @Nullable String getDeviceName(int index) { | |
| android.hardware.Camera.CameraInfo info = getCameraInfo(index); | |
| if (info == null) { | |
| return null; | |
| } | |
| String facing = | |
| (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) ? "front" : "back"; | |
| return "Camera " + index + ", Facing " + facing + ", Orientation " + info.orientation; | |
| } | |
| } |