diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-09-07 13:41:00 +0200 |
---|---|---|
committer | Assam Boudjelthia <assam.boudjelthia@qt.io> | 2021-09-08 15:09:11 +0300 |
commit | 18c1261976d7838814468cb1cc31a3858cf363cd (patch) | |
tree | 84c8d4e6d64677b007e4d632883971c5f4c976a3 /src/multimedia | |
parent | e0f94543ff5b9310bfb735110949e66663179a34 (diff) |
Fix orientation of camera frames on Android
Properly adjust orientation of video frames coming from
the camera. Now we show the video of both cameras the
right way in all orientations.
When in portrait mode, swap the width and height of the
video frames we create, to get the correct aspect
ratio of the camera device.
Pick-to: 6.2 6.2.0
Change-Id: I7168c672867988c419f160c817a380624392744e
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/multimedia')
3 files changed, 57 insertions, 16 deletions
diff --git a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp index bb7083d40..1d85acf95 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp @@ -48,6 +48,7 @@ #include <QtConcurrent/qtconcurrentrun.h> #include <qfile.h> #include <qguiapplication.h> +#include <qscreen.h> #include <qdebug.h> #include <qvideoframe.h> #include <private/qplatformimagecapture_p.h> @@ -63,7 +64,6 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent) : QObject(parent) , m_selectedCamera(0) , m_camera(0) - , m_nativeOrientation(0) , m_videoOutput(0) , m_savedState(-1) , m_previewStarted(false) @@ -76,6 +76,11 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent) if (qApp) { connect(qApp, &QGuiApplication::applicationStateChanged, this, &QAndroidCameraSession::onApplicationStateChanged); + + auto screen = qApp->primaryScreen(); + if (screen) + connect(screen, &QScreen::orientationChanged, + this, &QAndroidCameraSession::updateOrientation); } } @@ -177,8 +182,6 @@ bool QAndroidCameraSession::open() connect(m_camera, &AndroidCamera::takePictureFailed, this, &QAndroidCameraSession::onCameraTakePictureFailed); - m_nativeOrientation = m_camera->getNativeOrientation(); - if (m_camera->getPreviewFormat() != AndroidCamera::NV21) m_camera->setPreviewFormat(AndroidCamera::NV21); @@ -314,8 +317,14 @@ void QAndroidCameraSession::applyResolution(const QSize &captureSize, bool resta || currentFpsRange.min != adjustedFps.min || currentFpsRange.max != adjustedFps.max) { - if (m_videoOutput) - m_videoOutput->setVideoSize(adjustedViewfinderResolution); + if (m_videoOutput) { + // fix the resolution of output based on the orientation + QSize outputResolution = adjustedViewfinderResolution; + const int rotation = currentCameraRotation(); + if (rotation == 90 || rotation == 270) + outputResolution.transpose(); + m_videoOutput->setVideoSize(outputResolution); + } // if preview is started, we have to stop it first before changing its size if (m_previewStarted && restartPreview) @@ -384,8 +393,7 @@ bool QAndroidCameraSession::startPreview() AndroidMultimediaUtils::enableOrientationListener(true); - // Use the default native orientation as the orientation for the preview - m_camera->setDisplayOrientation(m_nativeOrientation); + updateOrientation(); m_camera->startPreview(); m_previewStarted = true; @@ -425,19 +433,52 @@ void QAndroidCameraSession::setImageSettings(const QImageEncoderSettings &settin applyResolution(m_actualImageSettings.resolution()); } +void QAndroidCameraSession::updateOrientation() +{ + if (!m_camera) + return; + + m_camera->setDisplayOrientation(currentCameraRotation()); + applyResolution(m_actualImageSettings.resolution()); +} + + int QAndroidCameraSession::currentCameraRotation() const { if (!m_camera) return 0; - // subtract natural camera orientation and physical device orientation - int rotation = 0; - int deviceOrientation = (AndroidMultimediaUtils::getDeviceOrientation() + 45) / 90 * 90; - if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) - rotation = (m_nativeOrientation - deviceOrientation + 360) % 360; - else // back-facing camera - rotation = (m_nativeOrientation + deviceOrientation) % 360; + auto screen = QGuiApplication::primaryScreen(); + auto screenOrientation = screen->orientation(); + if (screenOrientation == Qt::PrimaryOrientation) + screenOrientation = screen->primaryOrientation(); + int deviceOrientation = 0; + switch (screenOrientation) { + case Qt::PrimaryOrientation: + case Qt::PortraitOrientation: + break; + case Qt::LandscapeOrientation: + deviceOrientation = 90; + break; + case Qt::InvertedPortraitOrientation: + deviceOrientation = 180; + break; + case Qt::InvertedLandscapeOrientation: + deviceOrientation = 270; + break; + } + + int nativeCameraOrientation = m_camera->getNativeOrientation(); + + int rotation; + // subtract natural camera orientation and physical device orientation + if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) { + rotation = (nativeCameraOrientation + deviceOrientation) % 360; + rotation = (360 - rotation) % 360; // compensate the mirror + } else { // back-facing camera + rotation = (nativeCameraOrientation - deviceOrientation + 360) % 360; + } return rotation; } diff --git a/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h b/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h index 83228b692..56674757d 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h +++ b/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h @@ -127,6 +127,7 @@ Q_SIGNALS: private Q_SLOTS: void onVideoOutputReady(bool ready); + void updateOrientation(); void onApplicationStateChanged(Qt::ApplicationState state); @@ -161,7 +162,6 @@ private: int m_selectedCamera; AndroidCamera *m_camera; - int m_nativeOrientation; QAndroidVideoOutput *m_videoOutput; bool m_active = false; diff --git a/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp b/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp index 2ee3512f0..e40921f38 100644 --- a/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp +++ b/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp @@ -1348,7 +1348,7 @@ void AndroidCameraPrivate::setFocusAreas(const QList<QRect> &areas) { const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex); - if (!m_parameters.isValid()) + if (!m_parameters.isValid() || areas.isEmpty()) return; QJniObject list; |