diff options
author | Pekka Gehör <pekka.gehor@qt.io> | 2021-09-17 12:50:25 +0300 |
---|---|---|
committer | Pekka Gehör <pekka.gehor@qt.io> | 2021-10-01 13:00:32 +0300 |
commit | 63c658966f8ce5083853f517fe855e47eec6153e (patch) | |
tree | 745a718868a1de6e0d7c361d4b8d5cd28871a63a | |
parent | 148698ed27c3d4ac133a83c4b1c563fe2f9ed413 (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>
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(); |