Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qffmpegencodinginitializer.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
8#include "qvideoframe.h"
9
10#include "private/qplatformvideoframeinput_p.h"
11#include "private/qplatformaudiobufferinput_p.h"
12#include "private/qplatformaudiobufferinput_p.h"
13
15
16namespace QFFmpeg {
17
19
21{
22 for (QObject *source : m_pendingSources)
24}
25
26void EncodingInitializer::start(const std::vector<QPlatformAudioBufferInputBase *> &audioSources,
27 const std::vector<QPlatformVideoSource *> &videoSources)
28{
29 for (auto source : audioSources) {
30 if (auto audioInput = qobject_cast<QFFmpegAudioInput *>(source))
31 m_recordingEngine.addAudioInput(audioInput);
32 else if (auto audioBufferInput = qobject_cast<QPlatformAudioBufferInput *>(source))
33 addAudioBufferInput(audioBufferInput);
34 else
35 Q_ASSERT(!"Undefined source type");
36 }
37
38 for (auto source : videoSources)
39 addVideoSource(source);
40
41 tryStartRecordingEngine();
42}
43
44void EncodingInitializer::addAudioBufferInput(QPlatformAudioBufferInput *input)
45{
47
48 if (input->audioFormat().isValid())
49 m_recordingEngine.addAudioBufferInput(input, {});
50 else
51 addPendingAudioBufferInput(input);
52}
53
54void EncodingInitializer::addPendingAudioBufferInput(QPlatformAudioBufferInput *input)
55{
56 addPendingSource(input);
57
59 erasePendingSource(input, QStringLiteral("Audio source deleted"), true);
60 });
61
63 [this, input](const QAudioBuffer &buffer) {
64 if (buffer.isValid())
65 erasePendingSource(
66 input, [&]() { m_recordingEngine.addAudioBufferInput(input, buffer); });
67 else
68 erasePendingSource(input,
69 QStringLiteral("Audio source has sent the end frame"));
70 });
71}
72
73void EncodingInitializer::addVideoSource(QPlatformVideoSource *source)
74{
76 Q_ASSERT(source->isActive());
77
78 if (source->frameFormat().isValid())
79 m_recordingEngine.addVideoSource(source, {});
80 else if (source->hasError())
81 emitStreamInitializationError(QStringLiteral("Video source error: ")
82 + source->errorString());
83 else
84 addPendingVideoSource(source);
85}
86
87void EncodingInitializer::addPendingVideoSource(QPlatformVideoSource *source)
88{
89 addPendingSource(source);
90
92 if (source->hasError())
93 erasePendingSource(source,
94 QStringLiteral("Videio source error: ") + source->errorString());
95 });
96
98 erasePendingSource(source, QStringLiteral("Source deleted"), true);
99 });
100
102 if (!source->isActive())
103 erasePendingSource(source, QStringLiteral("Video source deactivated"));
104 });
105
107 [this, source](const QVideoFrame &frame) {
108 if (frame.isValid())
109 erasePendingSource(source,
110 [&]() { m_recordingEngine.addVideoSource(source, frame); });
111 else
112 erasePendingSource(source,
113 QStringLiteral("Video source has sent the end frame"));
114 });
115}
116
117void EncodingInitializer::tryStartRecordingEngine()
118{
119 if (m_pendingSources.empty())
120 m_recordingEngine.start();
121}
122
123void EncodingInitializer::emitStreamInitializationError(QString error)
124{
125 emit m_recordingEngine.streamInitializationError(
127 QStringLiteral("Video steam initialization error. ") + error);
128}
129
130void EncodingInitializer::addPendingSource(QObject *source)
131{
132 Q_ASSERT(m_pendingSources.count(source) == 0);
133
135 m_pendingSources.emplace(source);
136}
137
138template <typename F>
139void EncodingInitializer::erasePendingSource(QObject *source, F &&functionOrError, bool destroyed)
140{
141 const auto erasedCount = m_pendingSources.erase(source);
142 if (erasedCount == 0)
143 return; // got a queued event, just ignore it.
144
145 if (!destroyed) {
146 setEncoderInterface(source, nullptr);
147 disconnect(source, nullptr, this, nullptr);
148 }
149
150 if constexpr (std::is_invocable_v<F>)
151 functionOrError();
152 else
153 emitStreamInitializationError(functionOrError);
154
155 tryStartRecordingEngine();
156}
157
159{
160 return true;
161}
162
163} // namespace QFFmpeg
164
\inmodule QtMultimedia
EncodingInitializer(RecordingEngine &engine)
void start(const std::vector< QPlatformAudioBufferInputBase * > &audioSources, const std::vector< QPlatformVideoSource * > &videoSources)
void streamInitializationError(QMediaRecorder::Error code, const QString &description)
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void newAudioBuffer(const QAudioBuffer &buffer)
void newVideoFrame(const QVideoFrame &)
void activeChanged(bool)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:27
void setEncoderInterface(QObject *source, QMediaInputEncoderInterface *interface)
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
GLenum GLuint buffer
GLsizei GLsizei GLchar * source
GLenum GLenum GLenum input
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
#define emit
myObject disconnect()
[26]
QFrame frame
[0]
QJSEngine engine
[0]