1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "capturesessionfixture_p.h"
5#include <QtTest/qtest.h>
6
7QT_BEGIN_NAMESPACE
8
9using namespace std::chrono;
10
11CaptureSessionFixture::CaptureSessionFixture(StreamType streamType) : m_streamType{ streamType } { }
12
13CaptureSessionFixture::~CaptureSessionFixture()
14{
15 if (!m_recorder.actualLocation().isEmpty())
16 QFile::remove(fileName: m_recorder.actualLocation().toLocalFile());
17}
18
19void CaptureSessionFixture::setVideoSink(QVideoSink *videoSink)
20{
21 m_videoSink = videoSink;
22}
23
24void CaptureSessionFixture::start(RunMode mode, AutoStop autoStop)
25{
26 if (hasVideo()) {
27 m_session.setVideoFrameInput(&m_videoInput);
28
29 QObject::connect(sender: &m_videoGenerator, signal: &VideoGenerator::frameCreated, //
30 context: &m_videoInput, slot: &QVideoFrameInput::sendVideoFrame);
31
32 if (autoStop == AutoStop::EmitEmpty) {
33 m_recorder.setAutoStop(true);
34 m_videoGenerator.emitEmptyFrameOnStop();
35 }
36 }
37
38 if (hasAudio()) {
39 m_session.setAudioBufferInput(&m_audioInput);
40
41 QObject::connect(sender: &m_audioGenerator, signal: &AudioGenerator::audioBufferCreated, //
42 context: &m_audioInput, slot: &QAudioBufferInput::sendAudioBuffer);
43
44 if (autoStop == AutoStop::EmitEmpty) {
45 m_recorder.setAutoStop(true);
46 m_audioGenerator.emitEmptyBufferOnStop();
47 }
48 }
49
50 if (mode == RunMode::Pull) {
51 if (hasVideo())
52 QObject::connect(sender: &m_videoInput, signal: &QVideoFrameInput::readyToSendVideoFrame, //
53 context: &m_videoGenerator, slot: &VideoGenerator::nextFrame);
54
55 if (hasAudio())
56 QObject::connect(sender: &m_audioInput, signal: &QAudioBufferInput::readyToSendAudioBuffer, //
57 context: &m_audioGenerator, slot: &AudioGenerator::nextBuffer);
58 }
59
60 m_session.setRecorder(&m_recorder);
61 m_recorder.setQuality(QMediaRecorder::VeryHighQuality);
62
63 if (m_recorder.outputLocation().isEmpty()) {
64 // Create a temporary file.
65 // The file name is not available without opening.
66 if (!m_tempFile.open()) {
67 qWarning(msg: "Failed to open file: %s (%s)",
68 qPrintable(m_tempFile.fileName()), qPrintable(m_tempFile.errorString()));
69 } else {
70 m_tempFile.close();
71
72 m_recorder.setOutputLocation(m_tempFile.fileName());
73 }
74 }
75 // else: outputLocation has been already set
76
77 m_recorder.record();
78
79 // HACK: Add sink after starting recording because setting the video sink will
80 // emit ready signals and start the processing chain. TODO: Fix this
81 if (m_videoSink)
82 m_session.setVideoSink(m_videoSink);
83}
84
85bool CaptureSessionFixture::waitForRecorderStopped(std::chrono::milliseconds duration)
86{
87 // StoppedState is emitted when media is finalized.
88 const bool stopped = QTest::qWaitFor(
89 predicate: [&] { //
90 return recorderStateChanged.contains(
91 t: QList<QVariant>{ QMediaRecorder::RecorderState::StoppedState });
92 },
93 deadline: duration);
94
95 if (!stopped)
96 return false;
97
98 return m_recorder.recorderState() == QMediaRecorder::StoppedState;
99}
100
101bool CaptureSessionFixture::hasAudio() const
102{
103 return m_streamType == StreamType::Audio || m_streamType == StreamType::AudioAndVideo;
104}
105
106bool CaptureSessionFixture::hasVideo() const
107{
108 return m_streamType == StreamType::Video || m_streamType == StreamType::AudioAndVideo;
109}
110
111QT_END_NAMESPACE
112

source code of qtmultimedia/src/multimediatestlib/capturesessionfixture.cpp