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
qandroidvideodevices.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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
4#include <QtFFmpegMediaPluginImpl/private/qandroidvideodevices_p.h>
5
6#include <QtCore/private/qandroidextras_p.h>
7#include <QtCore/qcoreapplication.h>
8#include <QtCore/qcoreapplication_platform.h>
9#include <QtCore/qjnienvironment.h>
10#include <QtCore/qloggingcategory.h>
11
12#include <QtFFmpegMediaPluginImpl/private/qandroidvideoframebuffer_p.h>
13
14#include <QtMultimedia/private/qcameradevice_p.h>
15
16#include <jni.h>
17
18QT_BEGIN_NAMESPACE
19
20using namespace Qt::StringLiterals;
21
22namespace QFFmpeg {
23
24Q_STATIC_LOGGING_CATEGORY(qLCAndroidVideoDevices, "qt.multimedia.ffmpeg.android.videoDevices");
25
26// Can be called from any thread
34
39
40QCameraFormat createCameraFormat(int width, int height, int fpsMin, int fpsMax)
41{
42 QCameraFormatPrivate *format = new QCameraFormatPrivate();
43
44 format->resolution = { width, height };
45
46 format->minFrameRate = fpsMin;
47 format->maxFrameRate = fpsMax;
48
49 format->pixelFormat = QVideoFrameFormat::PixelFormat::Format_YUV420P;
50
51 return format->create();
52}
53
54// Can be called from any thread
56{
58
61
62 if (!deviceManager.isValid()) {
63 qCWarning(qLCAndroidVideoDevices) << "Failed to connect to Qt Video Device Manager.";
64 return devices;
65 }
66
67 const QJniArray cameraIdList = deviceManager.callMethod<QtJniTypes::String[]>("getCameraIdList");
68 if (!cameraIdList.isValid())
69 return devices;
70
71 int cameraIndex = 0;
72 for (const auto &cameraId : cameraIdList) {
73 if (!cameraId.isValid())
74 continue;
75
78
79 info->orientation = deviceManager.callMethod<jint>("getSensorOrientation", cameraId);
80
81 // Will be set to -1 if facing can not be determined.
82 const int facing = deviceManager.callMethod<jint>("getLensFacing", cameraId);
83
84 // Values grabbed from Android docs CameraCharacteristics.LENS_FACING
85 constexpr int LENS_FACING_FRONT = 0;
86 constexpr int LENS_FACING_BACK = 1;
87 constexpr int LENS_FACING_EXTERNAL = 2;
88
89 switch (facing) {
92 info->description = QStringLiteral(u"External Camera: %1").arg(cameraIndex);
93 break;
96 info->description = QStringLiteral(u"Rear Camera: %1").arg(cameraIndex);
97 break;
100 info->description = QStringLiteral(u"Front Camera: %1").arg(cameraIndex);
101 break;
102 default:
104 info->description = QStringLiteral(u"Camera: %1").arg(cameraIndex);
105 break;
106 }
107 ++cameraIndex;
108
109 const auto fpsRanges = deviceManager.callMethod<QStringList>("getFpsRange", cameraId);
110
111 int maxFps = 0, minFps = 0;
112 for (auto range : fpsRanges) {
113 range = range.remove(u"["_s);
114 range = range.remove(u"]"_s);
115
116 const auto split = range.split(u","_s);
117
118 int min = split.at(0).toInt();
119 int max = split.at(1).toInt();
120
121 if (max > maxFps) {
122 maxFps = max;
123 minFps = min;
124 }
125 }
126
127 const static int imageFormat =
129
131 "getStreamConfigurationsSizes", cameraId, imageFormat);
132
133 if (sizes.isEmpty())
134 continue;
135
136 for (const auto &sizeString : sizes) {
137 const auto split = sizeString.split(u"x"_s);
138
139 int width = split.at(0).toInt();
140 int height = split.at(1).toInt();
141
143 }
144
145
147 }
148
149 return devices;
150}
151
152} // namespace QFFmpeg
153
154// Called from background looper thread in Android
156 JNIEnv*,
157 jobject,
158 jlong nativePtr)
159{
160 using namespace QFFmpeg;
161 auto *videoDevices = reinterpret_cast<QAndroidVideoDevices*>(static_cast<size_t>(nativePtr));
162 Q_ASSERT(!videoDevices->thread()->isCurrentThread());
163 videoDevices->onVideoInputsChanged();
164}
165Q_DECLARE_JNI_NATIVE_METHOD(onCameraAvailableNative)
166
167// Called from background looper thread in Android
169 JNIEnv*,
170 jobject,
171 jlong nativePtr)
172{
173 using namespace QFFmpeg;
174 auto *videoDevices = reinterpret_cast<QAndroidVideoDevices*>(static_cast<size_t>(nativePtr));
175 Q_ASSERT(!videoDevices->thread()->isCurrentThread());
176 videoDevices->onVideoInputsChanged();
177}
178Q_DECLARE_JNI_NATIVE_METHOD(onCameraUnavailableNative)
179
180bool QFFmpeg::QAndroidVideoDevices::registerNativeMethods() {
181 return QJavaCameraAvailabilityListener::registerNativeMethods({
182 Q_JNI_NATIVE_METHOD(onCameraAvailableNative),
183 Q_JNI_NATIVE_METHOD(onCameraUnavailableNative),
184 });
185}
186
187QT_END_NAMESPACE
Q_STATIC_LOGGING_CATEGORY(qLCAndroidVideoDevices, "qt.multimedia.ffmpeg.android.videoDevices")
QCameraFormat createCameraFormat(int width, int height, int fpsMin, int fpsMax)
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
static void onCameraUnavailableNative(JNIEnv *, jobject, jlong nativePtr)
static void onCameraAvailableNative(JNIEnv *, jobject, jlong nativePtr)