Index: webrtc/api/java/android/org/webrtc/Camera2Enumerator.java |
diff --git a/webrtc/api/java/android/org/webrtc/Camera2Enumerator.java b/webrtc/api/java/android/org/webrtc/Camera2Enumerator.java |
index 8c342c5c25b51716dd6f1149945330bb22535d9e..fe2b259d2c727af68bef49a2648562796a4b787b 100644 |
--- a/webrtc/api/java/android/org/webrtc/Camera2Enumerator.java |
+++ b/webrtc/api/java/android/org/webrtc/Camera2Enumerator.java |
@@ -10,20 +10,20 @@ |
package org.webrtc; |
+import org.webrtc.CameraEnumerationAndroid.CaptureFormat; |
+ |
import android.annotation.TargetApi; |
import android.content.Context; |
- |
import android.graphics.ImageFormat; |
+import android.graphics.SurfaceTexture; |
+import android.hardware.camera2.CameraAccessException; |
import android.hardware.camera2.CameraCharacteristics; |
import android.hardware.camera2.CameraManager; |
+import android.hardware.camera2.CameraMetadata; |
import android.hardware.camera2.params.StreamConfigurationMap; |
import android.os.Build; |
import android.os.SystemClock; |
import android.util.Range; |
-import android.util.Size; |
- |
-import org.webrtc.CameraEnumerationAndroid.CaptureFormat; |
-import org.webrtc.Logging; |
import java.util.ArrayList; |
import java.util.HashMap; |
@@ -31,7 +31,7 @@ import java.util.List; |
import java.util.Map; |
@TargetApi(21) |
-public class Camera2Enumerator { |
+public class Camera2Enumerator implements CameraEnumerator { |
private final static String TAG = "Camera2Enumerator"; |
private final static double NANO_SECONDS_PER_SECOND = 1.0e9; |
@@ -40,21 +40,104 @@ public class Camera2Enumerator { |
private static final Map<String, List<CaptureFormat>> cachedSupportedFormats = |
new HashMap<String, List<CaptureFormat>>(); |
+ final Context context; |
+ final CameraManager cameraManager; |
+ |
+ public Camera2Enumerator(Context context) { |
+ this.context = context; |
+ this.cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); |
+ } |
+ |
+ @Override |
+ public String[] getDeviceNames() { |
+ try { |
+ return cameraManager.getCameraIdList(); |
+ } catch (CameraAccessException e) { |
+ Logging.e(TAG, "Camera access exception: " + e); |
+ return new String[] {}; |
+ } |
+ } |
+ |
+ @Override |
+ public boolean isFrontFacing(String deviceName) { |
+ CameraCharacteristics characteristics |
+ = getCameraCharacteristics(deviceName); |
+ |
+ return characteristics != null |
+ && characteristics.get(CameraCharacteristics.LENS_FACING) |
+ == CameraMetadata.LENS_FACING_FRONT; |
+ } |
+ |
+ @Override |
+ public boolean isBackFacing(String deviceName) { |
+ CameraCharacteristics characteristics |
+ = getCameraCharacteristics(deviceName); |
+ |
+ return characteristics != null |
+ && characteristics.get(CameraCharacteristics.LENS_FACING) |
+ == CameraMetadata.LENS_FACING_BACK; |
+ } |
+ |
+ @Override |
+ public CameraVideoCapturer createCapturer(String deviceName, |
+ CameraVideoCapturer.CameraEventsHandler eventsHandler) { |
+ return new Camera2Capturer(context, deviceName, eventsHandler); |
+ } |
+ |
+ private CameraCharacteristics getCameraCharacteristics(String deviceName) { |
+ try { |
+ return cameraManager.getCameraCharacteristics(deviceName); |
+ } catch (CameraAccessException e) { |
+ Logging.e(TAG, "Camera access exception: " + e); |
+ return null; |
+ } |
+ } |
+ |
public static boolean isSupported() { |
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; |
} |
- public static List<CaptureFormat> getSupportedFormats(Context context, String cameraId) { |
+ static List<CaptureFormat.FramerateRange> getSupportedFramerateRanges( |
+ CameraCharacteristics cameraCharacteristics) { |
+ final Range<Integer>[] fpsRanges = |
+ cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); |
+ |
+ if (fpsRanges == null) { |
+ return new ArrayList<CaptureFormat.FramerateRange>(); |
+ } |
+ |
+ int maxFps = 0; |
+ for (Range<Integer> fpsRange : fpsRanges) { |
+ maxFps = Math.max(maxFps, fpsRange.getUpper()); |
+ } |
+ int unitFactor = maxFps < 1000 ? 1000 : 1; |
+ return convertFramerates(fpsRanges, unitFactor); |
+ } |
+ |
+ static List<Size> getSupportedSizes( |
+ CameraCharacteristics cameraCharacteristics) { |
+ final StreamConfigurationMap streamMap = |
+ cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); |
+ final android.util.Size[] sizes = streamMap.getOutputSizes(SurfaceTexture.class); |
+ if (sizes == null) { |
+ Logging.e(TAG, "No supported camera output sizes."); |
+ return new ArrayList<Size>(); |
+ } |
+ return convertSizes(sizes); |
+ } |
+ |
+ static List<CaptureFormat> getSupportedFormats(Context context, String cameraId) { |
return getSupportedFormats( |
(CameraManager) context.getSystemService(Context.CAMERA_SERVICE), cameraId); |
} |
- public static List<CaptureFormat> getSupportedFormats( |
+ static List<CaptureFormat> getSupportedFormats( |
CameraManager cameraManager, String cameraId) { |
synchronized (cachedSupportedFormats) { |
if (cachedSupportedFormats.containsKey(cameraId)) { |
return cachedSupportedFormats.get(cameraId); |
} |
+ |
Logging.d(TAG, "Get supported formats for camera index " + cameraId + "."); |
final long startTimeMs = SystemClock.elapsedRealtime(); |
@@ -66,35 +149,34 @@ public class Camera2Enumerator { |
return new ArrayList<CaptureFormat>(); |
} |
- // Calculate default max fps from auto-exposure ranges in case getOutputMinFrameDuration() is |
- // not supported. |
- final Range<Integer>[] fpsRanges = |
- cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); |
- int defaultMaxFps = 0; |
- for (Range<Integer> fpsRange : fpsRanges) { |
- defaultMaxFps = Math.max(defaultMaxFps, fpsRange.getUpper()); |
- } |
- |
final StreamConfigurationMap streamMap = |
cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); |
- final Size[] sizes = streamMap.getOutputSizes(ImageFormat.YUV_420_888); |
- if (sizes == null) { |
- throw new RuntimeException("ImageFormat.YUV_420_888 not supported."); |
+ |
+ List<CaptureFormat.FramerateRange> framerateRanges = getSupportedFramerateRanges( |
+ cameraCharacteristics); |
+ List<Size> sizes = getSupportedSizes(cameraCharacteristics); |
+ |
+ int defaultMaxFps = 0; |
+ for (CaptureFormat.FramerateRange framerateRange : framerateRanges) { |
+ defaultMaxFps = Math.max(defaultMaxFps, framerateRange.max); |
} |
final List<CaptureFormat> formatList = new ArrayList<CaptureFormat>(); |
for (Size size : sizes) { |
long minFrameDurationNs = 0; |
try { |
- minFrameDurationNs = streamMap.getOutputMinFrameDuration(ImageFormat.YUV_420_888, size); |
+ minFrameDurationNs = streamMap.getOutputMinFrameDuration(SurfaceTexture.class, |
+ new android.util.Size(size.width, size.height)); |
} catch (Exception e) { |
// getOutputMinFrameDuration() is not supported on all devices. Ignore silently. |
} |
final int maxFps = (minFrameDurationNs == 0) |
- ? defaultMaxFps |
- : (int) Math.round(NANO_SECONDS_PER_SECOND / minFrameDurationNs); |
- formatList.add(new CaptureFormat(size.getWidth(), size.getHeight(), 0, maxFps * 1000)); |
+ ? defaultMaxFps |
+ : (int) Math.round(NANO_SECONDS_PER_SECOND / minFrameDurationNs) * 1000; |
+ formatList.add(new CaptureFormat(size.width, size.height, 0, maxFps)); |
+ Logging.d(TAG, "Format: " + size.width + "x" + size.height + "@" + maxFps); |
} |
+ |
cachedSupportedFormats.put(cameraId, formatList); |
final long endTimeMs = SystemClock.elapsedRealtime(); |
Logging.d(TAG, "Get supported formats for camera index " + cameraId + " done." |
@@ -102,4 +184,25 @@ public class Camera2Enumerator { |
return formatList; |
} |
} |
+ |
+ // Convert from android.util.Size to Size. |
+ private static List<Size> convertSizes(android.util.Size[] cameraSizes) { |
+ final List<Size> sizes = new ArrayList<Size>(); |
+ for (android.util.Size size : cameraSizes) { |
+ sizes.add(new Size(size.getWidth(), size.getHeight())); |
+ } |
+ return sizes; |
+ } |
+ |
+ // Convert from android.util.Range<Integer> to CaptureFormat.FramerateRange. |
+ private static List<CaptureFormat.FramerateRange> convertFramerates( |
+ Range<Integer>[] arrayRanges, int unitFactor) { |
+ final List<CaptureFormat.FramerateRange> ranges = new ArrayList<CaptureFormat.FramerateRange>(); |
+ for (Range<Integer> range : arrayRanges) { |
+ ranges.add(new CaptureFormat.FramerateRange( |
+ range.getLower() * unitFactor, |
+ range.getUpper() * unitFactor)); |
+ } |
+ return ranges; |
+ } |
} |