/* * 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 androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; 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> 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 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 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 getSupportedFormats(int cameraId) { if (cachedSupportedFormats == null) { cachedSupportedFormats = new ArrayList>(); for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) { cachedSupportedFormats.add(enumerateFormats(i)); } } return cachedSupportedFormats.get(cameraId); } private static List 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(); } finally { if (camera != null) { camera.release(); } } final List formatList = new ArrayList(); try { int minFps = 0; int maxFps = 0; final List 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 convertSizes(List cameraSizes) { final List sizes = new ArrayList(); 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 convertFramerates(List arrayRanges) { final List ranges = new ArrayList(); 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; } }