Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
QtVideoDeviceManager.java
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4package org.qtproject.qt.android.multimedia;
5
6import android.content.Context;
7import android.graphics.Rect;
8import android.hardware.camera2.CameraCharacteristics;
9import android.hardware.camera2.CameraManager;
10import android.hardware.camera2.CaptureRequest;
11import android.hardware.camera2.params.StreamConfigurationMap;
12import android.media.MediaCodecList;
13import android.media.MediaCodecInfo;
14import android.os.Build;
15import android.util.Range;
16import android.util.Size;
17
18import java.lang.String;
19import java.util.ArrayList;
20import java.util.Arrays;
21import java.util.HashSet;
22import java.util.Map;
23import java.util.Set;
24import java.util.WeakHashMap;
25
26import org.qtproject.qt.android.UsedFromNativeCode;
27
28class QtVideoDeviceManager {
29
30 CameraManager mCameraManager;
32
33 @UsedFromNativeCode
34 QtVideoDeviceManager(Context context) {
35 mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
36 cache = new WeakHashMap<String, CameraCharacteristics>();
37 }
38
39 CameraCharacteristics getCameraCharacteristics(String cameraId) {
40
41 if (cache.containsKey(cameraId))
42 return cache.get(cameraId);
43
44 try {
45 CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(cameraId);
46 cache.put(cameraId, cameraCharacteristics);
47 return cameraCharacteristics;
48 } catch (Exception e) {
49 e.printStackTrace();
50 }
51 return null;
52 }
53
54 static private boolean isSoftwareCodec(String longCodecName) {
55 longCodecName = longCodecName.toLowerCase();
56 return longCodecName.startsWith("omx.google.") || longCodecName.startsWith("c2.android.")
57 || !(longCodecName.startsWith("omx.") || longCodecName.startsWith("c2."));
58 }
59
60 private enum CODEC {
63 }
64 static private String[] getHWVideoCodecs(CODEC expectedType) {
65 MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
66 MediaCodecInfo[] mediaCodecInfo = mediaCodecList.getCodecInfos();
67 Set<String> codecs = new HashSet<String>();
68
69 for (MediaCodecInfo codecInfo : mediaCodecInfo) {
70 CODEC currentType = codecInfo.isEncoder() ? CODEC.ENCODER : CODEC.DECODER;
71 if (currentType == expectedType && !isSoftwareCodec(codecInfo.getName())) {
72 String[] supportedTypes = codecInfo.getSupportedTypes();
73 for (String type : supportedTypes) {
74 if (type.startsWith("video/"))
75 codecs.add(type.substring(6));
76 }
77 }
78 }
79 return codecs.toArray(new String[codecs.size()]);
80 }
81
82 static String[] getHWVideoDecoders() { return getHWVideoCodecs(CODEC.DECODER); }
83 static String[] getHWVideoEncoders() { return getHWVideoCodecs(CODEC.ENCODER); }
84
85 @UsedFromNativeCode
86 String[] getCameraIdList() {
87 try {
88 return mCameraManager.getCameraIdList();
89 } catch (Exception e) {
90 e.printStackTrace();
91 }
92 return null;
93 }
94
95 @UsedFromNativeCode
96 int getSensorOrientation(String cameraId) {
97 CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
98 if (characteristics == null)
99 return 0;
100 return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
101 }
102
103 // Returns -1 when camera is not available.
104 @UsedFromNativeCode
105 int getLensFacing(String cameraId) {
106 final CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
107 if (characteristics == null)
108 return -1;
109
110 // The docs guarantees this is not null:
111 // https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics#LENS_FACING
112 return characteristics.get(CameraCharacteristics.LENS_FACING);
113 }
114
115 @UsedFromNativeCode
116 String[] getFpsRange(String cameraId) {
117
118 CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
119 if (characteristics == null)
120 return new String[0];
121
122 Range<Integer>[] ranges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
123
124 String[] fps = new String[ranges.length];
125
126 for (int index = 0; index < ranges.length; index++) {
127 fps[index] = ranges[index].toString();
128 }
129
130 return fps;
131 }
132
133 @UsedFromNativeCode
134 float[] getZoomRange(String cameraId) {
135
136 float[] zoomRange = { 1.0f, 1.0f };
137 final CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
138 if (characteristics == null)
139 return zoomRange;
140
141 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
142 final Range<Float> range = characteristics.get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
143 if (range != null) {
144 zoomRange[0] = range.getLower();
145 zoomRange[1] = range.getUpper();
146 }
147 }
148
149 if (zoomRange[1] == 1.0f)
150 zoomRange[1] = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
151
152 return zoomRange;
153 }
154
155 Rect getActiveArraySize(String cameraId) {
156 Rect activeArraySize = new Rect();
157 final CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
158 if (characteristics != null)
159 activeArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
160 return activeArraySize;
161 }
162
163 static final int maxResolution = 3840*2160; // 4k resolution
164 @UsedFromNativeCode
165 String[] getStreamConfigurationsSizes(String cameraId, int imageFormat) {
166
167 CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
168 if (characteristics == null)
169 return new String[0];
170
171 StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
172 Size[] sizes = map.getOutputSizes(imageFormat);
173 if (sizes == null)
174 return new String[0];
175
176 ArrayList<String> stream = new ArrayList<>();
177
178 for (int index = 0; index < sizes.length; index++) {
179 if (sizes[index].getWidth() * sizes[index].getHeight() <= maxResolution)
180 stream.add(sizes[index].toString());
181 }
182
183 return stream.toArray(new String[0]);
184 }
185
186 int stringToControlAEMode(String mode) {
187 switch (mode) {
188 case "off":
189 return CaptureRequest.CONTROL_AE_MODE_ON;
190 case "auto":
191 return CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH;
192 case "on":
193 return CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH;
194 case "redeye":
195 return CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE;
196 case "external":
197 return CaptureRequest.CONTROL_AE_MODE_ON_EXTERNAL_FLASH;
198 default:
199 return -1;
200 }
201 }
202
203 String controlAEModeToString(int mode) {
204 switch (mode) {
205 case CaptureRequest.CONTROL_AE_MODE_ON:
206 return "off";
207 case CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH:
208 return "auto";
209 case CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH:
210 return "on";
211 case CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE:
212 return "redeye";
213 case CaptureRequest.CONTROL_AE_MODE_ON_EXTERNAL_FLASH:
214 return "external";
215 case CaptureRequest.CONTROL_AE_MODE_OFF:
216 default:
217 return "unknown";
218 }
219 }
220
221 // Returns all available modes exposed by the physical device, regardless
222 // of whether we have implemented them.
223 //
224 // Guaranteed to not return null. Will instead return array of size zero.
225 @UsedFromNativeCode
226 int[] getAllAvailableAfModes(String cameraId) {
227 if (cameraId.isEmpty())
228 return new int[0];
229
230 CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
231 if (characteristics == null)
232 return new int[0];
233
234 final int[] characteristicsValue = characteristics.get(
235 CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
236 return characteristicsValue != null ? characteristicsValue : new int[0];
237 }
238
239 boolean isAfModeAvailable(String cameraId, int afMode) {
240 if (cameraId == null || cameraId.isEmpty())
241 return false;
242 return Arrays
243 .stream(getAllAvailableAfModes(cameraId))
244 .anyMatch(value -> value == afMode);
245 }
246
247 // Returns supported QCamera::FocusModes as strings. I.e FocusModeAuto becomes "FocusModeAuto".
248 // This method will return only those focus-modes for which we have an implementation, and
249 // is also reported as available by the physical device. This method will never return null.
250 // It is guaranteed to return an empty list if no focus modes are found.
251 //
252 // Note: These returned strings MUST match that of QCamera::FocusMode.
253 @UsedFromNativeCode
254 String[] getSupportedQCameraFocusModesAsStrings(String cameraId) {
255 ArrayList<String> outList = new ArrayList<String>();
256
257 // FocusModeAuto maps to the CONTINUOUS_PICTURE mode.
258 if (isAfModeAvailable(cameraId, CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
259 outList.add("FocusModeAuto");
260 }
261
262 if (isAfModeAvailable(cameraId, CameraCharacteristics.CONTROL_AF_MODE_OFF)
263 && isManualFocusDistanceSupported(cameraId))
264 outList.add("FocusModeManual");
265
266 String[] ret = new String[ outList.size() ];
267 return outList.toArray(ret);
268 }
269
270 @UsedFromNativeCode
271 String[] getSupportedFlashModes(String cameraId) {
272
273 CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
274 if (characteristics == null)
275 return new String[0];
276
277 int supportedFlashModes[] = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES);
278 ArrayList<String> supportedFlashModesList = new ArrayList<String>();
279 for (int index = 0; index < supportedFlashModes.length; index++) {
280 supportedFlashModesList.add(controlAEModeToString(supportedFlashModes[index]));
281 }
282
283 String[] ret = new String[ supportedFlashModesList.size() ];
284 return supportedFlashModesList.toArray(ret);
285 }
286
287 // Returns the CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE for the given cameraId.
288 // for the given cameraId. If this returns 0, it means the camera is fixed-focus and can't be
289 // adjusted and so should not be applied as manual focus distance.
290 // Returns -1 if setting focus distance is not supported.
291 float getLensInfoMinimumFocusDistance(String cameraId) {
292 final CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
293 if (characteristics == null)
294 return -1;
295 final Float value = characteristics.get(
296 CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
297 if (value == null)
298 return -1;
299 return value;
300 }
301
302 // Returns true if the camera is able to manually set
303 // lens focus distance. This is required to support
304 // QCamera::FocusModeManual and QCamera::Feature::FocusDistance.
305 //
306 // Docs require LENS_INFO_MINIMUM_FOCUS_DISTANCE to be higher than 0 in
307 // order for manual focus distance to be supported.
308 boolean isManualFocusDistanceSupported(String cameraId) {
309 return getLensInfoMinimumFocusDistance(cameraId) > 0;
310 }
311
312 static boolean isEmulator()
313 {
314 return ((Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
315 || Build.FINGERPRINT.startsWith("generic")
316 || Build.FINGERPRINT.startsWith("unknown")
317 || Build.HARDWARE.contains("goldfish")
318 || Build.HARDWARE.contains("ranchu")
319 || Build.MODEL.contains("google_sdk")
320 || Build.MODEL.contains("Emulator")
321 || Build.MODEL.contains("Android SDK built for x86")
322 || Build.MANUFACTURER.contains("Genymotion")
323 || Build.PRODUCT.contains("sdk")
324 || Build.PRODUCT.contains("vbox86p")
325 || Build.PRODUCT.contains("emulator")
326 || Build.PRODUCT.contains("simulator"));
327 }
328
329 @UsedFromNativeCode
330 boolean isTorchModeSupported(String cameraId) {
331 boolean ret = false;
332 final CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
333 if (characteristics != null)
334 ret = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
335 return ret;
336 }
337}
QPainter Context
static const QString context()
Definition java.cpp:398
QFuture< void > map(QThreadPool *pool, Sequence &&sequence, MapFunctor &&map)
Calls function once for each item in sequence.
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[3]
#define Size(name)
return ret
GLenum mode
GLenum type
GLfloat GLfloat f
[26]
GLuint index
GLsizei range
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
QList< std::pair< QString, QString > > Map
char * toString(const MyType &t)
[31]