4#include <QtFFmpegMediaPluginImpl/private/qandroidcamera_p.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qloggingcategory.h>
13#include <QtCore/qmetaobject.h>
14#include <QtCore/qpermissions.h>
15#include <QtCore/private/qandroidextras_p.h>
17#include <QtGui/qguiapplication.h>
18#include <QtGui/qscreen.h>
20#include <QtFFmpegMediaPluginImpl/private/qandroidvideoframefactory_p.h>
21#include <QtFFmpegMediaPluginImpl/private/qffmpegvideobuffer_p.h>
23#include <QtMultimedia/private/qcameradevice_p.h>
24#include <QtMultimedia/private/qmultimediautils_p.h>
27#include "libavutil/hwcontext.h"
36QCameraFormat getDefaultCameraFormat(
const QCameraDevice & cameraDevice)
39 const auto defaultFrameFormat = QVideoFrameFormat::Format_YUV420P;
40 const auto defaultResolution = QSize(1920, 1080);
41 QCameraFormatPrivate *defaultFormat =
new QCameraFormatPrivate{
42 .pixelFormat = defaultFrameFormat,
43 .resolution = defaultResolution,
48 QCameraFormat resultFormat = defaultFormat->create();
49 const auto &supportedFormats = cameraDevice.videoFormats();
51 if (supportedFormats.empty() || supportedFormats.contains(resultFormat))
54 auto pixelCount = [](
const QSize& resolution) {
55 Q_ASSERT(resolution.isValid());
56 return resolution.width() * resolution.height();
59 const int defaultPixelCount = pixelCount(defaultResolution);
62 int differenceScore =
std::numeric_limits<
int>::max();
64 auto calcDifferenceScore = [defaultPixelCount, pixelCount](
const QCameraFormat& format) {
65 const int pixelDifference = pixelCount(format.resolution()) - defaultPixelCount;
69 return pixelDifference < 0
71 : std::numeric_limits<
int>::min() + pixelDifference;
74 for (
const auto &supportedFormat : supportedFormats) {
75 if (supportedFormat.pixelFormat() == defaultFrameFormat) {
76 if (supportedFormat.resolution() == defaultResolution)
77 return supportedFormat;
79 const int currentDifferenceScore = calcDifferenceScore(supportedFormat);
81 if (currentDifferenceScore < differenceScore) {
82 differenceScore = currentDifferenceScore;
83 resultFormat = supportedFormat;
91bool checkCameraPermission()
93 QCameraPermission permission;
95 const bool granted = qApp->checkPermission(permission) == Qt::PermissionStatus::Granted;
97 qCWarning(qLCAndroidCamera) <<
"Access to camera not granted!";
102int sensorOrientation(QString cameraId)
104 QJniObject deviceManager(QtJniTypes::Traits<QtJniTypes::QtVideoDeviceManager>::className(),
105 QNativeInterface::QAndroidApplication::context());
107 if (!deviceManager.isValid()) {
108 qCWarning(qLCAndroidCamera) <<
"Failed to connect to Qt Video Device Manager.";
112 return deviceManager.callMethod<jint>(
"getSensorOrientation",
113 QJniObject::fromString(cameraId).object<jstring>());
118[[nodiscard]]
static QList<QCamera::FocusMode> qGetSupportedFocusModesFromAndroidCamera(
119 const QJniObject &deviceManager,
120 const QCameraDevice &cameraDevice)
122 QList<QCamera::FocusMode> returnValue;
124 const QStringList focusModeStrings = deviceManager.callMethod<QStringList>(
125 "getSupportedQCameraFocusModesAsStrings",
126 QJniObject::fromString(QString::fromUtf8(cameraDevice.id())).object<jstring>());
129 for (
const QString &focusModeString : focusModeStrings) {
131 const auto focusMode =
static_cast<QCamera::FocusMode>(
132 QMetaEnum::fromType<QCamera::FocusMode>()
134 focusModeString.toLatin1().data(),
137 returnValue.push_back(focusMode);
139 qCDebug(qLCAndroidCamera) <<
140 "received a QCamera::FocusMode string from Android "
141 "QtVideoDeviceManager.java that was not recognized.";
432 "received invalid float array when querying zoomRange from Android Camera2. "
433 "Likely Qt developer bug";
439 "getSupportedFlashModes",
449 "isTorchModeSupported",
572 "attmpted to set focus-distance on camera without support for FocusDistance feature";
579 "attempted to set camera focus-distance with out-of-bounds value";
599 QLatin1String(
"attempted to set focus-mode '%1' on camera where it is unsupported.")
745 QString(u"Capture error with Camera %1. Camera2 Api error code: %2")
780 <<
"while list of valid photo resolutions is empty. Image "
781 "capture can fail if resolution is not supported by device.";
810 QStringLiteral(
"Capture session failure with Camera %1. Camera2 Api error code: %2")
834[[nodiscard]] QFFmpeg::QAndroidCamera& jLongToQAndroidCamera(jlong input)
836 Q_ASSERT(input != 0);
837 return *
reinterpret_cast<QFFmpeg::QAndroidCamera *>(
static_cast<uintptr_t>(input));
843 QtJniTypes::Image image)
845 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
846 camera.frameAvailable(QJniObject(image));
848Q_DECLARE_JNI_NATIVE_METHOD(onPreviewFrameAvailable)
851 QtJniTypes::Image image)
853 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
854 camera.frameAvailable(QJniObject(image),
true);
856Q_DECLARE_JNI_NATIVE_METHOD(onStillPhotoAvailable)
860 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
861 camera.onCameraOpened();
863Q_DECLARE_JNI_NATIVE_METHOD(onCameraOpened)
867 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
868 camera.onCameraDisconnect();
870Q_DECLARE_JNI_NATIVE_METHOD(onCameraDisconnect)
874 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
875 camera.onCameraError(error);
877Q_DECLARE_JNI_NATIVE_METHOD(onCameraError)
881 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
882 camera.onCaptureSessionConfigured();
884Q_DECLARE_JNI_NATIVE_METHOD(onCaptureSessionConfigured)
888 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
889 camera.onCaptureSessionConfigureFailed();
891Q_DECLARE_JNI_NATIVE_METHOD(onCaptureSessionConfigureFailed)
895 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
896 camera.onStillReaderSwapFailed();
898Q_DECLARE_JNI_NATIVE_METHOD(onStillReaderSwapFailed)
902 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
903 camera.onSessionActive();
905Q_DECLARE_JNI_NATIVE_METHOD(onSessionActive)
909 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
910 camera.onSessionClosed();
912Q_DECLARE_JNI_NATIVE_METHOD(onSessionClosed)
917 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
918 camera.onCaptureSessionFailed(reason, framenumber);
920Q_DECLARE_JNI_NATIVE_METHOD(onCaptureSessionFailed)
924 QFFmpeg::QAndroidCamera &camera = jLongToQAndroidCamera(qAndroidCameraPtr);
925 camera.onStillPhotoCaptureFailed();
927Q_DECLARE_JNI_NATIVE_METHOD(onStillPhotoCaptureFailed)
929bool QFFmpeg::QAndroidCamera::registerNativeMethods()
931 static const bool registered = []() {
932 return QtJniCamera2::registerNativeMethods({
933 Q_JNI_NATIVE_METHOD(onCameraOpened),
934 Q_JNI_NATIVE_METHOD(onCameraDisconnect),
935 Q_JNI_NATIVE_METHOD(onCameraError),
936 Q_JNI_NATIVE_METHOD(onCaptureSessionConfigured),
937 Q_JNI_NATIVE_METHOD(onCaptureSessionConfigureFailed),
938 Q_JNI_NATIVE_METHOD(onStillReaderSwapFailed),
939 Q_JNI_NATIVE_METHOD(onCaptureSessionFailed),
940 Q_JNI_NATIVE_METHOD(onPreviewFrameAvailable),
941 Q_JNI_NATIVE_METHOD(onStillPhotoAvailable),
942 Q_JNI_NATIVE_METHOD(onSessionActive),
943 Q_JNI_NATIVE_METHOD(onSessionClosed),
944 Q_JNI_NATIVE_METHOD(onStillPhotoCaptureFailed),
static void onCaptureSessionFailed(JNIEnv *, jobject, jlong qAndroidCameraPtr, jint reason, jlong framenumber)
static void onCameraOpened(JNIEnv *, jobject, jlong qAndroidCameraPtr)
static void onPreviewFrameAvailable(JNIEnv *, jobject, jlong qAndroidCameraPtr, QtJniTypes::Image image)
static void onStillReaderSwapFailed(JNIEnv *, jobject, jlong qAndroidCameraPtr)
static void onCaptureSessionConfigured(JNIEnv *, jobject, jlong qAndroidCameraPtr)
static void onCaptureSessionConfigureFailed(JNIEnv *, jobject, jlong qAndroidCameraPtr)
static void onStillPhotoCaptureFailed(JNIEnv *, jobject, jlong qAndroidCameraPtr)
static void onStillPhotoAvailable(JNIEnv *, jobject, jlong qAndroidCameraPtr, QtJniTypes::Image image)
static void onSessionClosed(JNIEnv *, jobject, jlong qAndroidCameraPtr)
static void onSessionActive(JNIEnv *, jobject, jlong qAndroidCameraPtr)
static void onCameraError(JNIEnv *, jobject, jlong qAndroidCameraPtr, jint error)
static void onCameraDisconnect(JNIEnv *, jobject, jlong qAndroidCameraPtr)
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)