summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2013-11-29 17:16:44 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-12-05 19:28:16 +0100
commit13d7f835fad59fbda69bfa160e21f19d095ac8d5 (patch)
tree6c32fca0a5af8c855c3b19c1d723a3133608c05b
parent99bebdbb7dbdde259bc06e86079daebb17482c64 (diff)
Android: fix camera viewfinder orientation.
The camera sensor on Android devices might be in a different orientation than the device natural orientation. There is no API in Qt to know about the camera orientation, so correcting the viewfinder orientation is not possible without making guesses. This patch makes sure the viewfinder orientation always matches the device natural orientation. For example, if the camera is mounted in landscape, and the device natural orientation is portrait, the viewfinder will automatically be rotated 90 degrees counter-clockwise. Task-number: QTBUG-35086 Change-Id: Ia890872971d72657debe709f61edba27d09dec65 Reviewed-by: Christian Stromme <christian.stromme@digia.com>
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.cpp37
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.h3
-rw-r--r--src/plugins/android/src/wrappers/jcamera.cpp12
-rw-r--r--src/plugins/android/src/wrappers/jcamera.h4
4 files changed, 50 insertions, 6 deletions
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
index 3a50139c3..5ff19d1c1 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
@@ -92,6 +92,7 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent)
, m_selectedCamera(0)
, m_camera(0)
, m_nativeOrientation(0)
+ , m_previewOrientation(0)
, m_videoOutput(0)
, m_captureMode(QCamera::CaptureViewfinder)
, m_state(QCamera::UnloadedState)
@@ -183,10 +184,20 @@ bool QAndroidCameraSession::open()
connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed()));
connect(m_camera, SIGNAL(pictureCaptured(QByteArray)), this, SLOT(onCameraPictureCaptured(QByteArray)));
connect(m_camera, SIGNAL(previewFrameAvailable(QByteArray)), this, SLOT(onCameraPreviewFrameAvailable(QByteArray)));
+
m_nativeOrientation = m_camera->getNativeOrientation();
+
+ // Preview orientation will always match the device natural orientation
+ if (m_camera->getFacing() == JCamera::CameraFacingFront)
+ m_previewOrientation = 360 - m_nativeOrientation;
+ else
+ m_previewOrientation = m_nativeOrientation;
+
m_status = QCamera::LoadedStatus;
+
if (m_camera->getPreviewFormat() != JCamera::NV21)
m_camera->setPreviewFormat(JCamera::NV21);
+
emit opened();
} else {
m_status = QCamera::UnavailableStatus;
@@ -257,8 +268,16 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool
}
if (m_camera->previewSize() != viewfinderResolution) {
- if (m_videoOutput)
- m_videoOutput->setVideoSize(viewfinderResolution);
+ if (m_videoOutput) {
+ QSize size = viewfinderResolution;
+
+ // If the preview orientation is not the defaut one (0 or 180 degrees),
+ // we have to invert the output aspect ratio.
+ if (m_previewOrientation % 180)
+ size.transpose();
+
+ m_videoOutput->setVideoSize(size);
+ }
// if preview is started, we have to stop it first before changing its size
if (m_previewStarted && restartPreview)
@@ -282,6 +301,7 @@ void QAndroidCameraSession::startPreview()
applyImageSettings();
adjustViewfinderSize(m_imageSettings.resolution());
+ m_camera->setDisplayOrientation(m_previewOrientation);
if (m_videoOutput && m_videoOutput->isReady())
onVideoOutputReady(true);
@@ -558,10 +578,11 @@ void QAndroidCameraSession::onCameraPreviewFrameAvailable(const QByteArray &data
QtConcurrent::run(this, &QAndroidCameraSession::processPreviewImage,
m_currentImageCaptureId,
- data);
+ data,
+ m_camera->getRotation());
}
-void QAndroidCameraSession::processPreviewImage(int id, const QByteArray &data)
+void QAndroidCameraSession::processPreviewImage(int id, const QByteArray &data, int rotation)
{
QSize frameSize = m_camera->previewSize();
QImage preview(frameSize, QImage::Format_ARGB32);
@@ -570,11 +591,17 @@ void QAndroidCameraSession::processPreviewImage(int id, const QByteArray &data)
frameSize.width(),
frameSize.height());
+ QTransform transform;
+
// Preview display of front-facing cameras is flipped horizontally, but the frame data
// we get here is not. Flip it ourselves if the camera is front-facing to match what the user
// sees on the viewfinder.
if (m_camera->getFacing() == JCamera::CameraFacingFront)
- preview = preview.transformed(QTransform().scale(-1, 1));
+ transform.scale(-1, 1);
+
+ transform.rotate(rotation);
+
+ preview = preview.transformed(transform);
emit imageCaptured(id, preview);
}
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
index 897cf52d1..17ea4171f 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.h
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
@@ -124,7 +124,7 @@ private:
void stopPreview();
void applyImageSettings();
- void processPreviewImage(int id, const QByteArray &data);
+ void processPreviewImage(int id, const QByteArray &data, int rotation);
void processCapturedImage(int id,
const QByteArray &data,
const QSize &resolution,
@@ -134,6 +134,7 @@ private:
int m_selectedCamera;
JCamera *m_camera;
int m_nativeOrientation;
+ int m_previewOrientation;
QAndroidVideoOutput *m_videoOutput;
QCamera::CaptureModes m_captureMode;
diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp
index 2d42ffbd6..e69cb554d 100644
--- a/src/plugins/android/src/wrappers/jcamera.cpp
+++ b/src/plugins/android/src/wrappers/jcamera.cpp
@@ -118,6 +118,7 @@ JCamera::JCamera(int cameraId, jobject cam)
: QObject()
, QJNIObjectPrivate(cam)
, m_cameraId(cameraId)
+ , m_rotation(0)
, m_hasAPI14(false)
{
if (isValid()) {
@@ -205,6 +206,11 @@ int JCamera::getNativeOrientation()
return m_info.getField<jint>("orientation");
}
+void JCamera::setDisplayOrientation(int degrees)
+{
+ callMethod<void>("setDisplayOrientation", "(I)V", degrees);
+}
+
QSize JCamera::getPreferredPreviewSizeForVideo()
{
if (!m_parameters.isValid())
@@ -612,10 +618,16 @@ void JCamera::setRotation(int rotation)
if (!m_parameters.isValid())
return;
+ m_rotation = rotation;
m_parameters.callMethod<void>("setRotation", "(I)V", rotation);
applyParameters();
}
+int JCamera::getRotation() const
+{
+ return m_rotation;
+}
+
QList<QSize> JCamera::getSupportedPictureSizes()
{
QList<QSize> list;
diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jcamera.h
index 464ca3cb2..7c47ec7a2 100644
--- a/src/plugins/android/src/wrappers/jcamera.h
+++ b/src/plugins/android/src/wrappers/jcamera.h
@@ -82,6 +82,8 @@ public:
CameraFacing getFacing();
int getNativeOrientation();
+ void setDisplayOrientation(int degrees);
+
QSize getPreferredPreviewSizeForVideo();
QList<QSize> getSupportedPreviewSizes();
@@ -136,6 +138,7 @@ public:
void setWhiteBalance(const QString &value);
void setRotation(int rotation);
+ int getRotation() const;
QList<QSize> getSupportedPictureSizes();
void setPictureSize(const QSize &size);
@@ -174,6 +177,7 @@ private:
QJNIObjectPrivate m_parameters;
QSize m_previewSize;
+ int m_rotation;
bool m_hasAPI14;
};