1 /* 2 * libjingle 3 * Copyright 2015 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 package org.webrtc; 29 30 import android.annotation.TargetApi; 31 import android.content.Context; 32 33 import android.graphics.ImageFormat; 34 import android.hardware.camera2.CameraCharacteristics; 35 import android.hardware.camera2.CameraManager; 36 import android.hardware.camera2.params.StreamConfigurationMap; 37 import android.os.Build; 38 import android.os.SystemClock; 39 import android.util.Range; 40 import android.util.Size; 41 42 import org.webrtc.CameraEnumerationAndroid.CaptureFormat; 43 import org.webrtc.Logging; 44 45 import java.util.ArrayList; 46 import java.util.HashMap; 47 import java.util.List; 48 import java.util.Map; 49 50 @TargetApi(21) 51 public class Camera2Enumerator implements CameraEnumerationAndroid.Enumerator { 52 private final static String TAG = "Camera2Enumerator"; 53 private final static double NANO_SECONDS_PER_SECOND = 1.0e9; 54 55 private final CameraManager cameraManager; 56 // Each entry contains the supported formats for a given camera index. The formats are enumerated 57 // lazily in getSupportedFormats(), and cached for future reference. 58 private final Map<Integer, List<CaptureFormat>> cachedSupportedFormats = 59 new HashMap<Integer, List<CaptureFormat>>(); 60 isSupported()61 public static boolean isSupported() { 62 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; 63 } 64 Camera2Enumerator(Context context)65 public Camera2Enumerator(Context context) { 66 cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 67 } 68 69 @Override getSupportedFormats(int cameraId)70 public List<CaptureFormat> getSupportedFormats(int cameraId) { 71 synchronized (cachedSupportedFormats) { 72 if (cachedSupportedFormats.containsKey(cameraId)) { 73 return cachedSupportedFormats.get(cameraId); 74 } 75 Logging.d(TAG, "Get supported formats for camera index " + cameraId + "."); 76 final long startTimeMs = SystemClock.elapsedRealtime(); 77 78 final CameraCharacteristics cameraCharacteristics; 79 try { 80 cameraCharacteristics = cameraManager.getCameraCharacteristics(Integer.toString(cameraId)); 81 } catch (Exception ex) { 82 Logging.e(TAG, "getCameraCharacteristics(): " + ex); 83 return new ArrayList<CaptureFormat>(); 84 } 85 86 // Calculate default max fps from auto-exposure ranges in case getOutputMinFrameDuration() is 87 // not supported. 88 final Range<Integer>[] fpsRanges = 89 cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); 90 int defaultMaxFps = 0; 91 for (Range<Integer> fpsRange : fpsRanges) { 92 defaultMaxFps = Math.max(defaultMaxFps, fpsRange.getUpper()); 93 } 94 95 final StreamConfigurationMap streamMap = 96 cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 97 final Size[] sizes = streamMap.getOutputSizes(ImageFormat.YUV_420_888); 98 if (sizes == null) { 99 throw new RuntimeException("ImageFormat.YUV_420_888 not supported."); 100 } 101 102 final List<CaptureFormat> formatList = new ArrayList<CaptureFormat>(); 103 for (Size size : sizes) { 104 long minFrameDurationNs = 0; 105 try { 106 minFrameDurationNs = streamMap.getOutputMinFrameDuration(ImageFormat.YUV_420_888, size); 107 } catch (Exception e) { 108 // getOutputMinFrameDuration() is not supported on all devices. Ignore silently. 109 } 110 final int maxFps = (minFrameDurationNs == 0) 111 ? defaultMaxFps 112 : (int) Math.round(NANO_SECONDS_PER_SECOND / minFrameDurationNs); 113 formatList.add(new CaptureFormat(size.getWidth(), size.getHeight(), 0, maxFps * 1000)); 114 } 115 cachedSupportedFormats.put(cameraId, formatList); 116 final long endTimeMs = SystemClock.elapsedRealtime(); 117 Logging.d(TAG, "Get supported formats for camera index " + cameraId + " done." 118 + " Time spent: " + (endTimeMs - startTimeMs) + " ms."); 119 return formatList; 120 } 121 } 122 } 123