4#include <QtFFmpegMediaPluginImpl/private/qandroidcamera_p.h>
12#include <QtCore/qdebug.h>
13#include <QtCore/qloggingcategory.h>
14#include <QtCore/qmetaobject.h>
15#include <QtCore/qpermissions.h>
16#include <QtCore/qreadwritelock.h>
17#include <QtCore/private/qandroidextras_p.h>
19#include <QtGui/qguiapplication.h>
20#include <QtGui/qscreen.h>
22#include <QtFFmpegMediaPluginImpl/private/qandroidvideoframefactory_p.h>
23#include <QtFFmpegMediaPluginImpl/private/qffmpegvideobuffer_p.h>
25#include <QtMultimedia/qmediaformat.h>
26#include <QtMultimedia/qmediadevices.h>
27#include <QtMultimedia/private/qcameradevice_p.h>
28#include <QtMultimedia/private/qmultimediautils_p.h>
29#include <QtMultimedia/private/qvideoframe_p.h>
30#include <QtMultimedia/private/qvideoframeconverter_p.h>
31#include <QtMultimedia/private/qvideotexturehelper_p.h>
34#include "libavutil/hwcontext.h"
43Q_GLOBAL_STATIC(QAndroidCameraMap, g_qcameras)
44Q_GLOBAL_STATIC(QReadWriteLock, rwLock)
49QCameraFormat getDefaultCameraFormat(
const QCameraDevice & cameraDevice)
52 const auto defaultFrameFormat = QVideoFrameFormat::Format_YUV420P;
53 const auto defaultResolution = QSize(1920, 1080);
54 QCameraFormatPrivate *defaultFormat =
new QCameraFormatPrivate{
55 .pixelFormat = defaultFrameFormat,
56 .resolution = defaultResolution,
61 QCameraFormat resultFormat = defaultFormat->create();
62 const auto &supportedFormats = cameraDevice.videoFormats();
64 if (supportedFormats.empty() || supportedFormats.contains(resultFormat))
67 auto pixelCount = [](
const QSize& resolution) {
68 Q_ASSERT(resolution.isValid());
69 return resolution.width() * resolution.height();
72 const int defaultPixelCount = pixelCount(defaultResolution);
75 int differenceScore = std::numeric_limits<
int>::max();
77 auto calcDifferenceScore = [defaultPixelCount, pixelCount](
const QCameraFormat& format) {
78 const int pixelDifference = pixelCount(format.resolution()) - defaultPixelCount;
82 return pixelDifference < 0
84 : std::numeric_limits<
int>::min() + pixelDifference;
87 for (
const auto &supportedFormat : supportedFormats) {
88 if (supportedFormat.pixelFormat() == defaultFrameFormat) {
89 if (supportedFormat.resolution() == defaultResolution)
90 return supportedFormat;
92 const int currentDifferenceScore = calcDifferenceScore(supportedFormat);
94 if (currentDifferenceScore < differenceScore) {
95 differenceScore = currentDifferenceScore;
96 resultFormat = supportedFormat;
104bool checkCameraPermission()
106 QCameraPermission permission;
108 const bool granted = qApp->checkPermission(permission) == Qt::PermissionStatus::Granted;
110 qCWarning(qLCAndroidCamera) <<
"Access to camera not granted!";
115int sensorOrientation(QString cameraId)
117 QJniObject deviceManager(QtJniTypes::Traits<QtJniTypes::QtVideoDeviceManager>::className(),
118 QNativeInterface::QAndroidApplication::context());
120 if (!deviceManager.isValid()) {
121 qCWarning(qLCAndroidCamera) <<
"Failed to connect to Qt Video Device Manager.";
125 return deviceManager.callMethod<jint>(
"getSensorOrientation",
126 QJniObject::fromString(cameraId).object<jstring>());
131[[nodiscard]]
static QList<QCamera::FocusMode> qGetSupportedFocusModesFromAndroidCamera(
132 const QJniObject &deviceManager,
133 const QCameraDevice &cameraDevice)
135 QList<QCamera::FocusMode> returnValue;
137 const QStringList focusModeStrings = deviceManager.callMethod<QStringList>(
138 "getSupportedQCameraFocusModesAsStrings",
139 QJniObject::fromString(QString::fromUtf8(cameraDevice.id())).object<jstring>());
142 for (
const QString &focusModeString : focusModeStrings) {
144 const auto focusMode =
static_cast<QCamera::FocusMode>(
145 QMetaEnum::fromType<QCamera::FocusMode>()
147 focusModeString.toLatin1().data(),
150 returnValue.push_back(focusMode);
152 qCDebug(qLCAndroidCamera) <<
153 "received a QCamera::FocusMode string from Android "
154 "QtVideoDeviceManager.java that was not recognized.";
166QAndroidCamera::QAndroidCamera(QCamera *camera)
167 : QPlatformCamera(camera)
168 , m_jniCamera(QNativeInterface::QAndroidApplication::context())
171 m_hwAccel = QFFmpeg::HWAccel::create(AVHWDeviceType::AV_HWDEVICE_TYPE_MEDIACODEC);
173 m_cameraDevice = camera->cameraDevice();
174 m_cameraFormat = !camera->cameraFormat().isNull() ? camera->cameraFormat()
175 : getDefaultCameraFormat(m_cameraDevice);
176 updateCameraCharacteristics();
180 connect(qApp, &QGuiApplication::applicationStateChanged,
181 this, &QAndroidCamera::onApplicationStateChanged);
185QAndroidCamera::~QAndroidCamera()
189 m_jniCamera.callMethod<
void>(
"stopAndClose");
190 setState(State::Closed);
193 QWriteLocker locker(rwLock);
194 g_qcameras->remove(QString::fromUtf8(m_cameraDevice.id()));
197 m_jniCamera.callMethod<
void>(
"stopBackgroundThread");
200void QAndroidCamera::setCamera(
const QCameraDevice &camera)
202 const bool oldActive = isActive();
208 m_jniCamera.callMethod<
void>(
"resetControlProperties");
210 m_cameraDevice = camera;
211 updateCameraCharacteristics();
212 m_cameraFormat = getDefaultCameraFormat(camera);
218std::optional<
int> QAndroidCamera::ffmpegHWPixelFormat()
const
226 return QFFmpegVideoBuffer::toAVPixelFormat(m_androidFramePixelFormat);
229QVideoFrameFormat QAndroidCamera::frameFormat()
const
231 QVideoFrameFormat result = QPlatformCamera::frameFormat();
233 result.setRotation(rotation());
238void QAndroidCamera::frameAvailable(QJniObject image,
bool takePhoto)
240 if ((!(m_state == State::WaitingStart || m_state == State::Started) && !m_waitingForFirstFrame)
241 || m_frameFactory ==
nullptr) {
242 qCWarning(qLCAndroidCamera) <<
"Received frame when not active... ignoring";
243 qCWarning(qLCAndroidCamera) <<
"state:" << m_state;
244 image.callMethod<
void>(
"close");
248 QVideoFrame videoFrame = m_frameFactory->createVideoFrame(image, rotation());
249 if (!videoFrame.isValid())
256 m_androidFramePixelFormat = videoFrame.pixelFormat();
257 if (m_waitingForFirstFrame) {
258 m_waitingForFirstFrame =
false;
259 setState(State::Started);
261 QMetaObject::invokeMethod(
this, &QAndroidCamera::applyStillResolution,
262 Qt::QueuedConnection);
265 videoFrame.setMirrored(m_cameraDevice.position() == QCameraDevice::Position::FrontFace);
268 Q_EMIT newVideoFrame(videoFrame);
270 Q_EMIT onStillPhotoCaptured(videoFrame);
273QtVideo::Rotation QAndroidCamera::rotation()
const
277 const QCameraDevice::Position cameraPosition = m_cameraDevice.position();
278 const bool isExternalCamera = cameraPosition == QCameraDevice::Position::UnspecifiedPosition;
279 if (isExternalCamera)
280 return QtVideo::Rotation::None;
282 auto screen = QGuiApplication::primaryScreen();
283 auto screenOrientation = screen->orientation();
284 if (screenOrientation == Qt::PrimaryOrientation)
285 screenOrientation = screen->primaryOrientation();
289 int deviceOrientation = 0;
290 switch (screenOrientation) {
291 case Qt::PrimaryOrientation:
292 case Qt::PortraitOrientation:
294 case Qt::LandscapeOrientation:
295 deviceOrientation = 270;
297 case Qt::InvertedPortraitOrientation:
298 deviceOrientation = 180;
300 case Qt::InvertedLandscapeOrientation:
301 deviceOrientation = 90;
305 const int sign = (cameraPosition == QCameraDevice::Position::FrontFace) ? 1 : -1;
306 int rotation = (sensorOrientation(QString::fromUtf8(m_cameraDevice.id()))
307 - deviceOrientation * sign + 360) % 360;
309 return QtVideo::Rotation(rotation);
312void QAndroidCamera::setActive(
bool active)
314 Q_ASSERT(thread()->isCurrentThread());
315 if (isActive() == active)
318 if (!m_jniCamera.isValid()) {
319 updateError(QCamera::CameraError, QStringLiteral(
"No connection to Android Camera2 API"));
323 if (!active || !checkCameraPermission()) {
324 m_jniCamera.callMethod<
void>(
"stopAndClose");
325 m_jniCamera.callMethod<
void>(
"clearSurfaces");
326 setState(State::Closed);
330 QWriteLocker locker(rwLock);
331 QString cameraId = QString::fromUtf8(m_cameraDevice.id());
332 int width = m_cameraFormat.resolution().width();
333 int height = m_cameraFormat.resolution().height();
335 if (width < 0 || height < 0) {
336 m_cameraFormat = getDefaultCameraFormat(m_cameraDevice);
337 width = m_cameraFormat.resolution().width();
338 height = m_cameraFormat.resolution().height();
341 m_videoResolution = { FFALIGN(width, 16), FFALIGN(height, 16) };
342 m_stillReaderSize = stillResolution();
344 setState(State::WaitingOpen);
345 g_qcameras->insert(cameraId,
this);
348 m_frameFactory = QAndroidVideoFrameFactory::create();
354 m_jniCamera.callMethod<
void>(
"prepareCamera",
static_cast<jint>(m_videoResolution.width()),
355 static_cast<jint>(m_videoResolution.height()),
356 static_cast<jint>(m_cameraFormat.minFrameRate()),
357 static_cast<jint>(m_cameraFormat.maxFrameRate()),
358 static_cast<jint>(m_stillReaderSize.width()),
359 static_cast<jint>(m_stillReaderSize.height()));
361 bool canOpen = m_jniCamera.callMethod<jboolean>(
"open", cameraId);
364 g_qcameras->remove(cameraId);
365 setState(State::Closed);
366 updateError(QCamera::CameraError,
367 QString(u"Failed to start camera: ").append(m_cameraDevice.description()));
375void QAndroidCamera::setState(QAndroidCamera::State newState)
377 if (newState == m_state)
380 bool wasActive = isActive();
382 if (newState == State::Started)
383 m_state = State::Started;
385 if (m_state == State::Started && newState == State::Closed)
386 m_state = State::Closed;
388 if ((m_state == State::WaitingOpen || m_state == State::WaitingStart)
389 && newState == State::Closed) {
391 m_state = State::Closed;
393 updateError(QCamera::CameraError,
394 QString(u"Failed to start Camera %1").arg(m_cameraDevice.description()));
397 if (m_state == State::Closed && newState == State::WaitingOpen)
398 m_state = State::WaitingOpen;
400 if (m_state == State::WaitingOpen && newState == State::WaitingStart)
401 m_state = State::WaitingStart;
403 if (wasActive != isActive())
404 Q_EMIT activeChanged(isActive());
407bool QAndroidCamera::setCameraFormat(
const QCameraFormat &format)
409 const auto chosenFormat = format.isNull() ? getDefaultCameraFormat(m_cameraDevice) : format;
411 if (chosenFormat == m_cameraFormat)
413 if (!m_cameraDevice.videoFormats().contains(chosenFormat))
416 m_cameraFormat = chosenFormat;
423void QAndroidCamera::updateCameraCharacteristics()
425 if (m_cameraDevice.id().isEmpty()) {
426 cleanCameraCharacteristics();
430 QJniObject deviceManager(QtJniTypes::Traits<QtJniTypes::QtVideoDeviceManager>::className(),
431 QNativeInterface::QAndroidApplication::context());
433 if (!deviceManager.isValid()) {
434 qCWarning(qLCAndroidCamera) <<
"Failed to connect to Qt Video Device Manager.";
435 cleanCameraCharacteristics();
441 QCamera::Features newSupportedFeatures = {};
443 float newMaxZoom = 1.f;
444 float newMinZoom = 1.f;
445 const auto newZoomRange = deviceManager.callMethod<jfloat[]>(
447 QJniObject::fromString(QString::fromUtf8(m_cameraDevice.id())).object<jstring>());
448 if (newZoomRange.isValid() && newZoomRange.size() == 2) {
449 newMinZoom = newZoomRange[0];
450 newMaxZoom = newZoomRange[1];
452 qCDebug(qLCAndroidCamera) <<
453 "received invalid float array when querying zoomRange from Android Camera2. "
454 "Likely Qt developer bug";
457 m_supportedFlashModes.clear();
458 m_supportedFlashModes.append(QCamera::FlashOff);
459 const QStringList flashModes = deviceManager.callMethod<QStringList>(
460 "getSupportedFlashModes",
461 QJniObject::fromString(QString::fromUtf8(m_cameraDevice.id())).object<jstring>());
462 for (
const auto &flashMode : flashModes) {
463 if (flashMode == QLatin1String(
"auto"))
464 m_supportedFlashModes.append(QCamera::FlashAuto);
465 else if (flashMode == QLatin1String(
"on"))
466 m_supportedFlashModes.append(QCamera::FlashOn);
469 m_TorchModeSupported = deviceManager.callMethod<jboolean>(
470 "isTorchModeSupported",
471 QJniObject::fromString(QString::fromUtf8(m_cameraDevice.id())).object<jstring>());
473 m_supportedFocusModes = qGetSupportedFocusModesFromAndroidCamera(
477 if (m_supportedFocusModes.contains(QCamera::FocusMode::FocusModeManual))
478 newSupportedFeatures |= QCamera::Feature::FocusDistance;
482 minimumZoomFactorChanged(newMinZoom);
483 maximumZoomFactorChanged(newMaxZoom);
484 supportedFeaturesChanged(newSupportedFeatures);
488 if (minZoomFactor() < maxZoomFactor()) {
490 const float newZoomFactor = qBound(minZoomFactor(), zoomFactor(), maxZoomFactor());
491 zoomTo(newZoomFactor, -1);
494 if (isFlashModeSupported(flashMode()))
495 setFlashMode(flashMode());
497 if (isTorchModeSupported(torchMode()))
498 setTorchMode(torchMode());
500 if (isFocusModeSupported(focusMode()))
501 setFocusMode(focusMode());
505 if (minZoomFactor() >= maxZoomFactor())
506 zoomFactorChanged(defaultZoomFactor());
508 if (!isFlashModeSupported(flashMode()))
509 flashModeChanged(defaultFlashMode());
511 if (!isTorchModeSupported(torchMode()))
512 torchModeChanged(defaultTorchMode());
514 if (!isFocusModeSupported(focusMode()))
515 focusModeChanged(defaultFocusMode());
519void QAndroidCamera::cleanCameraCharacteristics()
521 maximumZoomFactorChanged(1.0);
522 if (zoomFactor() != 1.0) {
525 if (torchMode() != QCamera::TorchOff) {
526 setTorchMode(QCamera::TorchOff);
528 m_TorchModeSupported =
false;
530 if (flashMode() != QCamera::FlashOff) {
531 setFlashMode(QCamera::FlashOff);
533 m_supportedFlashModes.clear();
534 m_supportedFlashModes.append(QCamera::FlashOff);
538 if (focusMode() != QCamera::FocusModeAuto)
539 setFocusMode(QCamera::FocusModeAuto);
540 m_supportedFocusModes.clear();
542 supportedFeaturesChanged({});
545QSize QAndroidCamera::stillResolution()
const
547 if (m_requestedStillResolution.isEmpty())
548 return m_videoResolution;
550 const QList<QSize> photoResolutions = m_cameraDevice.photoResolutions();
553 if (photoResolutions.isEmpty() || photoResolutions.contains(m_requestedStillResolution))
554 return m_requestedStillResolution;
556 return qClosestSupportedResolution(m_requestedStillResolution, photoResolutions);
560void QAndroidCamera::restartCamera()
570void QAndroidCamera::queueCameraRestart()
572 if (m_restartPending.exchange(
true))
576 QMetaObject::invokeMethod(
579 m_restartPending =
false;
582 Qt::QueuedConnection);
585void QAndroidCamera::setFocusDistance(
float distance)
587 if (QtPrivate::fuzzyCompare(focusDistance(), distance))
590 if (!(supportedFeatures() & QCamera::Feature::FocusDistance)) {
591 qCWarning(qLCAndroidCamera) <<
593 "attmpted to set focus-distance on camera without support for FocusDistance feature";
597 if (distance < 0 || distance > 1) {
598 qCWarning(qLCAndroidCamera) <<
600 "attempted to set camera focus-distance with out-of-bounds value";
607 m_jniCamera.callMethod<
void>(
"setFocusDistance", distance);
609 focusDistanceChanged(distance);
612void QAndroidCamera::setFocusMode(QCamera::FocusMode mode)
614 if (focusMode() == mode)
617 if (!isFocusModeSupported(mode)) {
618 qCWarning(qLCAndroidCamera) <<
620 QLatin1String(
"attempted to set focus-mode '%1' on camera where it is unsupported.")
621 .arg(QMetaEnum::fromType<QCamera::FocusMode>().valueToKey(mode));
627 m_jniCamera.callMethod<
void>(
629 static_cast<jint>(mode));
631 focusModeChanged(mode);
634void QAndroidCamera::setFlashMode(QCamera::FlashMode mode)
636 if (!isFlashModeSupported(mode))
641 case QCamera::FlashAuto:
642 flashMode = QLatin1String(
"auto");
644 case QCamera::FlashOn:
645 flashMode = QLatin1String(
"on");
647 case QCamera::FlashOff:
649 flashMode = QLatin1String(
"off");
653 m_jniCamera.callMethod<
void>(
"setFlashMode", QJniObject::fromString(flashMode).object<jstring>());
654 flashModeChanged(mode);
657bool QAndroidCamera::isFlashModeSupported(QCamera::FlashMode mode)
const
659 return m_supportedFlashModes.contains(mode);
662bool QAndroidCamera::isFlashReady()
const
666 return m_supportedFlashModes.size() > 1;
669bool QAndroidCamera::isFocusModeSupported(QCamera::FocusMode mode)
const
671 return QPlatformCamera::isFocusModeSupported(mode) || m_supportedFocusModes.contains(mode);
674bool QAndroidCamera::isTorchModeSupported(QCamera::TorchMode mode)
const
676 if (mode == QCamera::TorchOff)
678 else if (mode == QCamera::TorchOn)
679 return m_TorchModeSupported;
684void QAndroidCamera::setTorchMode(QCamera::TorchMode mode)
687 if (mode == QCamera::TorchOff) {
689 }
else if (mode == QCamera::TorchOn) {
692 qWarning() <<
"Unknown Torch mode";
695 m_jniCamera.callMethod<
void>(
"setTorchMode", jboolean(torchMode));
696 torchModeChanged(mode);
699void QAndroidCamera::zoomTo(
float factor,
float rate)
703 if (!m_cameraDevice.id().isEmpty()) {
704 m_jniCamera.callMethod<
void>(
"zoomTo", factor);
706 zoomFactorChanged(factor);
709void QAndroidCamera::onApplicationStateChanged()
711 switch (QGuiApplication::applicationState()) {
712 case Qt::ApplicationInactive:
718 case Qt::ApplicationActive:
730void QAndroidCamera::onCaptureSessionConfigured()
732 bool canStart = m_jniCamera.callMethod<jboolean>(
"start");
733 setState(canStart ? State::WaitingStart : State::Closed);
737void QAndroidCamera::onCaptureSessionConfigureFailed()
739 setState(State::Closed);
744void QAndroidCamera::onStillReaderSwapFailed()
746 queueCameraRestart();
750void QAndroidCamera::onCameraOpened()
752 bool canStart = m_jniCamera.callMethod<jboolean>(
"createSession");
753 setState(canStart ? State::WaitingStart : State::Closed);
757void QAndroidCamera::onCameraDisconnect()
759 setState(State::Closed);
763void QAndroidCamera::onCameraError(
int reason)
765 updateError(QCamera::CameraError,
766 QString(u"Capture error with Camera %1. Camera2 Api error code: %2")
767 .arg(m_cameraDevice.description())
772void QAndroidCamera::onSessionActive()
774 m_waitingForFirstFrame =
true;
778void QAndroidCamera::onSessionClosed()
780 m_waitingForFirstFrame =
false;
781 setState(State::Closed);
784void QAndroidCamera::capture()
786 m_jniCamera.callMethod<
void>(
"beginStillPhotoCapture");
789void QAndroidCamera::updateExif(
const QString &filename)
791 m_jniCamera.callMethod<
void>(
"saveExifToFile", QJniObject::fromString(filename).object<jstring>());
794void QAndroidCamera::setStillCaptureResolution(QSize resolution)
796 Q_ASSERT(thread()->isCurrentThread());
798 if (resolution != m_requestedStillResolution && !resolution.isEmpty()
799 && m_cameraDevice.photoResolutions().isEmpty()) {
800 qCWarning(qLCAndroidCamera) <<
"Image capture resolution set to" << resolution
801 <<
"while list of valid photo resolutions is empty. Image "
802 "capture can fail if resolution is not supported by device.";
804 m_requestedStillResolution = resolution;
805 applyStillResolution();
808void QAndroidCamera::applyStillResolution()
810 Q_ASSERT(thread()->isCurrentThread());
812 const QSize newSize = stillResolution();
814 if (!isActive() || m_stillReaderSize == newSize)
817 if (m_jniCamera.callMethod<jboolean>(
"updateStillImageReader", newSize.width(),
819 m_stillReaderSize = newSize;
823 queueCameraRestart();
826void QAndroidCamera::onCaptureSessionFailed(
int reason,
long frameNumber)
828 Q_UNUSED(frameNumber);
830 updateError(QCamera::CameraError,
831 QStringLiteral(
"Capture session failure with Camera %1. Camera2 Api error code: %2")
832 .arg(m_cameraDevice.description())
837void QAndroidCamera::onStillPhotoCaptureFailed()
841 Q_EMIT onImageCaptureFailed(
842 QImageCapture::Error::ResourceError,
843 QStringLiteral(
"Unknown error"));
852#define GET_CAMERA(cameraId)
853 QString key = QJniObject(cameraId).toString();
854 QReadLocker locker(rwLock);
855 if (!g_qcameras->contains(key)) {
856 qCWarning(qLCAndroidCamera) << "Calling back a QtCamera2 after being destroyed.";
859 QFFmpeg::QAndroidCamera *camera = g_qcameras->find(key).value();
861static void onPreviewFrameAvailable(JNIEnv *env, jobject obj, jstring cameraId,
862 QtJniTypes::Image image)
868 camera->frameAvailable(QJniObject(image));
870Q_DECLARE_JNI_NATIVE_METHOD(onPreviewFrameAvailable)
872static void onStillPhotoAvailable(JNIEnv *env, jobject obj, jstring cameraId,
873 QtJniTypes::Image image)
879 camera->frameAvailable(QJniObject(image),
true);
881Q_DECLARE_JNI_NATIVE_METHOD(onStillPhotoAvailable)
884static void onCameraOpened(JNIEnv *env, jobject obj, jstring cameraId)
890 camera->onCameraOpened();
892Q_DECLARE_JNI_NATIVE_METHOD(onCameraOpened)
894static void onCameraDisconnect(JNIEnv *env, jobject obj, jstring cameraId)
900 camera->onCameraDisconnect();
902Q_DECLARE_JNI_NATIVE_METHOD(onCameraDisconnect)
904static void onCameraError(JNIEnv *env, jobject obj, jstring cameraId, jint error)
910 camera->onCameraError(error);
912Q_DECLARE_JNI_NATIVE_METHOD(onCameraError)
914static void onCaptureSessionConfigured(JNIEnv *env, jobject obj, jstring cameraId)
920 camera->onCaptureSessionConfigured();
922Q_DECLARE_JNI_NATIVE_METHOD(onCaptureSessionConfigured)
924static void onCaptureSessionConfigureFailed(JNIEnv *env, jobject obj, jstring cameraId)
930 camera->onCaptureSessionConfigureFailed();
932Q_DECLARE_JNI_NATIVE_METHOD(onCaptureSessionConfigureFailed)
934static void onStillReaderSwapFailed(JNIEnv *env, jobject obj, jstring cameraId)
940 camera->onStillReaderSwapFailed();
942Q_DECLARE_JNI_NATIVE_METHOD(onStillReaderSwapFailed)
944static void onSessionActive(JNIEnv *env, jobject obj, jstring cameraId)
950 camera->onSessionActive();
952Q_DECLARE_JNI_NATIVE_METHOD(onSessionActive)
954static void onSessionClosed(JNIEnv *env, jobject obj, jstring cameraId)
960 camera->onSessionClosed();
962Q_DECLARE_JNI_NATIVE_METHOD(onSessionClosed)
964static void onCaptureSessionFailed(JNIEnv *env, jobject obj, jstring cameraId, jint reason,
971 camera->onCaptureSessionFailed(reason, framenumber);
973Q_DECLARE_JNI_NATIVE_METHOD(onCaptureSessionFailed)
975static void onStillPhotoCaptureFailed(JNIEnv *env, jobject obj, jstring cameraId)
981 camera->onStillPhotoCaptureFailed();
983Q_DECLARE_JNI_NATIVE_METHOD(onStillPhotoCaptureFailed)
985bool QFFmpeg::QAndroidCamera::registerNativeMethods()
987 static const bool registered = []() {
988 return QtJniCamera2::registerNativeMethods({
989 Q_JNI_NATIVE_METHOD(onCameraOpened),
990 Q_JNI_NATIVE_METHOD(onCameraDisconnect),
991 Q_JNI_NATIVE_METHOD(onCameraError),
992 Q_JNI_NATIVE_METHOD(onCaptureSessionConfigured),
993 Q_JNI_NATIVE_METHOD(onCaptureSessionConfigureFailed),
994 Q_JNI_NATIVE_METHOD(onStillReaderSwapFailed),
995 Q_JNI_NATIVE_METHOD(onCaptureSessionFailed),
996 Q_JNI_NATIVE_METHOD(onPreviewFrameAvailable),
997 Q_JNI_NATIVE_METHOD(onStillPhotoAvailable),
998 Q_JNI_NATIVE_METHOD(onSessionActive),
999 Q_JNI_NATIVE_METHOD(onSessionClosed),
1000 Q_JNI_NATIVE_METHOD(onStillPhotoCaptureFailed),
#define GET_CAMERA(cameraId)
QMap< QString, QFFmpeg::QAndroidCamera * > QAndroidCameraMap
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)