summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Gehör <pekka.gehor@qt.io>2021-09-17 12:50:25 +0300
committerPekka Gehör <pekka.gehor@qt.io>2021-10-01 13:00:32 +0300
commit63c658966f8ce5083853f517fe855e47eec6153e (patch)
tree745a718868a1de6e0d7c361d4b8d5cd28871a63a
parent148698ed27c3d4ac133a83c4b1c563fe2f9ed413 (diff)
Android: Fix video sizes and formats returned from Camera
After the fix, we get a list of available resolutions and frame rates of the camera. This also fixes the code in the widgets camera example that uses the video resolutions and frame rates. Task-number: QTBUG-96097 Change-Id: Ie5fa1e89f658f0c816015944fa5a4c1f34625c12 Reviewed-by: Samuel Mira <samuel.mira@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit bf455a536148af767bff45ee3186740cc681d58b) Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
-rw-r--r--examples/multimediawidgets/camera/videosettings.cpp47
-rw-r--r--src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp10
-rw-r--r--src/multimedia/platform/android/wrappers/jni/androidcamera.cpp68
-rw-r--r--src/multimedia/platform/android/wrappers/jni/androidcamera_p.h3
4 files changed, 91 insertions, 37 deletions
diff --git a/examples/multimediawidgets/camera/videosettings.cpp b/examples/multimediawidgets/camera/videosettings.cpp
index eaf7b49c9..b5b0ba384 100644
--- a/examples/multimediawidgets/camera/videosettings.cpp
+++ b/examples/multimediawidgets/camera/videosettings.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -94,20 +94,47 @@ VideoSettings::VideoSettings(QMediaRecorder *mediaRecorder, QWidget *parent)
ui->videoCodecBox->addItem(QMediaFormat::videoCodecName(codec) + ": " + description, QVariant::fromValue(codec));
}
-
ui->videoResolutionBox->addItem(tr("Default"));
- auto supportedResolutions = mediaRecorder->captureSession()->camera()->cameraDevice().photoResolutions(); // ### Should use resolutions from video formats
- for (const QSize &resolution : supportedResolutions) {
- ui->videoResolutionBox->addItem(QString("%1x%2").arg(resolution.width()).arg(resolution.height()),
+
+ const QList<QCameraFormat> videoFormats =
+ mediaRecorder->captureSession()->camera()->cameraDevice().videoFormats();
+
+ for (const QCameraFormat &format : videoFormats) {
+ const QSize resolution = format.resolution();
+ ui->videoResolutionBox->addItem(QString("%1x%2")
+ .arg(resolution.width())
+ .arg(resolution.height()),
QVariant(resolution));
}
ui->videoFramerateBox->addItem(tr("Default"));
-// const QList<qreal> supportedFrameRates = mediaRecorder->supportedFrameRates();
-// for (qreal rate : supportedFrameRates) {
-// QString rateString = QString("%1").arg(rate, 0, 'f', 2);
-// ui->videoFramerateBox->addItem(rateString, QVariant(rate));
-// }
+
+ connect(ui->videoResolutionBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+ [this, mediaRecorder](int index) {
+
+ // Get the current list of formats
+ const QList<QCameraFormat> videoFormats =
+ mediaRecorder->captureSession()->camera()->cameraDevice().videoFormats();
+
+ QCameraFormat videoFormat;
+ const auto resolution = ui->videoResolutionBox->itemData(index).value<QSize>();
+ for (const QCameraFormat &format : videoFormats) {
+ if (format.resolution() == resolution) {
+ videoFormat = format;
+ break;
+ }
+ }
+
+ ui->videoFramerateBox->clear();
+
+ const float minFrameRate = videoFormat.minFrameRate();
+ QString rateString = QString("%1").arg(minFrameRate, 0, 'f', 2);
+ ui->videoFramerateBox->addItem(rateString, QVariant(minFrameRate));
+
+ const float maxFrameRate = videoFormat.maxFrameRate();
+ rateString = QString("%1").arg(maxFrameRate, 0, 'f', 2);
+ ui->videoFramerateBox->addItem(rateString, QVariant(maxFrameRate));
+ });
//containers
ui->containerFormatBox->addItem(tr("Default container"), QVariant::fromValue(QMediaFormat::UnspecifiedFormat));
diff --git a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp
index 6491e3296..096701535 100644
--- a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp
+++ b/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp
@@ -146,7 +146,15 @@ void QAndroidCameraSession::updateAvailableCameras()
AndroidCamera::getCameraInfo(i, info);
if (!info->id.isEmpty()) {
- AndroidCamera::getSupportedFormats(i, info->videoFormats);
+ // Add supported picture and video sizes to the camera info
+ AndroidCamera *camera = AndroidCamera::open(i);
+
+ if (camera) {
+ info->videoFormats = camera->getSupportedFormats();
+ info->photoResolutions = camera->getSupportedPictureSizes();
+ }
+
+ delete camera;
g_availableCameras->append(info->create());
}
}
diff --git a/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp b/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp
index e40921f38..a60eb6ed0 100644
--- a/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp
+++ b/src/multimedia/platform/android/wrappers/jni/androidcamera.cpp
@@ -233,6 +233,7 @@ public:
Q_INVOKABLE void updateRotation();
Q_INVOKABLE QList<QSize> getSupportedPictureSizes();
+ Q_INVOKABLE QList<QSize> getSupportedVideoSizes();
Q_INVOKABLE void setPictureSize(const QSize &size);
Q_INVOKABLE void setJpegQuality(int quality);
@@ -703,6 +704,12 @@ QList<QSize> AndroidCamera::getSupportedPictureSizes()
return d->getSupportedPictureSizes();
}
+QList<QSize> AndroidCamera::getSupportedVideoSizes()
+{
+ Q_D(AndroidCamera);
+ return d->getSupportedVideoSizes();
+}
+
void AndroidCamera::setPictureSize(const QSize &size)
{
Q_D(AndroidCamera);
@@ -817,27 +824,12 @@ AndroidCamera::ImageFormat AndroidCamera::AndroidImageFormatFromQtPixelFormat(QV
}
}
-void AndroidCamera::getSupportedFormats(int id, QList<QCameraFormat> &formats)
+QList<QCameraFormat> AndroidCamera::getSupportedFormats()
{
- QJniObject camera = QJniObject::callStaticObjectMethod("android/hardware/Camera",
- "open",
- "(I)Landroid/hardware/Camera;",
- id);
- if (!camera.isValid())
- return;
-
- QJniObject cameraParams = camera.callObjectMethod("getParameters",
- "()Landroid/hardware/Camera$Parameters;");
- if (!cameraParams.isValid()) {
- camera.callMethod<void>("release");
- return;
- }
- AndroidCamera::FpsRange range = AndroidCameraPrivate::getPreviewFpsRange(cameraParams);
-
- for (const auto &previewSize : AndroidCameraPrivate::getSupportedPreviewSizes(cameraParams))
- {
- for (const auto &previewFormat : AndroidCameraPrivate::getSupportedPreviewFormats(cameraParams))
- {
+ QList<QCameraFormat> formats;
+ AndroidCamera::FpsRange range = getPreviewFpsRange();
+ for (const auto &previewSize : getSupportedVideoSizes()) {
+ for (const auto &previewFormat : getSupportedPreviewFormats()) {
QCameraFormatPrivate * format = new QCameraFormatPrivate();
format->pixelFormat = QtPixelFormatFromAndroidImageFormat(previewFormat);
format->resolution = previewSize;
@@ -847,7 +839,7 @@ void AndroidCamera::getSupportedFormats(int id, QList<QCameraFormat> &formats)
}
}
- camera.callMethod<void>("release");
+ return formats;
}
void AndroidCamera::startPreview()
@@ -1066,8 +1058,10 @@ AndroidCamera::FpsRange AndroidCameraPrivate::getPreviewFpsRange(QJniObject &par
jint* jRangeElements = env->GetIntArrayElements(jRangeArray, 0);
- range.min = jRangeElements[0];
- range.max = jRangeElements[1];
+ // Android Camera API returns values scaled by 1000, so divide here to report
+ // normal values for Qt
+ range.min = jRangeElements[0] / 1000;
+ range.max = jRangeElements[1] / 1000;
env->ReleaseIntArrayElements(jRangeArray, jRangeElements, 0);
env->DeleteLocalRef(jRangeArray);
@@ -1082,8 +1076,9 @@ void AndroidCameraPrivate::setPreviewFpsRange(int min, int max)
if (!m_parameters.isValid())
return;
- QJniEnvironment env;
- m_parameters.callMethod<void>("setPreviewFpsRange", "(II)V", min, max);
+ // Android Camera API returns values scaled by 1000, so multiply here to
+ // give Android API the scale is expects
+ m_parameters.callMethod<void>("setPreviewFpsRange", "(II)V", min * 1000, max * 1000);
}
AndroidCamera::ImageFormat AndroidCameraPrivate::getPreviewFormat()
@@ -1590,6 +1585,29 @@ QList<QSize> AndroidCameraPrivate::getSupportedPictureSizes()
return list;
}
+QList<QSize> AndroidCameraPrivate::getSupportedVideoSizes()
+{
+ const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
+ QList<QSize> list;
+
+ if (m_parameters.isValid()) {
+ QJniObject sizeList = m_parameters.callObjectMethod("getSupportedVideoSizes",
+ "()Ljava/util/List;");
+ if (!sizeList.isValid())
+ return list;
+
+ int count = sizeList.callMethod<jint>("size");
+ for (int i = 0; i < count; ++i) {
+ const QJniObject size = sizeList.callObjectMethod("get", "(I)Ljava/lang/Object;", i);
+ if (size.isValid())
+ list.append(QSize(size.getField<jint>("width"), size.getField<jint>("height")));
+ }
+ std::sort(list.begin(), list.end(), qt_sizeLessThan);
+ }
+
+ return list;
+}
+
void AndroidCameraPrivate::setPictureSize(const QSize &size)
{
const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
diff --git a/src/multimedia/platform/android/wrappers/jni/androidcamera_p.h b/src/multimedia/platform/android/wrappers/jni/androidcamera_p.h
index 94c2d3c46..d5bded8d3 100644
--- a/src/multimedia/platform/android/wrappers/jni/androidcamera_p.h
+++ b/src/multimedia/platform/android/wrappers/jni/androidcamera_p.h
@@ -187,7 +187,9 @@ public:
void setRotation(int rotation);
int getRotation() const;
+ QList<QCameraFormat> getSupportedFormats();
QList<QSize> getSupportedPictureSizes();
+ QList<QSize> getSupportedVideoSizes();
void setPictureSize(const QSize &size);
void setJpegQuality(int quality);
@@ -206,7 +208,6 @@ public:
static void getCameraInfo(int id, QCameraDevicePrivate *info);
static QVideoFrameFormat::PixelFormat QtPixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat);
static AndroidCamera::ImageFormat AndroidImageFormatFromQtPixelFormat(QVideoFrameFormat::PixelFormat);
- static void getSupportedFormats(int id, QList<QCameraFormat> &formats);
static bool requestCameraPermission();
static bool registerNativeMethods();