summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/android/src/mediacapture/mediacapture.pri2
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.cpp231
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.h22
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp8
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcaptureservice.h3
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcapturesession.cpp2
-rw-r--r--src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.cpp83
-rw-r--r--src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.h65
-rw-r--r--src/plugins/android/src/wrappers/jni/androidcamera.cpp121
-rw-r--r--src/plugins/android/src/wrappers/jni/androidcamera.h27
-rw-r--r--tests/auto/integration/qaudioinput/BLACKLIST1
-rw-r--r--tests/auto/integration/qmediaplayerbackend/BLACKLIST1
12 files changed, 521 insertions, 45 deletions
diff --git a/src/plugins/android/src/mediacapture/mediacapture.pri b/src/plugins/android/src/mediacapture/mediacapture.pri
index 2811f0371..a42a6a40c 100644
--- a/src/plugins/android/src/mediacapture/mediacapture.pri
+++ b/src/plugins/android/src/mediacapture/mediacapture.pri
@@ -14,6 +14,7 @@ SOURCES += \
$$PWD/qandroidcameracapturebufferformatcontrol.cpp \
$$PWD/qandroidcameraflashcontrol.cpp \
$$PWD/qandroidcamerafocuscontrol.cpp \
+ $$PWD/qandroidviewfindersettingscontrol.cpp \
$$PWD/qandroidcameralockscontrol.cpp \
$$PWD/qandroidcapturesession.cpp \
$$PWD/qandroidmediarecordercontrol.cpp \
@@ -39,6 +40,7 @@ HEADERS += \
$$PWD/qandroidcameracapturebufferformatcontrol.h \
$$PWD/qandroidcameraflashcontrol.h \
$$PWD/qandroidcamerafocuscontrol.h \
+ $$PWD/qandroidviewfindersettingscontrol.h \
$$PWD/qandroidcameralockscontrol.h \
$$PWD/qandroidcapturesession.h \
$$PWD/qandroidmediarecordercontrol.h \
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
index b44c0fe9f..9137fbc05 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
@@ -67,7 +68,6 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent)
, m_savedState(-1)
, m_status(QCamera::UnloadedStatus)
, m_previewStarted(false)
- , m_imageSettingsDirty(true)
, m_captureDestination(QCameraImageCapture::CaptureToFile)
, m_captureImageDriveMode(QCameraImageCapture::SingleImageCapture)
, m_lastImageCaptureId(0)
@@ -100,7 +100,7 @@ void QAndroidCameraSession::setCaptureMode(QCamera::CaptureModes mode)
emit captureModeChanged(m_captureMode);
if (m_previewStarted && m_captureMode.testFlag(QCamera::CaptureStillImage))
- adjustViewfinderSize(m_imageSettings.resolution());
+ applyViewfinderSettings(m_actualImageSettings.resolution());
}
bool QAndroidCameraSession::isCaptureModeSupported(QCamera::CaptureModes mode) const
@@ -223,7 +223,8 @@ void QAndroidCameraSession::close()
m_readyForCapture = false;
m_currentImageCaptureId = -1;
m_currentImageCaptureFileName.clear();
- m_imageSettingsDirty = true;
+ m_actualImageSettings = m_requestedImageSettings;
+ m_actualViewfinderSettings = m_requestedViewfinderSettings;
m_camera->release();
delete m_camera;
@@ -251,37 +252,108 @@ void QAndroidCameraSession::setVideoOutput(QAndroidVideoOutput *output)
}
}
-void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool restartPreview)
+void QAndroidCameraSession::setViewfinderSettings(const QCameraViewfinderSettings &settings)
+{
+ if (m_requestedViewfinderSettings == settings)
+ return;
+
+ m_requestedViewfinderSettings = m_actualViewfinderSettings = settings;
+
+ if (m_readyForCapture)
+ applyViewfinderSettings();
+}
+
+void QAndroidCameraSession::applyViewfinderSettings(const QSize &captureSize, bool restartPreview)
{
if (!m_camera)
return;
- QSize currentViewfinderResolution = m_camera->previewSize();
- QSize adjustedViewfinderResolution;
+ const QSize currentViewfinderResolution = m_camera->previewSize();
+ const AndroidCamera::ImageFormat currentPreviewFormat = m_camera->getPreviewFormat();
+ const AndroidCamera::FpsRange currentFpsRange = m_camera->getPreviewFpsRange();
- if (m_captureMode.testFlag(QCamera::CaptureVideo) && m_camera->getPreferredPreviewSizeForVideo().isEmpty()) {
+ // -- adjust resolution
+ QSize adjustedViewfinderResolution;
+ const bool validCaptureSize = captureSize.width() > 0 && captureSize.height() > 0;
+ if (m_captureMode.testFlag(QCamera::CaptureVideo)
+ && validCaptureSize
+ && m_camera->getPreferredPreviewSizeForVideo().isEmpty()) {
// According to the Android doc, if getPreferredPreviewSizeForVideo() returns null, it means
// the preview size cannot be different from the capture size
adjustedViewfinderResolution = captureSize;
} else {
- // search for viewfinder resolution with the same aspect ratio
- const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height());
- QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes();
- for (int i = previewSizes.count() - 1; i >= 0; --i) {
- const QSize &size = previewSizes.at(i);
- if (qAbs(aspectRatio - (qreal(size.width()) / size.height())) < 0.01) {
- adjustedViewfinderResolution = size;
- break;
+ qreal captureAspectRatio = 0;
+ if (validCaptureSize)
+ captureAspectRatio = qreal(captureSize.width()) / qreal(captureSize.height());
+
+ const QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes();
+
+ const QSize vfRes = m_requestedViewfinderSettings.resolution();
+ if (vfRes.width() > 0 && vfRes.height() > 0
+ && (!validCaptureSize || qAbs(captureAspectRatio - (qreal(vfRes.width()) / vfRes.height())) < 0.01)
+ && previewSizes.contains(vfRes)) {
+ adjustedViewfinderResolution = vfRes;
+ } else if (validCaptureSize) {
+ // search for viewfinder resolution with the same aspect ratio
+ for (int i = previewSizes.count() - 1; i >= 0; --i) {
+ const QSize &size = previewSizes.at(i);
+ if (qAbs(captureAspectRatio - (qreal(size.width()) / size.height())) < 0.01) {
+ adjustedViewfinderResolution = size;
+ break;
+ }
+ }
+ if (!adjustedViewfinderResolution.isValid()) {
+ qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio.");
+ return;
}
+ } else {
+ adjustedViewfinderResolution = previewSizes.last();
}
+ }
+ m_actualViewfinderSettings.setResolution(adjustedViewfinderResolution);
- if (!adjustedViewfinderResolution.isValid()) {
- qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio.");
- return;
+ // -- adjust pixel format
+
+ AndroidCamera::ImageFormat adjustedPreviewFormat = AndroidCamera::NV21;
+ if (m_requestedViewfinderSettings.pixelFormat() != QVideoFrame::Format_Invalid) {
+ const AndroidCamera::ImageFormat f = AndroidImageFormatFromQtPixelFormat(m_requestedViewfinderSettings.pixelFormat());
+ if (f == AndroidCamera::UnknownImageFormat || !m_camera->getSupportedPreviewFormats().contains(f))
+ qWarning("Unsupported viewfinder pixel format");
+ else
+ adjustedPreviewFormat = f;
+ }
+ m_actualViewfinderSettings.setPixelFormat(QtPixelFormatFromAndroidImageFormat(adjustedPreviewFormat));
+
+ // -- adjust FPS
+
+ AndroidCamera::FpsRange adjustedFps = currentFpsRange;
+ const AndroidCamera::FpsRange requestedFpsRange = AndroidCamera::FpsRange::makeFromQReal(m_requestedViewfinderSettings.minimumFrameRate(),
+ m_requestedViewfinderSettings.maximumFrameRate());
+ if (requestedFpsRange.min > 0 || requestedFpsRange.max > 0) {
+ int minDist = INT_MAX;
+ const QList<AndroidCamera::FpsRange> supportedFpsRanges = m_camera->getSupportedPreviewFpsRange();
+ auto it = supportedFpsRanges.rbegin(), end = supportedFpsRanges.rend();
+ for (; it != end; ++it) {
+ int dist = (requestedFpsRange.min > 0 ? qAbs(requestedFpsRange.min - it->min) : 0)
+ + (requestedFpsRange.max > 0 ? qAbs(requestedFpsRange.max - it->max) : 0);
+ if (dist < minDist) {
+ minDist = dist;
+ adjustedFps = *it;
+ if (minDist == 0)
+ break; // exact match
+ }
}
}
+ m_actualViewfinderSettings.setMinimumFrameRate(adjustedFps.getMinReal());
+ m_actualViewfinderSettings.setMaximumFrameRate(adjustedFps.getMaxReal());
+
+ // -- Set values on camera
+
+ if (currentViewfinderResolution != adjustedViewfinderResolution
+ || currentPreviewFormat != adjustedPreviewFormat
+ || currentFpsRange.min != adjustedFps.min
+ || currentFpsRange.max != adjustedFps.max) {
- if (currentViewfinderResolution != adjustedViewfinderResolution) {
if (m_videoOutput)
m_videoOutput->setVideoSize(adjustedViewfinderResolution);
@@ -290,6 +362,8 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool
m_camera->stopPreview();
m_camera->setPreviewSize(adjustedViewfinderResolution);
+ m_camera->setPreviewFormat(adjustedPreviewFormat);
+ m_camera->setPreviewFpsRange(adjustedFps);
// restart preview
if (m_previewStarted && restartPreview)
@@ -297,6 +371,36 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool
}
}
+QList<QSize> QAndroidCameraSession::getSupportedPreviewSizes() const
+{
+ return m_camera ? m_camera->getSupportedPreviewSizes() : QList<QSize>();
+}
+
+QList<QVideoFrame::PixelFormat> QAndroidCameraSession::getSupportedPixelFormats() const
+{
+ QList<QVideoFrame::PixelFormat> formats;
+
+ if (!m_camera)
+ return formats;
+
+ const QList<AndroidCamera::ImageFormat> nativeFormats = m_camera->getSupportedPreviewFormats();
+
+ formats.reserve(nativeFormats.size());
+
+ for (AndroidCamera::ImageFormat nativeFormat : nativeFormats) {
+ QVideoFrame::PixelFormat format = QtPixelFormatFromAndroidImageFormat(nativeFormat);
+ if (format != QVideoFrame::Format_Invalid)
+ formats.append(format);
+ }
+
+ return formats;
+}
+
+QList<AndroidCamera::FpsRange> QAndroidCameraSession::getSupportedPreviewFpsRange() const
+{
+ return m_camera ? m_camera->getSupportedPreviewFpsRange() : QList<AndroidCamera::FpsRange>();
+}
+
bool QAndroidCameraSession::startPreview()
{
if (!m_camera)
@@ -323,7 +427,8 @@ bool QAndroidCameraSession::startPreview()
emit statusChanged(m_status);
applyImageSettings();
- adjustViewfinderSize(m_imageSettings.resolution());
+ applyViewfinderSettings(m_captureMode.testFlag(QCamera::CaptureStillImage) ? m_actualImageSettings.resolution()
+ : QSize());
AndroidMultimediaUtils::enableOrientationListener(true);
@@ -357,19 +462,15 @@ void QAndroidCameraSession::stopPreview()
void QAndroidCameraSession::setImageSettings(const QImageEncoderSettings &settings)
{
- if (m_imageSettings == settings)
+ if (m_requestedImageSettings == settings)
return;
- m_imageSettings = settings;
- if (m_imageSettings.codec().isEmpty())
- m_imageSettings.setCodec(QLatin1String("jpeg"));
-
- m_imageSettingsDirty = true;
+ m_requestedImageSettings = m_actualImageSettings = settings;
applyImageSettings();
if (m_readyForCapture && m_captureMode.testFlag(QCamera::CaptureStillImage))
- adjustViewfinderSize(m_imageSettings.resolution());
+ applyViewfinderSettings(m_actualImageSettings.resolution());
}
int QAndroidCameraSession::currentCameraRotation() const
@@ -426,15 +527,32 @@ void QAndroidCameraSession::setPreviewCallback(PreviewCallback *callback)
void QAndroidCameraSession::applyImageSettings()
{
- if (!m_camera || !m_imageSettingsDirty)
+ if (!m_camera)
return;
- const QSize requestedResolution = m_imageSettings.resolution();
- const QList<QSize> supportedResolutions = m_camera->getSupportedPictureSizes();
+ if (m_actualImageSettings.codec().isEmpty())
+ m_actualImageSettings.setCodec(QLatin1String("jpeg"));
+ const QSize requestedResolution = m_requestedImageSettings.resolution();
+ const QList<QSize> supportedResolutions = m_camera->getSupportedPictureSizes();
if (!requestedResolution.isValid()) {
- // if no resolution is set, use the highest supported one
- m_imageSettings.setResolution(supportedResolutions.last());
+ // if the viewfinder resolution is explicitly set, pick the highest available capture
+ // resolution with the same aspect ratio
+ if (m_requestedViewfinderSettings.resolution().isValid()) {
+ const QSize vfResolution = m_actualViewfinderSettings.resolution();
+ const qreal vfAspectRatio = qreal(vfResolution.width()) / vfResolution.height();
+
+ auto it = supportedResolutions.rbegin(), end = supportedResolutions.rend();
+ for (; it != end; ++it) {
+ if (qAbs(vfAspectRatio - (qreal(it->width()) / it->height())) < 0.01) {
+ m_actualImageSettings.setResolution(*it);
+ break;
+ }
+ }
+ } else {
+ // otherwise, use the highest supported one
+ m_actualImageSettings.setResolution(supportedResolutions.last());
+ }
} else if (!supportedResolutions.contains(requestedResolution)) {
// if the requested resolution is not supported, find the closest one
int reqPixelCount = requestedResolution.width() * requestedResolution.height();
@@ -444,11 +562,12 @@ void QAndroidCameraSession::applyImageSettings()
supportedPixelCounts.append(s.width() * s.height());
}
int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount);
- m_imageSettings.setResolution(supportedResolutions.at(closestIndex));
+ m_actualImageSettings.setResolution(supportedResolutions.at(closestIndex));
}
+ m_camera->setPictureSize(m_actualImageSettings.resolution());
int jpegQuality = 100;
- switch (m_imageSettings.quality()) {
+ switch (m_requestedImageSettings.quality()) {
case QMultimedia::VeryLowQuality:
jpegQuality = 20;
break;
@@ -465,11 +584,7 @@ void QAndroidCameraSession::applyImageSettings()
jpegQuality = 100;
break;
}
-
- m_camera->setPictureSize(m_imageSettings.resolution());
m_camera->setJpegQuality(jpegQuality);
-
- m_imageSettingsDirty = false;
}
bool QAndroidCameraSession::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
@@ -531,7 +646,7 @@ int QAndroidCameraSession::capture(const QString &fileName)
m_currentImageCaptureFileName = fileName;
applyImageSettings();
- adjustViewfinderSize(m_imageSettings.resolution());
+ applyViewfinderSettings(m_actualImageSettings.resolution());
// adjust picture rotation depending on the device orientation
m_camera->setRotation(currentCameraRotation());
@@ -610,7 +725,7 @@ void QAndroidCameraSession::onCameraPictureCaptured(const QByteArray &data)
QtConcurrent::run(this, &QAndroidCameraSession::processCapturedImage,
m_currentImageCaptureId,
data,
- m_imageSettings.resolution(),
+ m_actualImageSettings.resolution(),
m_captureDestination,
m_currentImageCaptureFileName);
}
@@ -702,6 +817,42 @@ void QAndroidCameraSession::processCapturedImage(int id,
}
}
+QVideoFrame::PixelFormat QAndroidCameraSession::QtPixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat format)
+{
+ switch (format) {
+ case AndroidCamera::RGB565:
+ return QVideoFrame::Format_RGB565;
+ case AndroidCamera::NV21:
+ return QVideoFrame::Format_NV21;
+ case AndroidCamera::YUY2:
+ return QVideoFrame::Format_YUYV;
+ case AndroidCamera::JPEG:
+ return QVideoFrame::Format_Jpeg;
+ case AndroidCamera::YV12:
+ return QVideoFrame::Format_YV12;
+ default:
+ return QVideoFrame::Format_Invalid;
+ }
+}
+
+AndroidCamera::ImageFormat QAndroidCameraSession::AndroidImageFormatFromQtPixelFormat(QVideoFrame::PixelFormat format)
+{
+ switch (format) {
+ case QVideoFrame::Format_RGB565:
+ return AndroidCamera::RGB565;
+ case QVideoFrame::Format_NV21:
+ return AndroidCamera::NV21;
+ case QVideoFrame::Format_YUYV:
+ return AndroidCamera::YUY2;
+ case QVideoFrame::Format_Jpeg:
+ return AndroidCamera::JPEG;
+ case QVideoFrame::Format_YV12:
+ return AndroidCamera::YV12;
+ default:
+ return AndroidCamera::UnknownImageFormat;
+ }
+}
+
void QAndroidCameraSession::onVideoOutputReady(bool ready)
{
if (ready && m_state == QCamera::ActiveState)
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
index 9bc14277d..d08f2f6ac 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.h
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
@@ -74,11 +75,18 @@ public:
void setCaptureMode(QCamera::CaptureModes mode);
bool isCaptureModeSupported(QCamera::CaptureModes mode) const;
+ QCameraViewfinderSettings viewfinderSettings() const { return m_actualViewfinderSettings; }
+ void setViewfinderSettings(const QCameraViewfinderSettings &settings);
+ void applyViewfinderSettings(const QSize &captureSize = QSize(), bool restartPreview = true);
+
QAndroidVideoOutput *videoOutput() const { return m_videoOutput; }
void setVideoOutput(QAndroidVideoOutput *output);
- void adjustViewfinderSize(const QSize &captureSize, bool restartPreview = true);
- QImageEncoderSettings imageSettings() const { return m_imageSettings; }
+ QList<QSize> getSupportedPreviewSizes() const;
+ QList<QVideoFrame::PixelFormat> getSupportedPixelFormats() const;
+ QList<AndroidCamera::FpsRange> getSupportedPreviewFpsRange() const;
+
+ QImageEncoderSettings imageSettings() const { return m_actualImageSettings; }
void setImageSettings(const QImageEncoderSettings &settings);
bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const;
@@ -154,6 +162,9 @@ private:
QCameraImageCapture::CaptureDestinations dest,
const QString &fileName);
+ static QVideoFrame::PixelFormat QtPixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat);
+ static AndroidCamera::ImageFormat AndroidImageFormatFromQtPixelFormat(QVideoFrame::PixelFormat);
+
int m_selectedCamera;
AndroidCamera *m_camera;
int m_nativeOrientation;
@@ -165,8 +176,11 @@ private:
QCamera::Status m_status;
bool m_previewStarted;
- QImageEncoderSettings m_imageSettings;
- bool m_imageSettingsDirty;
+ QCameraViewfinderSettings m_requestedViewfinderSettings;
+ QCameraViewfinderSettings m_actualViewfinderSettings;
+
+ QImageEncoderSettings m_requestedImageSettings;
+ QImageEncoderSettings m_actualImageSettings;
QCameraImageCapture::CaptureDestinations m_captureDestination;
QCameraImageCapture::DriveMode m_captureImageDriveMode;
int m_lastImageCaptureId;
diff --git a/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp b/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp
index caade58d2..65df54c3f 100644
--- a/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
@@ -51,6 +52,7 @@
#include "qandroidcameraexposurecontrol.h"
#include "qandroidcameraflashcontrol.h"
#include "qandroidcamerafocuscontrol.h"
+#include "qandroidviewfindersettingscontrol.h"
#include "qandroidcameralockscontrol.h"
#include "qandroidcameraimageprocessingcontrol.h"
#include "qandroidimageencodercontrol.h"
@@ -80,6 +82,7 @@ QAndroidCaptureService::QAndroidCaptureService(const QString &service, QObject *
m_cameraExposureControl = new QAndroidCameraExposureControl(m_cameraSession);
m_cameraFlashControl = new QAndroidCameraFlashControl(m_cameraSession);
m_cameraFocusControl = new QAndroidCameraFocusControl(m_cameraSession);
+ m_viewfinderSettingsControl2 = new QAndroidViewfinderSettingsControl2(m_cameraSession);
m_cameraLocksControl = new QAndroidCameraLocksControl(m_cameraSession);
m_cameraImageProcessingControl = new QAndroidCameraImageProcessingControl(m_cameraSession);
m_imageEncoderControl = new QAndroidImageEncoderControl(m_cameraSession);
@@ -96,6 +99,7 @@ QAndroidCaptureService::QAndroidCaptureService(const QString &service, QObject *
m_cameraExposureControl = 0;
m_cameraFlashControl = 0;
m_cameraFocusControl = 0;
+ m_viewfinderSettingsControl2 = 0;
m_cameraLocksControl = 0;
m_cameraImageProcessingControl = 0;
m_imageEncoderControl = 0;
@@ -134,6 +138,7 @@ QAndroidCaptureService::~QAndroidCaptureService()
delete m_cameraExposureControl;
delete m_cameraFlashControl;
delete m_cameraFocusControl;
+ delete m_viewfinderSettingsControl2;
delete m_cameraLocksControl;
delete m_cameraImageProcessingControl;
delete m_imageEncoderControl;
@@ -181,6 +186,9 @@ QMediaControl *QAndroidCaptureService::requestControl(const char *name)
if (qstrcmp(name, QCameraFocusControl_iid) == 0)
return m_cameraFocusControl;
+ if (qstrcmp(name, QCameraViewfinderSettingsControl2_iid) == 0)
+ return m_viewfinderSettingsControl2;
+
if (qstrcmp(name, QCameraLocksControl_iid) == 0)
return m_cameraLocksControl;
diff --git a/src/plugins/android/src/mediacapture/qandroidcaptureservice.h b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h
index 7240bce6b..85816fdd6 100644
--- a/src/plugins/android/src/mediacapture/qandroidcaptureservice.h
+++ b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
@@ -57,6 +58,7 @@ class QAndroidCameraZoomControl;
class QAndroidCameraExposureControl;
class QAndroidCameraFlashControl;
class QAndroidCameraFocusControl;
+class QAndroidViewfinderSettingsControl2;
class QAndroidCameraLocksControl;
class QAndroidCameraImageProcessingControl;
class QAndroidImageEncoderControl;
@@ -93,6 +95,7 @@ private:
QAndroidCameraExposureControl *m_cameraExposureControl;
QAndroidCameraFlashControl *m_cameraFlashControl;
QAndroidCameraFocusControl *m_cameraFocusControl;
+ QAndroidViewfinderSettingsControl2 *m_viewfinderSettingsControl2;
QAndroidCameraLocksControl *m_cameraLocksControl;
QAndroidCameraImageProcessingControl *m_cameraImageProcessingControl;
QAndroidImageEncoderControl *m_imageEncoderControl;
diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
index 92a020882..9e38c8539 100644
--- a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
@@ -436,7 +436,7 @@ void QAndroidCaptureSession::applySettings()
void QAndroidCaptureSession::updateViewfinder()
{
m_cameraSession->camera()->stopPreviewSynchronous();
- m_cameraSession->adjustViewfinderSize(m_videoSettings.resolution(), false);
+ m_cameraSession->applyViewfinderSettings(m_videoSettings.resolution(), false);
}
void QAndroidCaptureSession::restartViewfinder()
diff --git a/src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.cpp
new file mode 100644
index 000000000..2a2882cb9
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidviewfindersettingscontrol.h"
+#include "qandroidcamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidViewfinderSettingsControl2::QAndroidViewfinderSettingsControl2(QAndroidCameraSession *session)
+ : m_cameraSession(session)
+{
+}
+
+QList<QCameraViewfinderSettings> QAndroidViewfinderSettingsControl2::supportedViewfinderSettings() const
+{
+ QList<QCameraViewfinderSettings> viewfinderSettings;
+
+ const QList<QSize> previewSizes = m_cameraSession->getSupportedPreviewSizes();
+ const QList<QVideoFrame::PixelFormat> pixelFormats = m_cameraSession->getSupportedPixelFormats();
+ const QList<AndroidCamera::FpsRange> fpsRanges = m_cameraSession->getSupportedPreviewFpsRange();
+
+ viewfinderSettings.reserve(previewSizes.size() * pixelFormats.size() * fpsRanges.size());
+
+ for (const QSize& size : previewSizes) {
+ for (QVideoFrame::PixelFormat pixelFormat : pixelFormats) {
+ for (const AndroidCamera::FpsRange& fpsRange : fpsRanges) {
+ QCameraViewfinderSettings s;
+ s.setResolution(size);
+ s.setPixelAspectRatio(QSize(1, 1));
+ s.setPixelFormat(pixelFormat);
+ s.setMinimumFrameRate(fpsRange.getMinReal());
+ s.setMaximumFrameRate(fpsRange.getMaxReal());
+ viewfinderSettings << s;
+ }
+ }
+ }
+ return viewfinderSettings;
+}
+
+QCameraViewfinderSettings QAndroidViewfinderSettingsControl2::viewfinderSettings() const
+{
+ return m_cameraSession->viewfinderSettings();
+}
+
+void QAndroidViewfinderSettingsControl2::setViewfinderSettings(const QCameraViewfinderSettings &settings)
+{
+ m_cameraSession->setViewfinderSettings(settings);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qandroidviewfindersettingscontrol.cpp"
diff --git a/src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.h b/src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.h
new file mode 100644
index 000000000..a6bf70857
--- /dev/null
+++ b/src/plugins/android/src/mediacapture/qandroidviewfindersettingscontrol.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDVIEWFINDERSETTINGSCONTROL_H
+#define QANDROIDVIEWFINDERSETTINGSCONTROL_H
+
+#include <QtMultimedia/qcameraviewfindersettingscontrol.h>
+#include <QtMultimedia/qcameraviewfindersettings.h>
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidCameraSession;
+
+class QAndroidViewfinderSettingsControl2 : public QCameraViewfinderSettingsControl2
+{
+ Q_OBJECT
+public:
+ explicit QAndroidViewfinderSettingsControl2(QAndroidCameraSession *session);
+
+ QList<QCameraViewfinderSettings> supportedViewfinderSettings() const Q_DECL_OVERRIDE;
+ QCameraViewfinderSettings viewfinderSettings() const Q_DECL_OVERRIDE;
+ void setViewfinderSettings(const QCameraViewfinderSettings &settings) Q_DECL_OVERRIDE;
+
+private:
+ QAndroidCameraSession *m_cameraSession;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDVIEWFINDERSETTINGSCONTROL_H
diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp
index 476fb8957..fd5522e10 100644
--- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
@@ -171,11 +172,17 @@ public:
Q_INVOKABLE QSize getPreferredPreviewSizeForVideo();
Q_INVOKABLE QList<QSize> getSupportedPreviewSizes();
+ Q_INVOKABLE QList<AndroidCamera::FpsRange> getSupportedPreviewFpsRange();
+
+ Q_INVOKABLE AndroidCamera::FpsRange getPreviewFpsRange();
+ Q_INVOKABLE void setPreviewFpsRange(int min, int max);
+
Q_INVOKABLE AndroidCamera::ImageFormat getPreviewFormat();
Q_INVOKABLE void setPreviewFormat(AndroidCamera::ImageFormat fmt);
Q_INVOKABLE QList<AndroidCamera::ImageFormat> getSupportedPreviewFormats();
Q_INVOKABLE QSize previewSize() const { return m_previewSize; }
+ Q_INVOKABLE QSize getPreviewSize();
Q_INVOKABLE void updatePreviewSize();
Q_INVOKABLE bool setPreviewTexture(void *surfaceTexture);
Q_INVOKABLE bool setPreviewDisplay(void *surfaceHolder);
@@ -380,6 +387,24 @@ QList<QSize> AndroidCamera::getSupportedPreviewSizes()
return d->getSupportedPreviewSizes();
}
+QList<AndroidCamera::FpsRange> AndroidCamera::getSupportedPreviewFpsRange()
+{
+ Q_D(AndroidCamera);
+ return d->getSupportedPreviewFpsRange();
+}
+
+AndroidCamera::FpsRange AndroidCamera::getPreviewFpsRange()
+{
+ Q_D(AndroidCamera);
+ return d->getPreviewFpsRange();
+}
+
+void AndroidCamera::setPreviewFpsRange(FpsRange range)
+{
+ Q_D(AndroidCamera);
+ QMetaObject::invokeMethod(d, "setPreviewFpsRange", Q_ARG(int, range.min), Q_ARG(int, range.max));
+}
+
AndroidCamera::ImageFormat AndroidCamera::getPreviewFormat()
{
Q_D(AndroidCamera);
@@ -404,6 +429,12 @@ QSize AndroidCamera::previewSize() const
return d->m_previewSize;
}
+QSize AndroidCamera::actualPreviewSize()
+{
+ Q_D(AndroidCamera);
+ return d->getPreviewSize();
+}
+
void AndroidCamera::setPreviewSize(const QSize &size)
{
Q_D(AndroidCamera);
@@ -877,6 +908,80 @@ QList<QSize> AndroidCameraPrivate::getSupportedPreviewSizes()
return list;
}
+QList<AndroidCamera::FpsRange> AndroidCameraPrivate::getSupportedPreviewFpsRange()
+{
+ QMutexLocker parametersLocker(&m_parametersMutex);
+
+ QJNIEnvironmentPrivate env;
+
+ QList<AndroidCamera::FpsRange> rangeList;
+
+ if (m_parameters.isValid()) {
+ QJNIObjectPrivate rangeListNative = m_parameters.callObjectMethod("getSupportedPreviewFpsRange",
+ "()Ljava/util/List;");
+ int count = rangeListNative.callMethod<jint>("size");
+
+ rangeList.reserve(count);
+
+ for (int i = 0; i < count; ++i) {
+ QJNIObjectPrivate range = rangeListNative.callObjectMethod("get",
+ "(I)Ljava/lang/Object;",
+ i);
+
+ jintArray jRange = static_cast<jintArray>(range.object());
+ jint* rangeArray = env->GetIntArrayElements(jRange, 0);
+
+ AndroidCamera::FpsRange fpsRange;
+
+ fpsRange.min = rangeArray[0];
+ fpsRange.max = rangeArray[1];
+
+ env->ReleaseIntArrayElements(jRange, rangeArray, 0);
+
+ rangeList << fpsRange;
+ }
+ }
+
+ return rangeList;
+}
+
+AndroidCamera::FpsRange AndroidCameraPrivate::getPreviewFpsRange()
+{
+ QMutexLocker parametersLocker(&m_parametersMutex);
+
+ QJNIEnvironmentPrivate env;
+
+ AndroidCamera::FpsRange range;
+
+ if (!m_parameters.isValid())
+ return range;
+
+ jintArray jRangeArray = env->NewIntArray(2);
+ m_parameters.callMethod<void>("getPreviewFpsRange", "([I)V", jRangeArray);
+
+ jint* jRangeElements = env->GetIntArrayElements(jRangeArray, 0);
+
+ range.min = jRangeElements[0];
+ range.max = jRangeElements[1];
+
+ env->ReleaseIntArrayElements(jRangeArray, jRangeElements, 0);
+ env->DeleteLocalRef(jRangeArray);
+
+ return range;
+}
+
+void AndroidCameraPrivate::setPreviewFpsRange(int min, int max)
+{
+ QMutexLocker parametersLocker(&m_parametersMutex);
+
+ if (!m_parameters.isValid())
+ return;
+
+ QJNIEnvironmentPrivate env;
+ m_parameters.callMethod<void>("setPreviewFpsRange", "(II)V", min, max);
+ exceptionCheckAndClear(env);
+}
+
AndroidCamera::ImageFormat AndroidCameraPrivate::getPreviewFormat()
{
QMutexLocker parametersLocker(&m_parametersMutex);
@@ -919,6 +1024,22 @@ QList<AndroidCamera::ImageFormat> AndroidCameraPrivate::getSupportedPreviewForma
return list;
}
+QSize AndroidCameraPrivate::getPreviewSize()
+{
+ QMutexLocker parametersLocker(&m_parametersMutex);
+
+ if (!m_parameters.isValid())
+ return QSize();
+
+ QJNIObjectPrivate size = m_parameters.callObjectMethod("getPreviewSize",
+ "()Landroid/hardware/Camera$Size;");
+
+ if (!size.isValid())
+ return QSize();
+
+ return QSize(size.getField<jint>("width"), size.getField<jint>("height"));
+}
+
void AndroidCameraPrivate::updatePreviewSize()
{
QMutexLocker parametersLocker(&m_parametersMutex);
diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.h b/src/plugins/android/src/wrappers/jni/androidcamera.h
index 788da82da..f4694d7dc 100644
--- a/src/plugins/android/src/wrappers/jni/androidcamera.h
+++ b/src/plugins/android/src/wrappers/jni/androidcamera.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ruslan Baratov
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
@@ -83,6 +84,26 @@ public:
YV12 = 842094169
};
+ // http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getSupportedPreviewFpsRange%28%29
+ // "The values are multiplied by 1000 and represented in integers"
+ struct FpsRange {
+ int min;
+ int max;
+
+ FpsRange(): min(0), max(0) {}
+
+ qreal getMinReal() const { return min / 1000.0; }
+ qreal getMaxReal() const { return max / 1000.0; }
+
+ static FpsRange makeFromQReal(qreal min, qreal max)
+ {
+ FpsRange range;
+ range.min = static_cast<int>(min * 1000.0);
+ range.max = static_cast<int>(max * 1000.0);
+ return range;
+ }
+ };
+
~AndroidCamera();
static AndroidCamera *open(int cameraId);
@@ -100,11 +121,17 @@ public:
QSize getPreferredPreviewSizeForVideo();
QList<QSize> getSupportedPreviewSizes();
+ QList<FpsRange> getSupportedPreviewFpsRange();
+
+ FpsRange getPreviewFpsRange();
+ void setPreviewFpsRange(FpsRange);
+
ImageFormat getPreviewFormat();
void setPreviewFormat(ImageFormat fmt);
QList<ImageFormat> getSupportedPreviewFormats();
QSize previewSize() const;
+ QSize actualPreviewSize();
void setPreviewSize(const QSize &size);
bool setPreviewTexture(AndroidSurfaceTexture *surfaceTexture);
bool setPreviewDisplay(AndroidSurfaceHolder *surfaceHolder);
diff --git a/tests/auto/integration/qaudioinput/BLACKLIST b/tests/auto/integration/qaudioinput/BLACKLIST
index f6a8a670f..ab3f9e037 100644
--- a/tests/auto/integration/qaudioinput/BLACKLIST
+++ b/tests/auto/integration/qaudioinput/BLACKLIST
@@ -3,5 +3,6 @@
redhatenterpriselinuxworkstation-6.6
rhel-7.2
ubuntu-14.04
+ubuntu-16.04
opensuse-13.1
opensuse-42.1
diff --git a/tests/auto/integration/qmediaplayerbackend/BLACKLIST b/tests/auto/integration/qmediaplayerbackend/BLACKLIST
index 7ce72c7ac..43b8e8b26 100644
--- a/tests/auto/integration/qmediaplayerbackend/BLACKLIST
+++ b/tests/auto/integration/qmediaplayerbackend/BLACKLIST
@@ -23,6 +23,7 @@ opensuse-13.1 64bit
redhatenterpriselinuxworkstation-6.6
rhel-7.1
ubuntu-14.04 64bit
+ubuntu-16.04 64bit
windows 64bit developer-build
rhel-7.2