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
qffmpegaudioinput.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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
4#include <qiodevice.h>
5#include <qaudiosource.h>
6#include <qaudiobuffer.h>
7#include <qatomic.h>
8#include <qdebug.h>
9
11
12namespace QFFmpeg {
13
15{
17public:
18 AudioSourceIO(QFFmpegAudioInput *audioInput) : QIODevice(), m_input(audioInput)
19 {
20 m_muted = m_input->muted;
21 m_volume = m_input->volume;
22 updateVolume();
24 }
25
26 ~AudioSourceIO() override = default;
27
29 {
30 QMutexLocker locker(&m_mutex);
31 if (m_device == device)
32 return;
33 m_device = device;
34 QMetaObject::invokeMethod(this, "updateSource");
35 }
37 {
38 m_bufferSize.storeRelease((frameSize > 0 && m_format.isValid())
39 ? m_format.bytesForFrames(frameSize)
41 }
42 void setRunning(bool r) {
43 QMutexLocker locker(&m_mutex);
44 if (m_running == r)
45 return;
46 m_running = r;
47 QMetaObject::invokeMethod(this, "updateRunning");
48 }
49
50 void setVolume(float vol) {
51 QMutexLocker locker(&m_mutex);
52 m_volume = vol;
53 QMetaObject::invokeMethod(this, "updateVolume");
54 }
55 void setMuted(bool muted) {
56 QMutexLocker locker(&m_mutex);
57 m_muted = muted;
58 QMetaObject::invokeMethod(this, "updateVolume");
59 }
60
61 int bufferSize() const { return m_bufferSize.loadAcquire(); }
62
63protected:
64 qint64 readData(char *, qint64) override
65 {
66 return 0;
67 }
68 qint64 writeData(const char *data, qint64 len) override
69 {
70 int l = len;
71 while (len > 0) {
72 const auto bufferSize = m_bufferSize.loadAcquire();
73 int toAppend = qMin(len, bufferSize - m_pcm.size());
74 m_pcm.append(data, toAppend);
75 data += toAppend;
76 len -= toAppend;
77 if (m_pcm.size() == bufferSize)
78 sendBuffer();
79 }
80
81 return l;
82 }
83
84private Q_SLOTS:
85 void updateSource() {
86 QMutexLocker locker(&m_mutex);
87 m_format = m_device.preferredFormat();
88 if (std::exchange(m_src, nullptr))
89 m_pcm.clear();
90
91 m_src = std::make_unique<QAudioSource>(m_device, m_format);
92 updateVolume();
93 if (m_running)
94 m_src->start(this);
95 }
96 void updateVolume()
97 {
98 if (m_src)
99 m_src->setVolume(m_muted ? 0. : m_volume);
100 }
101 void updateRunning()
102 {
103 QMutexLocker locker(&m_mutex);
104 if (m_running) {
105 if (!m_src)
106 updateSource();
107 m_src->start(this);
108 } else {
109 m_src->stop();
110 }
111 }
112
113private:
114
115 void sendBuffer()
116 {
117 QAudioFormat fmt = m_src->format();
118 qint64 time = fmt.durationForBytes(m_processed);
119 QAudioBuffer buffer(m_pcm, fmt, time);
120 emit m_input->newAudioBuffer(buffer);
121 m_processed += m_pcm.size();
122 m_pcm.clear();
123 }
124
125 QMutex m_mutex;
126 QAudioDevice m_device;
127 float m_volume = 1.;
128 bool m_muted = false;
129 bool m_running = false;
130
131 QFFmpegAudioInput *m_input = nullptr;
132 std::unique_ptr<QAudioSource> m_src;
133 QAudioFormat m_format;
135 qint64 m_processed = 0;
136 QByteArray m_pcm;
137};
138
139}
140
143{
144 qRegisterMetaType<QAudioBuffer>();
145
146 inputThread = std::make_unique<QThread>();
147 audioIO = new QFFmpeg::AudioSourceIO(this);
148 audioIO->moveToThread(inputThread.get());
149 inputThread->start();
150}
151
153{
154 // Ensure that COM is uninitialized by nested QWindowsResampler
155 // on the same thread that initialized it.
156 audioIO->deleteLater();
157 inputThread->exit();
158 inputThread->wait();
159}
160
165
167{
168 audioIO->setMuted(muted);
169}
170
172{
173 audioIO->setVolume(volume);
174}
175
177{
178 audioIO->setFrameSize(s);
179}
180
182{
183 audioIO->setRunning(b);
184}
185
187{
188 return audioIO->bufferSize();
189}
190
192
193#include "moc_qffmpegaudioinput_p.cpp"
194
195#include "qffmpegaudioinput.moc"
IOBluetoothDevice * device
\inmodule QtCore
Definition qatomic.h:112
\inmodule QtMultimedia
The QAudioDevice class provides an information about audio devices and their functionality.
QAudioFormat preferredFormat() const
Returns the default audio format settings for this device.
The QAudioFormat class stores audio stream parameter information.
Q_MULTIMEDIA_EXPORT qint32 bytesForFrames(qint32 frameCount) const
Returns the number of bytes required for frameCount frames of this format.
constexpr bool isValid() const noexcept
Returns true if all of the parameters are valid.
\qmltype AudioInput \instantiates QAudioInput
Definition qaudioinput.h:19
T loadAcquire() const noexcept
void storeRelease(T newValue) noexcept
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
void clear()
Clears the contents of the byte array and makes it null.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void newAudioBuffer(const QAudioBuffer &buffer)
void setFrameSize(int frameSize)
void setAudioDevice(const QAudioDevice &) override
void setVolume(float) override
void setMuted(bool) override
QFFmpegAudioInput(QAudioInput *qq)
void setDevice(const QAudioDevice &device)
void setFrameSize(int frameSize)
qint64 writeData(const char *data, qint64 len) override
Writes up to maxSize bytes from data to the device.
qint64 readData(char *, qint64) override
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
AudioSourceIO(QFFmpegAudioInput *audioInput)
~AudioSourceIO() override=default
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
Definition qobject.cpp:1643
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
Combined button and popup list for selecting options.
constexpr int DefaultAudioInputBufferSize
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLboolean GLboolean GLboolean b
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLdouble s
[6]
Definition qopenglext.h:235
GLenum GLsizei len
static constexpr QSize frameSize(const T &frame)
#define Q_OBJECT
#define Q_SLOTS
#define emit
long long qint64
Definition qtypes.h:60
QVideoFrameFormat::PixelFormat fmt
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...