Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 package org.webrtc; | 11 package org.webrtc; |
| 12 | 12 |
| 13 import android.annotation.TargetApi; | 13 import android.annotation.TargetApi; |
| 14 import android.content.Context; | 14 import android.content.Context; |
| 15 | 15 |
| 16 import android.graphics.ImageFormat; | 16 import android.graphics.ImageFormat; |
| 17 import android.graphics.SurfaceTexture; | |
| 18 import android.hardware.camera2.CameraAccessException; | |
| 17 import android.hardware.camera2.CameraCharacteristics; | 19 import android.hardware.camera2.CameraCharacteristics; |
| 18 import android.hardware.camera2.CameraManager; | 20 import android.hardware.camera2.CameraManager; |
| 21 import android.hardware.camera2.CameraMetadata; | |
| 19 import android.hardware.camera2.params.StreamConfigurationMap; | 22 import android.hardware.camera2.params.StreamConfigurationMap; |
| 20 import android.os.Build; | 23 import android.os.Build; |
| 21 import android.os.SystemClock; | 24 import android.os.SystemClock; |
| 22 import android.util.Range; | 25 import android.util.Range; |
| 23 import android.util.Size; | |
| 24 | 26 |
| 25 import org.webrtc.CameraEnumerationAndroid.CaptureFormat; | 27 import org.webrtc.CameraEnumerationAndroid.CaptureFormat; |
| 26 import org.webrtc.Logging; | 28 import org.webrtc.Logging; |
| 27 | 29 |
| 28 import java.util.ArrayList; | 30 import java.util.ArrayList; |
| 29 import java.util.HashMap; | 31 import java.util.HashMap; |
| 30 import java.util.List; | 32 import java.util.List; |
| 31 import java.util.Map; | 33 import java.util.Map; |
| 32 | 34 |
| 33 @TargetApi(21) | 35 @TargetApi(21) |
| 34 public class Camera2Enumerator { | 36 public class Camera2Enumerator implements CameraEnumerator { |
| 35 private final static String TAG = "Camera2Enumerator"; | 37 private final static String TAG = "Camera2Enumerator"; |
| 36 private final static double NANO_SECONDS_PER_SECOND = 1.0e9; | 38 private final static double NANO_SECONDS_PER_SECOND = 1.0e9; |
| 37 | 39 |
| 38 // Each entry contains the supported formats for a given camera index. The for mats are enumerated | 40 // Each entry contains the supported formats for a given camera index. The for mats are enumerated |
| 39 // lazily in getSupportedFormats(), and cached for future reference. | 41 // lazily in getSupportedFormats(), and cached for future reference. |
| 40 private static final Map<String, List<CaptureFormat>> cachedSupportedFormats = | 42 private static final Map<String, List<CaptureFormat>> cachedSupportedFormats = |
| 41 new HashMap<String, List<CaptureFormat>>(); | 43 new HashMap<String, List<CaptureFormat>>(); |
| 42 | 44 |
| 45 final Context context; | |
| 46 final CameraManager cameraManager; | |
| 47 | |
| 48 public Camera2Enumerator(Context context) { | |
| 49 this.context = context; | |
| 50 this.cameraManager = (CameraManager) context.getSystemService(Context.CAMERA _SERVICE); | |
| 51 } | |
| 52 | |
| 53 public String[] getDeviceNames() { | |
| 54 try { | |
| 55 return cameraManager.getCameraIdList(); | |
| 56 } catch (CameraAccessException e) { | |
| 57 Logging.e(TAG, "Camera access exception: " + e); | |
| 58 return new String[] {}; | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 public boolean isFrontFacing(String deviceName) { | |
| 63 CameraCharacteristics characteristics | |
| 64 = getCameraCharacteristics(deviceName); | |
| 65 | |
| 66 return characteristics != null | |
| 67 && characteristics.get(CameraCharacteristics.LENS_FACING) | |
| 68 == CameraMetadata.LENS_FACING_FRONT; | |
| 69 } | |
| 70 | |
| 71 public boolean isBackFacing(String deviceName) { | |
| 72 CameraCharacteristics characteristics | |
| 73 = getCameraCharacteristics(deviceName); | |
| 74 | |
| 75 return characteristics != null | |
| 76 && characteristics.get(CameraCharacteristics.LENS_FACING) | |
| 77 == CameraMetadata.LENS_FACING_BACK; | |
| 78 } | |
| 79 | |
| 80 public CameraVideoCapturer createCapturer(String deviceName, | |
| 81 CameraVideoCapturer.CameraEventsHandler eventsHandler) { | |
| 82 return new Camera2Capturer(context, deviceName, eventsHandler); | |
| 83 } | |
| 84 | |
| 85 private CameraCharacteristics getCameraCharacteristics(String deviceName) { | |
| 86 try { | |
| 87 return cameraManager.getCameraCharacteristics(deviceName); | |
| 88 } catch (CameraAccessException e) { | |
| 89 Logging.e(TAG, "Camera access exception: " + e); | |
| 90 return null; | |
| 91 } | |
| 92 } | |
| 93 | |
| 43 public static boolean isSupported() { | 94 public static boolean isSupported() { |
| 44 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; | 95 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; |
| 45 } | 96 } |
| 46 | 97 |
| 47 public static List<CaptureFormat> getSupportedFormats(Context context, String cameraId) { | 98 static List<CaptureFormat.FramerateRange> getSupportedFramerateRanges( |
| 99 CameraCharacteristics cameraCharacteristics) { | |
| 100 final Range<Integer>[] fpsRanges = | |
| 101 cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TAR GET_FPS_RANGES); | |
| 102 | |
| 103 if (fpsRanges == null) { | |
| 104 return new ArrayList<CaptureFormat.FramerateRange>(); | |
| 105 } | |
| 106 | |
| 107 int maxFps = 0; | |
| 108 for (Range<Integer> fpsRange : fpsRanges) { | |
| 109 maxFps = Math.max(maxFps, fpsRange.getUpper()); | |
| 110 } | |
| 111 int unitFactor = maxFps < 1000 ? 1000 : 1; | |
| 112 return convertFramerates(fpsRanges, unitFactor); | |
| 113 } | |
| 114 | |
| 115 static List<Size> getSupportedSizes( | |
| 116 CameraCharacteristics cameraCharacteristics) { | |
| 117 final StreamConfigurationMap streamMap = | |
| 118 cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGUR ATION_MAP); | |
| 119 final android.util.Size[] sizes = streamMap.getOutputSizes(SurfaceTexture.cl ass); | |
| 120 if (sizes == null) { | |
| 121 Logging.e(TAG, "No supported camera output sizes."); | |
| 122 return new ArrayList<Size>(); | |
| 123 } | |
| 124 return convertSizes(sizes); | |
| 125 } | |
| 126 | |
| 127 static List<CaptureFormat> getSupportedFormats(Context context, String cameraI d) { | |
| 48 return getSupportedFormats( | 128 return getSupportedFormats( |
| 49 (CameraManager) context.getSystemService(Context.CAMERA_SERVICE), camera Id); | 129 (CameraManager) context.getSystemService(Context.CAMERA_SERVICE), camera Id); |
| 50 } | 130 } |
| 51 | 131 |
| 52 public static List<CaptureFormat> getSupportedFormats( | 132 static List<CaptureFormat> getSupportedFormats( |
| 53 CameraManager cameraManager, String cameraId) { | 133 CameraManager cameraManager, String cameraId) { |
| 54 synchronized (cachedSupportedFormats) { | 134 synchronized (cachedSupportedFormats) { |
| 55 if (cachedSupportedFormats.containsKey(cameraId)) { | 135 if (cachedSupportedFormats.containsKey(cameraId)) { |
| 56 return cachedSupportedFormats.get(cameraId); | 136 return cachedSupportedFormats.get(cameraId); |
| 57 } | 137 } |
| 138 | |
| 58 Logging.d(TAG, "Get supported formats for camera index " + cameraId + ".") ; | 139 Logging.d(TAG, "Get supported formats for camera index " + cameraId + ".") ; |
| 59 final long startTimeMs = SystemClock.elapsedRealtime(); | 140 final long startTimeMs = SystemClock.elapsedRealtime(); |
| 60 | 141 |
| 61 final CameraCharacteristics cameraCharacteristics; | 142 final CameraCharacteristics cameraCharacteristics; |
| 62 try { | 143 try { |
| 63 cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) ; | 144 cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) ; |
| 64 } catch (Exception ex) { | 145 } catch (Exception ex) { |
| 65 Logging.e(TAG, "getCameraCharacteristics(): " + ex); | 146 Logging.e(TAG, "getCameraCharacteristics(): " + ex); |
| 66 return new ArrayList<CaptureFormat>(); | 147 return new ArrayList<CaptureFormat>(); |
| 67 } | 148 } |
| 68 | 149 |
| 69 // Calculate default max fps from auto-exposure ranges in case getOutputMi nFrameDuration() is | |
| 70 // not supported. | |
| 71 final Range<Integer>[] fpsRanges = | |
| 72 cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_T ARGET_FPS_RANGES); | |
| 73 int defaultMaxFps = 0; | |
| 74 for (Range<Integer> fpsRange : fpsRanges) { | |
| 75 defaultMaxFps = Math.max(defaultMaxFps, fpsRange.getUpper()); | |
| 76 } | |
| 77 | |
| 78 final StreamConfigurationMap streamMap = | 150 final StreamConfigurationMap streamMap = |
| 79 cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGUR ATION_MAP); | 151 cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGUR ATION_MAP); |
| 80 final Size[] sizes = streamMap.getOutputSizes(ImageFormat.YUV_420_888); | 152 |
| 81 if (sizes == null) { | 153 List<CaptureFormat.FramerateRange> framerateRanges = getSupportedFramerate Ranges( |
| 82 throw new RuntimeException("ImageFormat.YUV_420_888 not supported."); | 154 cameraCharacteristics); |
| 155 List<Size> sizes = getSupportedSizes(cameraCharacteristics); | |
| 156 | |
| 157 int defaultMaxFps = 0; | |
| 158 for (CaptureFormat.FramerateRange framerateRange : framerateRanges) { | |
| 159 defaultMaxFps = Math.max(defaultMaxFps, framerateRange.max); | |
| 160 } | |
| 161 if (defaultMaxFps < 1000) { | |
|
magjed_webrtc
2016/06/27 10:33:24
This check should not be needed for CaptureFormat.
sakal
2016/06/27 12:08:28
You're right.
| |
| 162 defaultMaxFps *= 1000; | |
| 83 } | 163 } |
| 84 | 164 |
| 85 final List<CaptureFormat> formatList = new ArrayList<CaptureFormat>(); | 165 final List<CaptureFormat> formatList = new ArrayList<CaptureFormat>(); |
| 86 for (Size size : sizes) { | 166 for (Size size : sizes) { |
| 87 long minFrameDurationNs = 0; | 167 long minFrameDurationNs = 0; |
| 88 try { | 168 try { |
| 89 minFrameDurationNs = streamMap.getOutputMinFrameDuration(ImageFormat.Y UV_420_888, size); | 169 minFrameDurationNs = streamMap.getOutputMinFrameDuration(SurfaceTextur e.class, |
| 170 new android.util.Size(size.width, size.height)); | |
| 90 } catch (Exception e) { | 171 } catch (Exception e) { |
| 91 // getOutputMinFrameDuration() is not supported on all devices. Ignore silently. | 172 // getOutputMinFrameDuration() is not supported on all devices. Ignore silently. |
| 92 } | 173 } |
| 93 final int maxFps = (minFrameDurationNs == 0) | 174 final int maxFps = (minFrameDurationNs == 0) |
| 94 ? defaultMaxFps | 175 ? defaultMaxFps |
| 95 : (int) Math.round(NANO_SECONDS_PER_SECOND / minF rameDurationNs); | 176 : (int) Math.round(NANO_SECONDS_PER_SECOND / minFrameDurationNs) * 1 000; |
| 96 formatList.add(new CaptureFormat(size.getWidth(), size.getHeight(), 0, m axFps * 1000)); | 177 formatList.add(new CaptureFormat(size.width, size.height, 0, maxFps)); |
| 178 Logging.d(TAG, "Format: " + size.width + "x" + size.height + "@" + maxFp s); | |
| 97 } | 179 } |
| 180 | |
| 98 cachedSupportedFormats.put(cameraId, formatList); | 181 cachedSupportedFormats.put(cameraId, formatList); |
| 99 final long endTimeMs = SystemClock.elapsedRealtime(); | 182 final long endTimeMs = SystemClock.elapsedRealtime(); |
| 100 Logging.d(TAG, "Get supported formats for camera index " + cameraId + " do ne." | 183 Logging.d(TAG, "Get supported formats for camera index " + cameraId + " do ne." |
| 101 + " Time spent: " + (endTimeMs - startTimeMs) + " ms."); | 184 + " Time spent: " + (endTimeMs - startTimeMs) + " ms."); |
| 102 return formatList; | 185 return formatList; |
| 103 } | 186 } |
| 104 } | 187 } |
| 188 | |
| 189 // Convert from android.util.Size to Size. | |
| 190 public static List<Size> convertSizes(android.util.Size[] cameraSizes) { | |
|
magjed_webrtc
2016/06/27 10:33:24
Can this be a private method instead?
sakal
2016/06/27 12:08:28
I changed this. I reduced visibility in Camera1Enu
| |
| 191 final List<Size> sizes = new ArrayList<Size>(); | |
| 192 for (android.util.Size size : cameraSizes) { | |
| 193 sizes.add(new Size(size.getWidth(), size.getHeight())); | |
| 194 } | |
| 195 return sizes; | |
| 196 } | |
| 197 | |
| 198 // Convert from android.util.Range<Integer> to CaptureFormat.FramerateRange. | |
| 199 public static List<CaptureFormat.FramerateRange> convertFramerates( | |
|
magjed_webrtc
2016/06/27 10:33:24
ditto, private?
| |
| 200 Range<Integer>[] arrayRanges, int unitFactor) { | |
| 201 final List<CaptureFormat.FramerateRange> ranges = new ArrayList<CaptureForma t.FramerateRange>(); | |
| 202 for (Range<Integer> range : arrayRanges) { | |
| 203 ranges.add(new CaptureFormat.FramerateRange( | |
| 204 range.getLower() * unitFactor, | |
| 205 range.getUpper() * unitFactor)); | |
| 206 } | |
| 207 return ranges; | |
| 208 } | |
| 105 } | 209 } |
| OLD | NEW |