Qt 6.x
The Qt SDK
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 <qdebug.h>
8
10
11namespace QFFmpeg {
12
14{
16public:
17 AudioSourceIO(QFFmpegAudioInput *audioInput) : QIODevice(), m_input(audioInput)
18 {
19 m_muted = m_input->muted;
20 m_volume = m_input->volume;
21 updateVolume();
23 }
24
25 ~AudioSourceIO() override = default;
26
28 {
29 QMutexLocker locker(&m_mutex);
30 if (m_device == device)
31 return;
32 m_device = device;
33 QMetaObject::invokeMethod(this, "updateSource");
34 }
36 {
37 QMutexLocker locker(&m_mutex);
38 m_bufferSize = m_format.bytesForFrames(frameSize);
39 }
40 void setRunning(bool r) {
41 QMutexLocker locker(&m_mutex);
42 if (m_running == r)
43 return;
44 m_running = r;
45 QMetaObject::invokeMethod(this, "updateRunning");
46 }
47
48 void setVolume(float vol) {
49 QMutexLocker locker(&m_mutex);
50 m_volume = vol;
51 QMetaObject::invokeMethod(this, "updateVolume");
52 }
53 void setMuted(bool muted) {
54 QMutexLocker locker(&m_mutex);
55 m_muted = muted;
56 QMetaObject::invokeMethod(this, "updateVolume");
57 }
58
59 int bufferSize() const { return m_bufferSize; }
60
61protected:
62 qint64 readData(char *, qint64) override
63 {
64 return 0;
65 }
66 qint64 writeData(const char *data, qint64 len) override
67 {
68 int l = len;
69 while (len > 0) {
70 int toAppend = qMin(len, m_bufferSize - m_pcm.size());
71 m_pcm.append(data, toAppend);
72 data += toAppend;
73 len -= toAppend;
74 if (m_pcm.size() == m_bufferSize)
75 sendBuffer();
76 }
77
78 return l;
79 }
80
81private Q_SLOTS:
82 void updateSource() {
83 QMutexLocker locker(&m_mutex);
84 m_format = m_device.preferredFormat();
85 if (std::exchange(m_src, nullptr))
86 m_pcm.clear();
87
88 m_src = std::make_unique<QAudioSource>(m_device, m_format);
89 updateVolume();
90 if (m_running)
91 m_src->start(this);
92 }
93 void updateVolume()
94 {
95 if (m_src)
96 m_src->setVolume(m_muted ? 0. : m_volume);
97 }
98 void updateRunning()
99 {
100 QMutexLocker locker(&m_mutex);
101 if (m_running) {
102 if (!m_src)
103 updateSource();
104 m_src->start(this);
105 } else {
106 m_src->stop();
107 }
108 }
109
110private:
111
112 void sendBuffer()
113 {
114 QAudioFormat fmt = m_src->format();
115 qint64 time = fmt.durationForBytes(m_processed);
116 QAudioBuffer buffer(m_pcm, fmt, time);
117 emit m_input->newAudioBuffer(buffer);
118 m_processed += m_bufferSize;
119 m_pcm.clear();
120 }
121
122 QMutex m_mutex;
123 QAudioDevice m_device;
124 float m_volume = 1.;
125 bool m_muted = false;
126 bool m_running = false;
127
128 QFFmpegAudioInput *m_input = nullptr;
129 std::unique_ptr<QAudioSource> m_src;
130 QAudioFormat m_format;
131 std::atomic<int> m_bufferSize = DefaultAudioInputBufferSize;
132 qint64 m_processed = 0;
133 QByteArray m_pcm;
134};
135
136}
137
140{
141 qRegisterMetaType<QAudioBuffer>();
142
143 inputThread = std::make_unique<QThread>();
144 audioIO = std::make_unique<QFFmpeg::AudioSourceIO>(this);
145 audioIO->moveToThread(inputThread.get());
146 inputThread->start();
147}
148
150{
151 inputThread->exit();
152 inputThread->wait();
153}
154
156{
157 audioIO->setDevice(device);
158}
159
161{
162 audioIO->setMuted(muted);
163}
164
166{
167 audioIO->setVolume(volume);
168}
169
171{
172 audioIO->setFrameSize(s);
173}
174
176{
177 audioIO->setRunning(b);
178}
179
181{
182 return audioIO->bufferSize();
183}
184
186
187#include "moc_qffmpegaudioinput_p.cpp"
188
189#include "qffmpegaudioinput.moc"
IOBluetoothDevice * device
\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.
\qmltype AudioInput \instantiates QAudioInput
Definition qaudioinput.h:19
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
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:317
\inmodule QtCore
Definition qmutex.h:285
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]
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLsizei len
GLdouble s
[6]
Definition qopenglext.h:235
static constexpr QSize frameSize(const T &frame)
#define Q_OBJECT
#define Q_SLOTS
#define emit
long long qint64
Definition qtypes.h:55
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...