Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qaudiobufferinput.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
5
6#include <QtMultimedia/private/qmediaframeinput_p.h>
7#include <QtMultimedia/private/qmediainputencoderinterface_p.h>
8#include <QtMultimedia/private/qplatformaudiobufferinput_p.h>
9
11
13{
14public:
15 QAudioBufferInputPrivate(QAudioBufferInput *q) : q(q) { }
16
17 bool sendAudioBuffer(const QAudioBuffer &audioBuffer)
18 {
19 return sendMediaFrame(
20 [&]() { emit m_platfromAudioBufferInput->newAudioBuffer(audioBuffer); });
21 }
22
23 void initialize(const QAudioFormat &format = {})
24 {
25 m_platfromAudioBufferInput = std::make_unique<QPlatformAudioBufferInput>(format);
26 addUpdateSignal(m_platfromAudioBufferInput.get(),
27 &QPlatformAudioBufferInput::encoderUpdated);
28 }
29
31 {
32 m_platfromAudioBufferInput.reset();
33
34 if (captureSession())
35 captureSession()->setAudioBufferInput(nullptr);
36 }
37
38 QMediaCaptureSession *session() const { return m_captureSession; }
39
40 QPlatformAudioBufferInput *platfromAudioBufferInput() const
41 {
42 return m_platfromAudioBufferInput.get();
43 }
44
45private:
46 void updateCaptureSessionConnections(QMediaCaptureSession *prevSession,
47 QMediaCaptureSession *newSession) override
48 {
49 if (prevSession)
50 removeUpdateSignal(prevSession, &QMediaCaptureSession::audioOutputChanged);
51
52 if (newSession)
53 addUpdateSignal(newSession, &QMediaCaptureSession::audioOutputChanged);
54 }
55
57 {
58 if (auto encoderInterface = m_platfromAudioBufferInput->encoderInterface())
59 return encoderInterface->canPushFrame();
60
61 // Not implemented yet
62 // return captureSession()->audioOutput() != nullptr;
63 return false;
64 }
65
66 void emitReadyToSendMediaFrame() override { emit q->readyToSendAudioBuffer(); }
67
68private:
69 QAudioBufferInput *q = nullptr;
70 QMediaCaptureSession *m_captureSession = nullptr;
71 std::unique_ptr<QPlatformAudioBufferInput> m_platfromAudioBufferInput;
72};
73
74/*!
75 \class QAudioBufferInput
76 \inmodule QtMultimedia
77 \ingroup multimedia
78 \ingroup multimedia_audio
79 \since 6.8
80
81 \brief The QAudioBufferInput class is used for providing custom audio buffers
82 to \l QMediaRecorder through \l QMediaCaptureSession.
83
84 QAudioBufferInput is only supported with the FFmpeg backend.
85
86 Custom audio buffers can be recorded by connecting a \l QAudioBufferInput and a
87 \l QMediaRecorder to a \l QMediaCaptureSession. For a pull mode implementation,
88 call \l sendAudioBuffer() in response to the \l readyToSendAudioBuffer() signal.
89 In the snippet below this is done by connecting the signal to a slot in a custom
90 media generator class. The slot function emits another signal with a new audio
91 buffer, which is connected to \l sendAudioBuffer():
92
93 \snippet custommediainputsnippets/custommediainputsnippets.cpp QAudioBufferInput setup
94
95 Here's a minimal implementation of the slot function that provides audio buffers:
96
97 \snippet custommediainputsnippets/custommediainputsnippets.cpp nextAudioBuffer()
98
99 For more details see readyToSendAudioBuffer() and sendAudioBuffer().
100
101 \sa QMediaRecorder and QMediaCaptureSession.
102*/
103
104/*!
105 Constructs a new QAudioBufferInput object with \a parent.
106*/
107QAudioBufferInput::QAudioBufferInput(QObject *parent) : QAudioBufferInput({}, parent) { }
108
109/*!
110 Constructs a new QAudioBufferInput object with audio \a format and \a parent.
111
112 The specified \a format will work as a hint for the initialization of the matching
113 audio encoder upon invoking \l QMediaRecorder::record().
114 If the format is not specified or not valid, the audio encoder will be initialized
115 upon sending the first audio buffer.
116
117 We recommend specifying the format if you know in advance what kind of audio buffers
118 you're going to send.
119*/
120QAudioBufferInput::QAudioBufferInput(const QAudioFormat &format, QObject *parent)
121 : QObject(*new QAudioBufferInputPrivate(this), parent)
122{
123 Q_D(QAudioBufferInput);
124 d->initialize(format);
125}
126
127/*!
128 Destroys the object.
129 */
130QAudioBufferInput::~QAudioBufferInput()
131{
132 Q_D(QAudioBufferInput);
133 d->uninitialize();
134}
135
136/*!
137 Sends \l QAudioBuffer to \l QMediaRecorder through \l QMediaCaptureSession.
138
139 Returns \c true if the specified \a audioBuffer has been sent successfully
140 to the destination. Returns \c false, if the buffer hasn't been sent,
141 which can happen if the instance is not assigned to
142 \l QMediaCaptureSession, the session doesn't have a media recorder,
143 the media recorder is not started or its queue is full.
144 The \l readyToSendAudioBuffer() signal will be emitted as soon as
145 the destination is able to handle a new audio buffer.
146
147 Sending of an empty audio buffer is treated by \l QMediaRecorder
148 as an end of the input stream. QMediaRecorder stops the recording
149 automatically if \l QMediaRecorder::autoStop is \c true and
150 all the inputs have reported the end of the stream.
151*/
152bool QAudioBufferInput::sendAudioBuffer(const QAudioBuffer &audioBuffer)
153{
154 Q_D(QAudioBufferInput);
155 return d->sendAudioBuffer(audioBuffer);
156}
157
158/*!
159 Returns the audio format that was specified upon construction of the audio buffer input.
160*/
161QAudioFormat QAudioBufferInput::format() const
162{
163 Q_D(const QAudioBufferInput);
164 return d->platfromAudioBufferInput()->audioFormat();
165}
166
167/*!
168 Returns the capture session this audio buffer input is connected to, or
169 a \c nullptr if the audio buffer input is not connected to a capture session.
170
171 Use QMediaCaptureSession::setAudioBufferInput() to connect
172 the audio buffer input to a session.
173*/
174QMediaCaptureSession *QAudioBufferInput::captureSession() const
175{
176 Q_D(const QAudioBufferInput);
177 return d->captureSession();
178}
179
180void QAudioBufferInput::setCaptureSession(QMediaCaptureSession *captureSession)
181{
182 Q_D(QAudioBufferInput);
183 d->setCaptureSession(captureSession);
184}
185
186QPlatformAudioBufferInput *QAudioBufferInput::platformAudioBufferInput() const
187{
188 Q_D(const QAudioBufferInput);
189 return d->platfromAudioBufferInput();
190}
191
192/*!
193 \fn void QAudioBufferInput::readyToSendAudioBuffer()
194
195 Signals that a new audio buffer can be sent to the audio buffer input.
196 After receiving the signal, if you have audio date to be sent, invoke \l sendAudioBuffer
197 once or in a loop until it returns \c false.
198
199 \sa sendAudioBuffer()
200*/
201
202QT_END_NAMESPACE
void updateCaptureSessionConnections(QMediaCaptureSession *prevSession, QMediaCaptureSession *newSession) override
QMediaCaptureSession * session() const
bool sendAudioBuffer(const QAudioBuffer &audioBuffer)
bool checkIfCanSendMediaFrame() const override
QPlatformAudioBufferInput * platfromAudioBufferInput() const
QAudioBufferInputPrivate(QAudioBufferInput *q)
void initialize(const QAudioFormat &format={})
void emitReadyToSendMediaFrame() override
Combined button and popup list for selecting options.