155 lines
5.7 KiB
C++
155 lines
5.7 KiB
C++
// Copyright (C) 2024 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
|
|
|
#include "recordingrunner.h"
|
|
|
|
/// Base
|
|
|
|
RecordingRunner::RecordingRunner(const RecorderSettings &recorderSettings)
|
|
{
|
|
if (recorderSettings.frameRate)
|
|
m_recorder.setVideoFrameRate(recorderSettings.frameRate);
|
|
if (recorderSettings.resolution.isValid())
|
|
m_recorder.setVideoResolution(recorderSettings.resolution);
|
|
if (recorderSettings.quality)
|
|
m_recorder.setQuality(*recorderSettings.quality);
|
|
if (!recorderSettings.outputLocation.isEmpty())
|
|
m_recorder.setOutputLocation(recorderSettings.outputLocation);
|
|
if (recorderSettings.fileFormat || recorderSettings.audioCodec || recorderSettings.videoCodec) {
|
|
QMediaFormat format;
|
|
if (recorderSettings.fileFormat)
|
|
format.setFileFormat(*recorderSettings.fileFormat);
|
|
if (recorderSettings.videoCodec)
|
|
format.setVideoCodec(*recorderSettings.videoCodec);
|
|
if (recorderSettings.audioCodec)
|
|
format.setAudioCodec(*recorderSettings.audioCodec);
|
|
m_recorder.setMediaFormat(format);
|
|
}
|
|
|
|
m_recorder.setAutoStop(true);
|
|
|
|
connect(&m_recorder, &QMediaRecorder::recorderStateChanged, this,
|
|
&RecordingRunner::handleRecorderStateChanged);
|
|
connect(&m_recorder, &QMediaRecorder::errorOccurred, this, &RecordingRunner::handleError);
|
|
|
|
m_session.setRecorder(&m_recorder);
|
|
}
|
|
|
|
RecordingRunner::~RecordingRunner() = default;
|
|
|
|
void RecordingRunner::run()
|
|
{
|
|
m_recorder.record();
|
|
}
|
|
|
|
void RecordingRunner::handleRecorderStateChanged(QMediaRecorder::RecorderState state)
|
|
{
|
|
if (state == QMediaRecorder::RecordingState) {
|
|
qInfo() << "Starting recording to" << m_recorder.actualLocation();
|
|
} else if (state == QMediaRecorder::StoppedState) {
|
|
const bool noError = m_recorder.error() == QMediaRecorder::NoError;
|
|
qInfo() << "The recording to" << m_recorder.actualLocation() << "has been finished"
|
|
<< (noError ? "" : "with an error");
|
|
|
|
emit finished();
|
|
}
|
|
}
|
|
|
|
void RecordingRunner::handleError(QMediaRecorder::Error error, QString description)
|
|
{
|
|
qWarning() << "Recoding error occurred:" << error << description;
|
|
|
|
if (m_recorder.recorderState() == QMediaRecorder::StoppedState)
|
|
emit finished();
|
|
}
|
|
|
|
/// Pull mode
|
|
|
|
PullModeRecordingRunner::PullModeRecordingRunner(
|
|
const RecorderSettings &recorderSettings,
|
|
const AudioGeneratorSettingsOpt &audioGeneratorSettings,
|
|
const VideoGeneratorSettingsOpt &videoGeneratorSettings)
|
|
: RecordingRunner(recorderSettings)
|
|
{
|
|
Q_ASSERT(audioGeneratorSettings || videoGeneratorSettings);
|
|
|
|
if (audioGeneratorSettings) {
|
|
m_audioGenerator = std::make_unique<AudioGenerator>(*audioGeneratorSettings);
|
|
m_audioInput = std::make_unique<QAudioBufferInput>();
|
|
connect(m_audioInput.get(), &QAudioBufferInput::readyToSendAudioBuffer, this,
|
|
&PullModeRecordingRunner::sendNextAudioBuffer);
|
|
session().setAudioBufferInput(m_audioInput.get());
|
|
}
|
|
|
|
if (videoGeneratorSettings) {
|
|
m_videoGenerator = std::make_unique<VideoGenerator>(*videoGeneratorSettings);
|
|
m_videoInput = std::make_unique<QVideoFrameInput>();
|
|
connect(m_videoInput.get(), &QVideoFrameInput::readyToSendVideoFrame, this,
|
|
&PullModeRecordingRunner::sendNextVideoFrame);
|
|
session().setVideoFrameInput(m_videoInput.get());
|
|
}
|
|
}
|
|
|
|
void PullModeRecordingRunner::sendNextAudioBuffer()
|
|
{
|
|
const bool result = m_audioInput->sendAudioBuffer(m_audioGenerator->generate());
|
|
Q_ASSERT(result);
|
|
}
|
|
|
|
void PullModeRecordingRunner::sendNextVideoFrame()
|
|
{
|
|
const bool result = m_videoInput->sendVideoFrame(m_videoGenerator->generate());
|
|
Q_ASSERT(result);
|
|
}
|
|
|
|
/// Push mode
|
|
|
|
PushModeRecordingRunner::PushModeRecordingRunner(
|
|
const RecorderSettings &recorderSettings,
|
|
const AudioGeneratorSettingsOpt &audioGeneratorSettings,
|
|
const VideoGeneratorSettingsOpt &videoGeneratorSettings,
|
|
const PushModeSettings &pushModeSettings)
|
|
: RecordingRunner(recorderSettings)
|
|
{
|
|
if (audioGeneratorSettings) {
|
|
m_audioBufferInputQueue =
|
|
std::make_unique<AudioBufferInputQueue>(pushModeSettings.maxQueueSize);
|
|
session().setAudioBufferInput(m_audioBufferInputQueue->mediaFrameInput());
|
|
m_audioBufferSource = std::make_unique<AudioBufferSource>(*audioGeneratorSettings,
|
|
pushModeSettings.producingRate);
|
|
m_audioBufferSource->addFrameReceivedCallback(&AudioBufferInputQueue::pushMediaFrame,
|
|
m_audioBufferInputQueue.get());
|
|
}
|
|
|
|
if (videoGeneratorSettings) {
|
|
m_videoFrameInputQueue =
|
|
std::make_unique<VideoFrameInputQueue>(pushModeSettings.maxQueueSize);
|
|
session().setVideoFrameInput(m_videoFrameInputQueue->mediaFrameInput());
|
|
m_videoFrameSource = std::make_unique<VideoFrameSource>(*videoGeneratorSettings,
|
|
pushModeSettings.producingRate);
|
|
m_videoFrameSource->addFrameReceivedCallback(&VideoFrameInputQueue::pushMediaFrame,
|
|
m_videoFrameInputQueue.get());
|
|
}
|
|
|
|
connect(this, &RecordingRunner::finished, this, &PushModeRecordingRunner::onFinished);
|
|
}
|
|
|
|
PushModeRecordingRunner::~PushModeRecordingRunner() = default;
|
|
|
|
void PushModeRecordingRunner::onFinished()
|
|
{
|
|
m_audioBufferSource.reset();
|
|
m_videoFrameSource.reset();
|
|
}
|
|
|
|
void PushModeRecordingRunner::run()
|
|
{
|
|
if (m_audioBufferSource)
|
|
m_audioBufferSource->run();
|
|
if (m_videoFrameSource)
|
|
m_videoFrameSource->run();
|
|
RecordingRunner::run();
|
|
}
|
|
|
|
#include "moc_recordingrunner.cpp"
|