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 |