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