From 93e90f07f207b75332f8b64a37c80f1fa5f87db0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 5 Oct 2021 14:51:36 +0200 Subject: Fix tst_qmediacapturesession on macOS Fix the remaining test failures on macOS: Increase timeouts in tests, as those often caused failures. Fix a couple of behaviors in the platform specific code, to ensure we handle errors correctly. Pick-to: 6.2 Change-Id: Ib1a0949f5e65a0fb3d0b89a5508631d1faa7cf1e Reviewed-by: Doris Verria Reviewed-by: Lars Knoll --- .../platform/darwin/camera/avfcameraservice.mm | 3 +- .../platform/darwin/camera/avfimagecapture.mm | 34 ++++++++------- .../platform/darwin/camera/avfmediaencoder.mm | 10 ++++- .../tst_qmediacapturesession.cpp | 50 ++++++++++++++++++---- 4 files changed, 70 insertions(+), 27 deletions(-) diff --git a/src/multimedia/platform/darwin/camera/avfcameraservice.mm b/src/multimedia/platform/darwin/camera/avfcameraservice.mm index 8d75716c9..5c7cc5848 100644 --- a/src/multimedia/platform/darwin/camera/avfcameraservice.mm +++ b/src/multimedia/platform/darwin/camera/avfcameraservice.mm @@ -81,10 +81,11 @@ void AVFCameraService::setCamera(QPlatformCamera *camera) m_cameraControl->setCaptureSession(nullptr); m_cameraControl = control; - emit cameraChanged(); if (m_cameraControl) m_cameraControl->setCaptureSession(this); + + emit cameraChanged(); } QPlatformImageCapture *AVFCameraService::imageCapture() diff --git a/src/multimedia/platform/darwin/camera/avfimagecapture.mm b/src/multimedia/platform/darwin/camera/avfimagecapture.mm index a397fe418..999abab95 100644 --- a/src/multimedia/platform/darwin/camera/avfimagecapture.mm +++ b/src/multimedia/platform/darwin/camera/avfimagecapture.mm @@ -96,14 +96,14 @@ int AVFImageCapture::doCapture(const QString &actualFileName) Q_ARG(int, m_lastCaptureId), Q_ARG(int, QImageCapture::ResourceError), Q_ARG(QString, QPlatformImageCapture::msgImageCaptureNotSet())); - return m_lastCaptureId; + return -1; } if (!isReadyForCapture()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(int, m_lastCaptureId), Q_ARG(int, QImageCapture::NotReadyError), Q_ARG(QString, QPlatformImageCapture::msgCameraNotReady())); - return m_lastCaptureId; + return -1; } m_lastCaptureId++; @@ -225,13 +225,16 @@ void AVFImageCapture::onNewViewfinderFrame(const QVideoFrame &frame) void AVFImageCapture::onCameraChanged() { - if (m_service) - m_cameraControl = static_cast(m_service->camera()); - else - m_cameraControl = nullptr; + auto camera = m_service ? static_cast(m_service->camera()) : nullptr; + + if (camera == m_cameraControl) + return; + + m_cameraControl = camera; if (m_cameraControl) connect(m_cameraControl, SIGNAL(activeChanged(bool)), this, SLOT(updateReadyStatus())); + updateReadyStatus(); } void AVFImageCapture::makeCapturePreview(CaptureRequest request, @@ -385,20 +388,19 @@ void AVFImageCapture::setCaptureSession(QPlatformMediaCaptureSession *session) m_session = nullptr; m_cameraControl = nullptr; m_videoConnection = nil; - return; + } else { + m_session = m_service->session(); + Q_ASSERT(m_session); + + connect(m_service, &AVFCameraService::cameraChanged, this, &AVFImageCapture::onCameraChanged); + connect(m_session, SIGNAL(readyToConfigureConnections()), SLOT(updateCaptureConnection())); + connect(m_session, &AVFCameraSession::newViewfinderFrame, + this, &AVFImageCapture::onNewViewfinderFrame); } - m_session = m_service->session(); - Q_ASSERT(m_session); - - connect(m_service, &AVFCameraService::cameraChanged, this, &AVFImageCapture::onCameraChanged); - connect(m_session, SIGNAL(readyToConfigureConnections()), SLOT(updateCaptureConnection())); - connect(m_session, &AVFCameraSession::newViewfinderFrame, - this, &AVFImageCapture::onNewViewfinderFrame); - updateCaptureConnection(); - updateReadyStatus(); onCameraChanged(); + updateReadyStatus(); } bool AVFImageCapture::videoCaptureDeviceIsValid() const diff --git a/src/multimedia/platform/darwin/camera/avfmediaencoder.mm b/src/multimedia/platform/darwin/camera/avfmediaencoder.mm index 2e081108e..c02bdfe46 100644 --- a/src/multimedia/platform/darwin/camera/avfmediaencoder.mm +++ b/src/multimedia/platform/darwin/camera/avfmediaencoder.mm @@ -484,13 +484,21 @@ void AVFMediaEncoder::record(QMediaEncoderSettings &settings) if (QMediaRecorder::RecordingState == m_state) return; + AVFCamera *cameraControl = m_service->avfCameraControl(); + auto audioInput = m_service->audioInput(); + + if (!cameraControl && !audioInput) { + qWarning() << Q_FUNC_INFO << "Cannot record without any inputs"; + Q_EMIT error(QMediaRecorder::ResourceError, tr("No inputs specified")); + return; + } + m_service->session()->setActive(true); const bool audioOnly = settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified; AVCaptureSession *session = m_service->session()->captureSession(); float rotation = 0; if (!audioOnly) { - AVFCamera *cameraControl = m_service->avfCameraControl(); if (!cameraControl || !cameraControl->isActive()) { qDebugCamera() << Q_FUNC_INFO << "can not start record while camera is not active"; Q_EMIT error(QMediaRecorder::ResourceError, diff --git a/tests/auto/integration/qmediacapturesession/tst_qmediacapturesession.cpp b/tests/auto/integration/qmediacapturesession/tst_qmediacapturesession.cpp index 76a69b205..fec6a3729 100644 --- a/tests/auto/integration/qmediacapturesession/tst_qmediacapturesession.cpp +++ b/tests/auto/integration/qmediacapturesession/tst_qmediacapturesession.cpp @@ -65,6 +65,8 @@ class tst_QMediaCaptureSession: public QObject private slots: void stress_test_setup_and_teardown(); + void record_video_without_preview(); + void can_add_and_remove_AudioInput_with_and_without_AudioOutput_attached(); void can_change_AudioDevices_on_attached_AudioInput(); void can_change_AudioInput_during_recording(); @@ -110,7 +112,7 @@ void tst_QMediaCaptureSession::recordOk(QMediaCaptureSession &session) recorder.record(); QTRY_VERIFY_WITH_TIMEOUT(recorder.recorderState() == QMediaRecorder::RecordingState, 2000); - QVERIFY(durationChanged.wait(1000)); + QVERIFY(durationChanged.wait(2000)); recorder.stop(); QTRY_VERIFY_WITH_TIMEOUT(recorder.recorderState() == QMediaRecorder::StoppedState, 2000); @@ -130,8 +132,8 @@ void tst_QMediaCaptureSession::recordFail(QMediaCaptureSession &session) session.setRecorder(&recorder); recorder.record(); - QTRY_VERIFY_WITH_TIMEOUT(recorderErrorSignal.count() == 1, 1000); - QTRY_VERIFY_WITH_TIMEOUT(recorder.recorderState() == QMediaRecorder::StoppedState, 1000); + QTRY_VERIFY_WITH_TIMEOUT(recorderErrorSignal.count() == 1, 2000); + QTRY_VERIFY_WITH_TIMEOUT(recorder.recorderState() == QMediaRecorder::StoppedState, 2000); } void tst_QMediaCaptureSession::stress_test_setup_and_teardown() @@ -155,6 +157,35 @@ void tst_QMediaCaptureSession::stress_test_setup_and_teardown() } } +void tst_QMediaCaptureSession::record_video_without_preview() +{ + QCamera camera; + + if (!camera.isAvailable()) + QSKIP("No video input is available"); + + QMediaRecorder recorder; + QMediaCaptureSession session; + + session.setRecorder(&recorder); + + QSignalSpy cameraChanged(&session, SIGNAL(cameraChanged())); + + session.setCamera(&camera); + camera.setActive(true); + QTRY_COMPARE(cameraChanged.count(), 1); + + recordOk(session); + QVERIFY(!QTest::currentTestFailed()); + + session.setCamera(nullptr); + QTRY_COMPARE(cameraChanged.count(), 2); + + // can't record without audio and video + recordFail(session); + QVERIFY(!QTest::currentTestFailed()); +} + void tst_QMediaCaptureSession::can_add_and_remove_AudioInput_with_and_without_AudioOutput_attached() { QAudioInput input; @@ -238,7 +269,7 @@ void tst_QMediaCaptureSession::can_change_AudioInput_during_recording() recorder.record(); QTRY_VERIFY(recorder.recorderState() == QMediaRecorder::RecordingState); - QVERIFY(durationChanged.wait(1000)); + QVERIFY(durationChanged.wait(2000)); session.setAudioInput(nullptr); QTRY_COMPARE(audioInputChanged.count(), 2); session.setAudioInput(&input); @@ -377,8 +408,8 @@ void tst_QMediaCaptureSession::can_add_and_remove_Camera() QSignalSpy cameraChanged(&session, SIGNAL(cameraChanged())); - camera.setActive(true); session.setCamera(&camera); + camera.setActive(true); QTRY_COMPARE(cameraChanged.count(), 1); session.setCamera(nullptr); @@ -443,9 +474,10 @@ void tst_QMediaCaptureSession::can_disconnect_Camera_when_recording() session.setCamera(&camera); QTRY_COMPARE(cameraChanged.count(), 1); + durationChanged.clear(); recorder.record(); QTRY_VERIFY(recorder.recorderState() == QMediaRecorder::RecordingState); - QVERIFY(durationChanged.wait(1000)); + QTRY_VERIFY(durationChanged.count() > 0); session.setCamera(nullptr); QTRY_COMPARE(cameraChanged.count(), 2); @@ -587,7 +619,7 @@ void tst_QMediaCaptureSession::can_change_VideoOutput_when_recording() recorder.record(); QTRY_VERIFY(recorder.recorderState() == QMediaRecorder::RecordingState); - QVERIFY(durationChanged.wait(1000)); + QVERIFY(durationChanged.wait(2000)); session.setVideoOutput(&videoOutput); QTRY_COMPARE(videoOutputChanged.count(), 1); @@ -734,7 +766,7 @@ void tst_QMediaCaptureSession::recording_stops_when_recorder_removed() recorder.record(); QTRY_VERIFY(recorder.recorderState() == QMediaRecorder::RecordingState); - QVERIFY(durationChanged.wait(1000)); + QVERIFY(durationChanged.wait(2000)); session.setRecorder(nullptr); QTRY_COMPARE(recorderChanged.count(), 2); @@ -888,7 +920,7 @@ void tst_QMediaCaptureSession::can_add_ImageCapture_and_capture_during_recording recorder.record(); QTRY_VERIFY(recorder.recorderState() == QMediaRecorder::RecordingState); - QVERIFY(durationChanged.wait(1000)); + QVERIFY(durationChanged.wait(2000)); session.setImageCapture(&capture); QTRY_COMPARE(imageCaptureChanged.count(), 1); -- cgit v1.2.3