1 /* 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.webrtc; 12 13 import android.os.SystemClock; 14 import android.support.annotation.Nullable; 15 import java.util.ArrayList; 16 import java.util.List; 17 import org.webrtc.CameraEnumerationAndroid.CaptureFormat; 18 19 @SuppressWarnings("deprecation") 20 public class Camera1Enumerator implements CameraEnumerator { 21 private final static String TAG = "Camera1Enumerator"; 22 // Each entry contains the supported formats for corresponding camera index. The formats for all 23 // cameras are enumerated on the first call to getSupportedFormats(), and cached for future 24 // reference. 25 private static List<List<CaptureFormat>> cachedSupportedFormats; 26 27 private final boolean captureToTexture; 28 Camera1Enumerator()29 public Camera1Enumerator() { 30 this(true /* captureToTexture */); 31 } 32 Camera1Enumerator(boolean captureToTexture)33 public Camera1Enumerator(boolean captureToTexture) { 34 this.captureToTexture = captureToTexture; 35 } 36 37 // Returns device names that can be used to create a new VideoCapturerAndroid. 38 @Override getDeviceNames()39 public String[] getDeviceNames() { 40 ArrayList<String> namesList = new ArrayList<>(); 41 for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) { 42 String name = getDeviceName(i); 43 if (name != null) { 44 namesList.add(name); 45 Logging.d(TAG, "Index: " + i + ". " + name); 46 } else { 47 Logging.e(TAG, "Index: " + i + ". Failed to query camera name."); 48 } 49 } 50 String[] namesArray = new String[namesList.size()]; 51 return namesList.toArray(namesArray); 52 } 53 54 @Override isFrontFacing(String deviceName)55 public boolean isFrontFacing(String deviceName) { 56 android.hardware.Camera.CameraInfo info = getCameraInfo(getCameraIndex(deviceName)); 57 return info != null && info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT; 58 } 59 60 @Override isBackFacing(String deviceName)61 public boolean isBackFacing(String deviceName) { 62 android.hardware.Camera.CameraInfo info = getCameraInfo(getCameraIndex(deviceName)); 63 return info != null && info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK; 64 } 65 66 @Override getSupportedFormats(String deviceName)67 public List<CaptureFormat> getSupportedFormats(String deviceName) { 68 return getSupportedFormats(getCameraIndex(deviceName)); 69 } 70 71 @Override createCapturer( String deviceName, CameraVideoCapturer.CameraEventsHandler eventsHandler)72 public CameraVideoCapturer createCapturer( 73 String deviceName, CameraVideoCapturer.CameraEventsHandler eventsHandler) { 74 return new Camera1Capturer(deviceName, eventsHandler, captureToTexture); 75 } 76 getCameraInfo(int index)77 private static @Nullable android.hardware.Camera.CameraInfo getCameraInfo(int index) { 78 android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); 79 try { 80 android.hardware.Camera.getCameraInfo(index, info); 81 } catch (Exception e) { 82 Logging.e(TAG, "getCameraInfo failed on index " + index, e); 83 return null; 84 } 85 return info; 86 } 87 getSupportedFormats(int cameraId)88 static synchronized List<CaptureFormat> getSupportedFormats(int cameraId) { 89 if (cachedSupportedFormats == null) { 90 cachedSupportedFormats = new ArrayList<List<CaptureFormat>>(); 91 for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) { 92 cachedSupportedFormats.add(enumerateFormats(i)); 93 } 94 } 95 return cachedSupportedFormats.get(cameraId); 96 } 97 enumerateFormats(int cameraId)98 private static List<CaptureFormat> enumerateFormats(int cameraId) { 99 Logging.d(TAG, "Get supported formats for camera index " + cameraId + "."); 100 final long startTimeMs = SystemClock.elapsedRealtime(); 101 final android.hardware.Camera.Parameters parameters; 102 android.hardware.Camera camera = null; 103 try { 104 Logging.d(TAG, "Opening camera with index " + cameraId); 105 camera = android.hardware.Camera.open(cameraId); 106 parameters = camera.getParameters(); 107 } catch (RuntimeException e) { 108 Logging.e(TAG, "Open camera failed on camera index " + cameraId, e); 109 return new ArrayList<CaptureFormat>(); 110 } finally { 111 if (camera != null) { 112 camera.release(); 113 } 114 } 115 116 final List<CaptureFormat> formatList = new ArrayList<CaptureFormat>(); 117 try { 118 int minFps = 0; 119 int maxFps = 0; 120 final List<int[]> listFpsRange = parameters.getSupportedPreviewFpsRange(); 121 if (listFpsRange != null) { 122 // getSupportedPreviewFpsRange() returns a sorted list. Take the fps range 123 // corresponding to the highest fps. 124 final int[] range = listFpsRange.get(listFpsRange.size() - 1); 125 minFps = range[android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX]; 126 maxFps = range[android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX]; 127 } 128 for (android.hardware.Camera.Size size : parameters.getSupportedPreviewSizes()) { 129 formatList.add(new CaptureFormat(size.width, size.height, minFps, maxFps)); 130 } 131 } catch (Exception e) { 132 Logging.e(TAG, "getSupportedFormats() failed on camera index " + cameraId, e); 133 } 134 135 final long endTimeMs = SystemClock.elapsedRealtime(); 136 Logging.d(TAG, "Get supported formats for camera index " + cameraId + " done." 137 + " Time spent: " + (endTimeMs - startTimeMs) + " ms."); 138 return formatList; 139 } 140 141 // Convert from android.hardware.Camera.Size to Size. convertSizes(List<android.hardware.Camera.Size> cameraSizes)142 static List<Size> convertSizes(List<android.hardware.Camera.Size> cameraSizes) { 143 final List<Size> sizes = new ArrayList<Size>(); 144 for (android.hardware.Camera.Size size : cameraSizes) { 145 sizes.add(new Size(size.width, size.height)); 146 } 147 return sizes; 148 } 149 150 // Convert from int[2] to CaptureFormat.FramerateRange. convertFramerates(List<int[]> arrayRanges)151 static List<CaptureFormat.FramerateRange> convertFramerates(List<int[]> arrayRanges) { 152 final List<CaptureFormat.FramerateRange> ranges = new ArrayList<CaptureFormat.FramerateRange>(); 153 for (int[] range : arrayRanges) { 154 ranges.add(new CaptureFormat.FramerateRange( 155 range[android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX], 156 range[android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX])); 157 } 158 return ranges; 159 } 160 161 // Returns the camera index for camera with name |deviceName|, or throws IllegalArgumentException 162 // if no such camera can be found. getCameraIndex(String deviceName)163 static int getCameraIndex(String deviceName) { 164 Logging.d(TAG, "getCameraIndex: " + deviceName); 165 for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) { 166 if (deviceName.equals(getDeviceName(i))) { 167 return i; 168 } 169 } 170 throw new IllegalArgumentException("No such camera: " + deviceName); 171 } 172 173 // Returns the name of the camera with camera index. Returns null if the 174 // camera can not be used. getDeviceName(int index)175 static @Nullable String getDeviceName(int index) { 176 android.hardware.Camera.CameraInfo info = getCameraInfo(index); 177 if (info == null) { 178 return null; 179 } 180 181 String facing = 182 (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) ? "front" : "back"; 183 return "Camera " + index + ", Facing " + facing + ", Orientation " + info.orientation; 184 } 185 } 186