diff options
Diffstat (limited to 'tests/auto/integration/qcamerabackend')
-rw-r--r-- | tests/auto/integration/qcamerabackend/BLACKLIST | 1 | ||||
-rw-r--r-- | tests/auto/integration/qcamerabackend/CMakeLists.txt | 10 | ||||
-rw-r--r-- | tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp | 253 |
3 files changed, 168 insertions, 96 deletions
diff --git a/tests/auto/integration/qcamerabackend/BLACKLIST b/tests/auto/integration/qcamerabackend/BLACKLIST index 0521c9fbd..e958c2103 100644 --- a/tests/auto/integration/qcamerabackend/BLACKLIST +++ b/tests/auto/integration/qcamerabackend/BLACKLIST @@ -1,3 +1,4 @@ +ci [testCameraCaptureMetadata] osx diff --git a/tests/auto/integration/qcamerabackend/CMakeLists.txt b/tests/auto/integration/qcamerabackend/CMakeLists.txt index c89456e8a..07a6a4cae 100644 --- a/tests/auto/integration/qcamerabackend/CMakeLists.txt +++ b/tests/auto/integration/qcamerabackend/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + # Generated from qcamerabackend.pro. ##################################################################### @@ -7,14 +10,17 @@ qt_internal_add_test(tst_qcamerabackend SOURCES tst_qcamerabackend.cpp - PUBLIC_LIBRARIES + ../shared/mediabackendutils.h + INCLUDE_DIRECTORIES + ../shared/ + LIBRARIES Qt::Gui Qt::MultimediaPrivate Qt::Widgets ) # special case begin -if (APPLE) +if(APPLE) set_property(TARGET tst_qcamerabackend PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist") set_property(TARGET tst_qcamerabackend PROPERTY PROPERTY MACOSX_BUNDLE TRUE) endif() diff --git a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp index 0edc9256e..63790dfd2 100644 --- a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp +++ b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp @@ -1,32 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//TESTED_COMPONENT=src/multimedia +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QtTest> #include <QtGui/QImageReader> @@ -34,9 +7,11 @@ #include <QtCore/qlocale.h> #include <QDebug> #include <QVideoSink> +#include <QMediaPlayer> #include <private/qplatformcamera_p.h> #include <private/qplatformimagecapture_p.h> +#include <private/qplatformmediaintegration_p.h> #include <qcamera.h> #include <qcameradevice.h> #include <qimagecapture.h> @@ -47,6 +22,12 @@ #include <qmediaplayer.h> #include <qaudiooutput.h> +#ifdef Q_OS_DARWIN +#include <QtCore/private/qcore_mac_p.h> +#endif + +#include <mediabackendutils.h> + QT_USE_NAMESPACE /* @@ -83,6 +64,8 @@ private slots: void testNativeMetadata(); + void multipleCameraSet(); + private: bool noCamera = false; }; @@ -116,6 +99,14 @@ public Q_SLOTS: if (surfaceFormat.pixelFormat() == cameraFormat.pixelFormat() && surfaceFormat.frameSize() == cameraFormat.resolution()) { formatMismatch = 0; +#ifdef Q_OS_ANDROID + } else if ((surfaceFormat.pixelFormat() == QVideoFrameFormat::Format_YUV420P + || surfaceFormat.pixelFormat() == QVideoFrameFormat::Format_NV12) + && (cameraFormat.pixelFormat() == QVideoFrameFormat::Format_YUV420P + || cameraFormat.pixelFormat() == QVideoFrameFormat::Format_NV12) + && surfaceFormat.frameSize() == cameraFormat.resolution()) { + formatMismatch = 0; +#endif } else { formatMismatch = 1; } @@ -222,8 +213,8 @@ void tst_QCameraBackend::testCameraActive() session.setCamera(&camera); session.setImageCapture(&imageCapture); - QSignalSpy errorSignal(&camera, SIGNAL(errorOccurred(QCamera::Error, const QString &))); - QSignalSpy activeChangedSignal(&camera, SIGNAL(activeChanged(bool))); + QSignalSpy errorSignal(&camera, &QCamera::errorOccurred); + QSignalSpy activeChangedSignal(&camera, &QCamera::activeChanged); QCOMPARE(camera.isActive(), false); @@ -233,7 +224,7 @@ void tst_QCameraBackend::testCameraActive() QCOMPARE(camera.error(), QCamera::NoError); camera.start(); - QCOMPARE(camera.isActive(), true); + QTRY_COMPARE(camera.isActive(), true); QTRY_COMPARE(activeChangedSignal.size(), 1); QCOMPARE(activeChangedSignal.last().first().value<bool>(), true); @@ -246,6 +237,14 @@ void tst_QCameraBackend::testCameraActive() void tst_QCameraBackend::testCameraStartParallel() { +#ifdef Q_OS_ANDROID + QSKIP("Multi-camera feature is currently not supported on Android. " + "Cannot open same device twice."); +#endif +#ifdef Q_OS_LINUX + QSKIP("Multi-camera feature is currently not supported on Linux. " + "Cannot open same device twice."); +#endif if (noCamera) QSKIP("No camera available"); @@ -266,8 +265,8 @@ void tst_QCameraBackend::testCameraStartParallel() QCOMPARE(camera2.isActive(), true); QCOMPARE(camera2.error(), QCamera::NoError); - QCOMPARE(errorSpy1.count(), 0); - QCOMPARE(errorSpy2.count(), 0); + QCOMPARE(errorSpy1.size(), 0); + QCOMPARE(errorSpy2.size(), 0); } void tst_QCameraBackend::testCameraFormat() @@ -278,15 +277,15 @@ void tst_QCameraBackend::testCameraFormat() if (videoFormats.isEmpty()) QSKIP("No Camera available, skipping test."); QCameraFormat cameraFormat = videoFormats.first(); - QSignalSpy spy(&camera, SIGNAL(cameraFormatChanged())); - QVERIFY(spy.count() == 0); + QSignalSpy spy(&camera, &QCamera::cameraFormatChanged); + QVERIFY(spy.size() == 0); QMediaCaptureSession session; session.setCamera(&camera); - QVERIFY(videoFormats.count()); + QVERIFY(videoFormats.size()); camera.setCameraFormat(cameraFormat); QCOMPARE(camera.cameraFormat(), cameraFormat); - QVERIFY(spy.count() == 1); + QVERIFY(spy.size() == 1); TestVideoFormat videoFormatTester(cameraFormat); session.setVideoOutput(&videoFormatTester); @@ -296,11 +295,11 @@ void tst_QCameraBackend::testCameraFormat() spy.clear(); camera.stop(); // Change camera format - if (videoFormats.count() > 1) { + if (videoFormats.size() > 1) { QCameraFormat secondFormat = videoFormats.at(1); camera.setCameraFormat(secondFormat); QCOMPARE(camera.cameraFormat(), secondFormat); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(camera.cameraFormat(), secondFormat); videoFormatTester.setCameraFormatToTest(secondFormat); camera.start(); @@ -315,7 +314,7 @@ void tst_QCameraBackend::testCameraFormat() spy.clear(); camera.stop(); camera.setCameraFormat({}); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); videoFormatTester.setCameraFormatToTest({}); camera.start(); // In case of a null format, the backend should have picked @@ -326,7 +325,7 @@ void tst_QCameraBackend::testCameraFormat() spy.clear(); // Shouldn't change anything as it's the same device camera.setCameraDevice(device); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QCameraBackend::testCameraCapture() @@ -342,9 +341,9 @@ void tst_QCameraBackend::testCameraCapture() QVERIFY(!imageCapture.isReadyForCapture()); - QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage))); - QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); - QSignalSpy errorSignal(&imageCapture, SIGNAL(errorOccurred(int,QImageCapture::Error,const QString&))); + QSignalSpy capturedSignal(&imageCapture, &QImageCapture::imageCaptured); + QSignalSpy savedSignal(&imageCapture, &QImageCapture::imageSaved); + QSignalSpy errorSignal(&imageCapture, &QImageCapture::errorOccurred); imageCapture.captureToFile(); QTRY_COMPARE(errorSignal.size(), 1); @@ -365,7 +364,7 @@ void tst_QCameraBackend::testCameraCapture() int id = imageCapture.captureToFile(); - QTRY_VERIFY(!savedSignal.isEmpty()); + QTRY_VERIFY_WITH_TIMEOUT(!savedSignal.isEmpty(), 8s); QTRY_COMPARE(capturedSignal.size(), 1); QCOMPARE(capturedSignal.last().first().toInt(), id); @@ -401,10 +400,10 @@ void tst_QCameraBackend::testCaptureToBuffer() QTRY_VERIFY(camera.isActive()); - QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage))); - QSignalSpy imageAvailableSignal(&imageCapture, SIGNAL(imageAvailable(int,QVideoFrame))); - QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); - QSignalSpy errorSignal(&imageCapture, SIGNAL(errorOccurred(int,QImageCapture::Error,const QString&))); + QSignalSpy capturedSignal(&imageCapture, &QImageCapture::imageCaptured); + QSignalSpy imageAvailableSignal(&imageCapture, &QImageCapture::imageAvailable); + QSignalSpy savedSignal(&imageCapture, &QImageCapture::imageSaved); + QSignalSpy errorSignal(&imageCapture, &QImageCapture::errorOccurred); camera.start(); QTRY_VERIFY(imageCapture.isReadyForCapture()); @@ -446,8 +445,14 @@ void tst_QCameraBackend::testCameraCaptureMetadata() camera.setFlashMode(QCamera::FlashOff); - QSignalSpy metadataSignal(&imageCapture, SIGNAL(imageMetadataAvailable(int,const QMediaMetaData&))); - QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); + QMediaMetaData referenceMetaData; + referenceMetaData.insert(QMediaMetaData::Title, QStringLiteral("Title")); + referenceMetaData.insert(QMediaMetaData::Language, QVariant::fromValue(QLocale::German)); + referenceMetaData.insert(QMediaMetaData::Description, QStringLiteral("Description")); + imageCapture.setMetaData(referenceMetaData); + + QSignalSpy metadataSignal(&imageCapture, &QImageCapture::imageMetadataAvailable); + QSignalSpy savedSignal(&imageCapture, &QImageCapture::imageSaved); camera.start(); @@ -458,7 +463,19 @@ void tst_QCameraBackend::testCameraCaptureMetadata() int id = imageCapture.captureToFile(tmpFile); QTRY_VERIFY(!savedSignal.isEmpty()); QVERIFY(!metadataSignal.isEmpty()); + QCOMPARE(metadataSignal.first().first().toInt(), id); + QMediaMetaData receivedMetaData = metadataSignal.first()[1].value<QMediaMetaData>(); + + if (isGStreamerPlatform()) { + for (auto key : { + QMediaMetaData::Title, + QMediaMetaData::Language, + QMediaMetaData::Description, + }) + QCOMPARE(receivedMetaData[key], referenceMetaData[key]); + QVERIFY(receivedMetaData[QMediaMetaData::Resolution].isValid()); + } } void tst_QCameraBackend::testExposureCompensation() @@ -470,22 +487,22 @@ void tst_QCameraBackend::testExposureCompensation() QCamera camera; session.setCamera(&camera); - QSignalSpy exposureCompensationSignal(&camera, SIGNAL(exposureCompensationChanged(float))); + QSignalSpy exposureCompensationSignal(&camera, &QCamera::exposureCompensationChanged); - //it should be possible to set exposure parameters in Unloaded state + // it should be possible to set exposure parameters in Unloaded state QCOMPARE(camera.exposureCompensation(), 0.); if (!(camera.supportedFeatures() & QCamera::Feature::ExposureCompensation)) return; camera.setExposureCompensation(1.0); QCOMPARE(camera.exposureCompensation(), 1.0); - QTRY_COMPARE(exposureCompensationSignal.count(), 1); + QTRY_COMPARE(exposureCompensationSignal.size(), 1); QCOMPARE(exposureCompensationSignal.last().first().toReal(), 1.0); //exposureCompensationChanged should not be emitted when value is not changed camera.setExposureCompensation(1.0); QTest::qWait(50); - QCOMPARE(exposureCompensationSignal.count(), 1); + QCOMPARE(exposureCompensationSignal.size(), 1); //exposure compensation should be preserved during start camera.start(); @@ -496,7 +513,7 @@ void tst_QCameraBackend::testExposureCompensation() exposureCompensationSignal.clear(); camera.setExposureCompensation(-1.0); QCOMPARE(camera.exposureCompensation(), -1.0); - QTRY_COMPARE(exposureCompensationSignal.count(), 1); + QTRY_COMPARE(exposureCompensationSignal.size(), 1); QCOMPARE(exposureCompensationSignal.last().first().toReal(), -1.0); } @@ -525,7 +542,7 @@ void tst_QCameraBackend::testExposureMode() camera.setExposureMode(QCamera::ExposureAuto); QCOMPARE(camera.exposureMode(), QCamera::ExposureAuto); camera.start(); - QVERIFY(camera.isActive()); + QTRY_VERIFY(camera.isActive()); QCOMPARE(camera.exposureMode(), QCamera::ExposureAuto); // Manual @@ -569,16 +586,16 @@ void tst_QCameraBackend::testVideoRecording() QMediaRecorder recorder; session.setRecorder(&recorder); - QSignalSpy errorSignal(camera.data(), SIGNAL(errorOccurred(QCamera::Error, const QString &))); - QSignalSpy recorderErrorSignal(&recorder, SIGNAL(errorOccurred(Error, const QString &))); - QSignalSpy recorderStateChanged(&recorder, SIGNAL(recorderStateChanged(RecorderState))); - QSignalSpy durationChanged(&recorder, SIGNAL(durationChanged(qint64))); + QSignalSpy errorSignal(camera.data(), &QCamera::errorOccurred); + QSignalSpy recorderErrorSignal(&recorder, &QMediaRecorder::errorOccurred); + QSignalSpy recorderStateChanged(&recorder, &QMediaRecorder::recorderStateChanged); + QSignalSpy durationChanged(&recorder, &QMediaRecorder::durationChanged); recorder.setVideoResolution(320, 240); // Insert metadata QMediaMetaData metaData; - metaData.insert(QMediaMetaData::Author, QString::fromUtf8("Author")); + metaData.insert(QMediaMetaData::Author, QStringLiteral("Author")); metaData.insert(QMediaMetaData::Date, QDateTime::currentDateTime()); recorder.setMetaData(metaData); @@ -591,27 +608,41 @@ void tst_QCameraBackend::testVideoRecording() QTRY_VERIFY(camera->isActive()); - for (int recordings = 0; recordings < 2; ++recordings) { - //record 200ms clip - recorder.record(); - durationChanged.clear(); - QTRY_VERIFY(durationChanged.count()); + recorder.record(); + if (!recorderErrorSignal.empty() || recorderErrorSignal.wait(550)) { + QEXPECT_FAIL_GSTREAMER("", "QTBUG-124148: GStreamer might return ResourceError", Continue); + + QCOMPARE(recorderErrorSignal.last().first().toInt(), QMediaRecorder::FormatError); + return; + } + + QTRY_VERIFY(durationChanged.size()); - QCOMPARE(recorder.metaData(), metaData); + QCOMPARE(recorder.metaData(), metaData); - recorderStateChanged.clear(); - recorder.stop(); - QTRY_VERIFY(recorderStateChanged.size() > 0); - QVERIFY(recorder.recorderState() == QMediaRecorder::StoppedState); + recorderStateChanged.clear(); + recorder.stop(); + QTRY_VERIFY(recorderStateChanged.size() > 0); + QVERIFY(recorder.recorderState() == QMediaRecorder::StoppedState); - QVERIFY(errorSignal.isEmpty()); - QVERIFY(recorderErrorSignal.isEmpty()); + QVERIFY(errorSignal.isEmpty()); + QVERIFY(recorderErrorSignal.isEmpty()); - QString fileName = recorder.actualLocation().toLocalFile(); - QVERIFY(!fileName.isEmpty()); - QVERIFY(QFileInfo(fileName).size() > 0); - QFile(fileName).remove(); - } + QString fileName = recorder.actualLocation().toLocalFile(); + QVERIFY(!fileName.isEmpty()); + QVERIFY(QFileInfo(fileName).size() > 0); + + QMediaPlayer player; + player.setSource(fileName); + + QTRY_COMPARE_WITH_TIMEOUT(player.mediaStatus(), QMediaPlayer::LoadedMedia, 8s); + QCOMPARE_EQ(player.metaData().value(QMediaMetaData::Resolution).toSize(), QSize(320, 240)); + QCOMPARE_GT(player.duration(), 350); + QCOMPARE_LT(player.duration(), 650); + + // TODO: integrate with a virtual camera and check mediaplayer output + + QFile(fileName).remove(); } void tst_QCameraBackend::testNativeMetadata() @@ -627,10 +658,10 @@ void tst_QCameraBackend::testNativeMetadata() QMediaRecorder recorder; session.setRecorder(&recorder); - QSignalSpy errorSignal(&camera, SIGNAL(errorOccurred(QCamera::Error, const QString &))); - QSignalSpy recorderErrorSignal(&recorder, SIGNAL(errorOccurred(Error, const QString &))); - QSignalSpy recorderStateChanged(&recorder, SIGNAL(recorderStateChanged(RecorderState))); - QSignalSpy durationChanged(&recorder, SIGNAL(durationChanged(qint64))); + QSignalSpy errorSignal(&camera, &QCamera::errorOccurred); + QSignalSpy recorderErrorSignal(&recorder, &QMediaRecorder::errorOccurred); + QSignalSpy recorderStateChanged(&recorder, &QMediaRecorder::recorderStateChanged); + QSignalSpy durationChanged(&recorder, &QMediaRecorder::durationChanged); camera.start(); if (device.isNull()) { @@ -643,15 +674,15 @@ void tst_QCameraBackend::testNativeMetadata() // Insert common metadata supported on all platforms // Don't use Date, as some backends set that on their own QMediaMetaData metaData; - metaData.insert(QMediaMetaData::Title, QString::fromUtf8("Title")); + metaData.insert(QMediaMetaData::Title, QStringLiteral("Title")); metaData.insert(QMediaMetaData::Language, QVariant::fromValue(QLocale::German)); - metaData.insert(QMediaMetaData::Description, QString::fromUtf8("Description")); + metaData.insert(QMediaMetaData::Description, QStringLiteral("Description")); recorder.setMetaData(metaData); recorder.record(); - durationChanged.clear(); - QTRY_VERIFY(durationChanged.count()); + QTRY_VERIFY(durationChanged.size()); + QTRY_VERIFY(recorder.recorderState() == QMediaRecorder::RecorderState::RecordingState); QCOMPARE(recorder.metaData(), metaData); @@ -659,9 +690,13 @@ void tst_QCameraBackend::testNativeMetadata() recorder.stop(); QTRY_VERIFY(recorderStateChanged.size() > 0); + QTRY_VERIFY(recorder.recorderState() == QMediaRecorder::RecorderState::StoppedState); QVERIFY(errorSignal.isEmpty()); - QVERIFY(recorderErrorSignal.isEmpty()); + if (!isGStreamerPlatform()) { + // https://bugreports.qt.io/browse/QTBUG-124183 + QVERIFY(recorderErrorSignal.isEmpty()); + } QString fileName = recorder.actualLocation().toLocalFile(); QVERIFY(!fileName.isEmpty()); @@ -669,30 +704,60 @@ void tst_QCameraBackend::testNativeMetadata() // QMediaRecorder::metaData() can only test that QMediaMetaData is set properly on the recorder. // Use QMediaPlayer to test that the native metadata is properly set on the track - QMediaPlayer player; QAudioOutput output; + QMediaPlayer player; player.setAudioOutput(&output); - QSignalSpy metadataChangedSpy(&player, SIGNAL(metaDataChanged())); + QSignalSpy metadataChangedSpy(&player, &QMediaPlayer::metaDataChanged); player.setSource(QUrl::fromLocalFile(fileName)); player.play(); - QTRY_VERIFY(metadataChangedSpy.count() > 0); + int metadataChangedRequiredCount = isGStreamerPlatform() ? 2 : 1; + + QTRY_VERIFY(metadataChangedSpy.size() >= metadataChangedRequiredCount); - QCOMPARE(player.metaData().value(QMediaMetaData::Title).toString(), metaData.value(QMediaMetaData::Title).toString()); + QCOMPARE(player.metaData().value(QMediaMetaData::Title).toString(), + metaData.value(QMediaMetaData::Title).toString()); auto lang = player.metaData().value(QMediaMetaData::Language).value<QLocale::Language>(); if (lang != QLocale::AnyLanguage) QCOMPARE(lang, metaData.value(QMediaMetaData::Language).value<QLocale::Language>()); QCOMPARE(player.metaData().value(QMediaMetaData::Description).toString(), metaData.value(QMediaMetaData::Description).toString()); + QVERIFY(player.metaData().value(QMediaMetaData::Resolution).isValid()); - metadataChangedSpy.clear(); + if (isGStreamerPlatform()) + QVERIFY(player.metaData().value(QMediaMetaData::Date).isValid()); player.stop(); player.setSource({}); QFile(fileName).remove(); } +void tst_QCameraBackend::multipleCameraSet() +{ + if (noCamera) + QSKIP("No camera available"); + + QMediaCaptureSession session; + QCameraDevice device = QMediaDevices::defaultVideoInput(); + + QMediaRecorder recorder; + session.setRecorder(&recorder); + + for (int i = 0; i < 5; ++i) { +#ifdef Q_OS_DARWIN + QMacAutoReleasePool releasePool; +#endif + + QCamera camera(device); + session.setCamera(&camera); + + camera.start(); + + QTest::qWait(100); + } +} + QTEST_MAIN(tst_QCameraBackend) #include "tst_qcamerabackend.moc" |