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
QtCameraAvailabilityListener.java
Go to the documentation of this file.
1// Copyright (C) 2025 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.qffmpeg;
5
6import android.app.Activity;
7import android.hardware.camera2.CameraManager;
8import android.os.Handler;
9import android.util.Log;
10
11import org.qtproject.qt.android.UsedFromNativeCode;
12
13import java.util.concurrent.CountDownLatch;
14
15// This class implements the camera-device availability callbacks for Android CameraManager.
16// This class should only be used with QAndroidVideoDevices.
17// In the future it might make sense to a central QtVideoDeviceManager that everything references,
18// and to build this class' functionality into that.
19class QtCameraAvailabilityListener extends CameraManager.AvailabilityCallback {
20
21 static final String LOG_TAG = "QtCameraAvailabilityListener";
22
23 CameraManager mCameraManager = null;
24 // Holds the pointer to the QAndroidVideoDevices instance.
25 // Should only ever be accessed from mAvailabilityCallbackHandler thread.
26 long mVideoDevicesNativePtr = 0;
27
28 Handler mAvailabilityCallbackHandler = null;
29
30 // Called from any native C++ thread.
31 @UsedFromNativeCode
32 QtCameraAvailabilityListener(Activity activity, long videoDevicesNativePtr) {
33 mCameraManager = (CameraManager)activity.getSystemService(Activity.CAMERA_SERVICE);
34 mVideoDevicesNativePtr = videoDevicesNativePtr;
35
36 // We use the Android main UI thread for receiving callbacks.
37 mAvailabilityCallbackHandler = new Handler(activity.getMainLooper());
38
39 // TODO: This will call C++ updateNativeVideoDevices() for each currently available
40 // camera when registered, possibly leading to us enumerating video-devices unncessarily
41 // often, and also signalling QMediaDevices::videoInputsChanged more than necessary.
42 // This should generally not be a problem assuming the multimedia backend is initialized
43 // before user-code.
44 //
45 // A future solution could be to post a job on the handler and wait for it, or
46 // to dynamically add/remove devices from an internal list which is then returned in
47 // QAndroidVideoDevices::findVideoInputs()
48 mCameraManager.registerAvailabilityCallback(this, mAvailabilityCallbackHandler);
49 }
50
51 // Called by QAndroidVideoDevices destructor.
52 // Posts a blocking job to background thread to clear the
53 // reference to QAndroidVideoDevices, then returns after
54 // reference is cleared.
55 @UsedFromNativeCode
56 void cleanup() {
57 assert(!mAvailabilityCallbackHandler.getLooper().isCurrentThread());
58
59 // Perform cleanup on the same thread that we receive callbacks, then wait for cleanup job
60 // to finish. No need for locks.
61 final CountDownLatch latch = new CountDownLatch(1);
62 final boolean postSuccess = mAvailabilityCallbackHandler.post(() -> {
63 mCameraManager.unregisterAvailabilityCallback(this);
64 assert(mVideoDevicesNativePtr != 0);
65 mVideoDevicesNativePtr = 0;
66 latch.countDown(); // Signal that the task is done
67 });
68
69 if (!postSuccess) {
70 Log.w(
71 LOG_TAG,
72 "Unable to post cleanup job to corresponding thread during " +
73 "QAndroidVideoDevices cleanup.");
74 return;
75 }
76
77 try {
78 latch.await();
79 } catch (Exception e) {
80 Log.w(
81 LOG_TAG,
82 "Unable to wait for cleanup job to finish on corresponding thread during" +
83 "QAndroidVideoDevices cleanup.");
84 }
85
86 // After waiting, QAndroidVideoDevices can now be safely destroyed.
87 }
88
89 native void onCameraAvailableNative(long videoDevicesNativePtr);
90
91 // Will be called once for each connected camera device when availability-listener
92 // is attached to the Android CameraManager.
94 public void onCameraAvailable(String cameraId) {
95 assert(mAvailabilityCallbackHandler.getLooper().isCurrentThread());
96 assert(mVideoDevicesNativePtr != 0);
97 onCameraAvailableNative(mVideoDevicesNativePtr);
98 }
99
100 native void onCameraUnavailableNative(long videoDevicesNativePtr);
101
102 @Override
103 public void onCameraUnavailable(String cameraId) {
104 assert(mAvailabilityCallbackHandler.getLooper().isCurrentThread());
105 assert(mVideoDevicesNativePtr != 0);
106 onCameraUnavailableNative(mVideoDevicesNativePtr);
107 }
108
109 @Override
110 public void onCameraAccessPrioritiesChanged() {
111 // TODO: In the future we should handle camera priorities, such as when the camera-device
112 // is connected but is in use by another application, making the current application unable
113 // to use it until the device is released by the other application.
114 }
115}
Q_CORE_EXPORT QtJniTypes::Activity activity()
#define assert
@ Handler
void cleanup()