summaryrefslogtreecommitdiffstats
path: root/src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp')
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp132
1 files changed, 51 insertions, 81 deletions
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp b/src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp
index 71979e04f..014c53ca4 100644
--- a/src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp
+++ b/src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qffmpegaudioinput_p.h"
#include <qiodevice.h>
#include <qaudiosource.h>
#include <qaudiobuffer.h>
+#include <qatomic.h>
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@@ -49,37 +14,33 @@ namespace QFFmpeg {
class AudioSourceIO : public QIODevice
{
Q_OBJECT
- public:
- AudioSourceIO(QFFmpegAudioInput *audioInput)
- : QIODevice()
- , input(audioInput)
+public:
+ AudioSourceIO(QFFmpegAudioInput *audioInput) : QIODevice(), m_input(audioInput)
{
- m_muted = input->muted;
- m_volume = input->volume;
+ m_muted = m_input->muted;
+ m_volume = m_input->volume;
updateVolume();
open(QIODevice::WriteOnly);
}
- ~AudioSourceIO()
- {
- delete m_src;
- }
+
+ ~AudioSourceIO() override = default;
void setDevice(const QAudioDevice &device)
{
- QMutexLocker locker(&mutex);
+ QMutexLocker locker(&m_mutex);
if (m_device == device)
return;
m_device = device;
QMetaObject::invokeMethod(this, "updateSource");
}
- void setFrameSize(int s)
+ void setFrameSize(int frameSize)
{
- QMutexLocker locker(&mutex);
- frameSize = s;
- bufferSize = m_format.bytesForFrames(frameSize);
+ m_bufferSize.storeRelease((frameSize > 0 && m_format.isValid())
+ ? m_format.bytesForFrames(frameSize)
+ : DefaultAudioInputBufferSize);
}
void setRunning(bool r) {
- QMutexLocker locker(&mutex);
+ QMutexLocker locker(&m_mutex);
if (m_running == r)
return;
m_running = r;
@@ -87,16 +48,17 @@ class AudioSourceIO : public QIODevice
}
void setVolume(float vol) {
- QMutexLocker locker(&mutex);
+ QMutexLocker locker(&m_mutex);
m_volume = vol;
QMetaObject::invokeMethod(this, "updateVolume");
}
void setMuted(bool muted) {
- QMutexLocker locker(&mutex);
+ QMutexLocker locker(&m_mutex);
m_muted = muted;
QMetaObject::invokeMethod(this, "updateVolume");
}
+ int bufferSize() const { return m_bufferSize.loadAcquire(); }
protected:
qint64 readData(char *, qint64) override
@@ -107,11 +69,12 @@ protected:
{
int l = len;
while (len > 0) {
- int toAppend = qMin(len, bufferSize - pcm.size());
- pcm.append(data, toAppend);
+ const auto bufferSize = m_bufferSize.loadAcquire();
+ int toAppend = qMin(len, bufferSize - m_pcm.size());
+ m_pcm.append(data, toAppend);
data += toAppend;
len -= toAppend;
- if (pcm.size() == bufferSize)
+ if (m_pcm.size() == bufferSize)
sendBuffer();
}
@@ -120,13 +83,12 @@ protected:
private Q_SLOTS:
void updateSource() {
- QMutexLocker locker(&mutex);
+ QMutexLocker locker(&m_mutex);
m_format = m_device.preferredFormat();
- if (m_src) {
- delete m_src;
- pcm.clear();
- }
- m_src = new QAudioSource(m_device, m_format);
+ if (std::exchange(m_src, nullptr))
+ m_pcm.clear();
+
+ m_src = std::make_unique<QAudioSource>(m_device, m_format);
updateVolume();
if (m_running)
m_src->start(this);
@@ -138,7 +100,7 @@ private Q_SLOTS:
}
void updateRunning()
{
- QMutexLocker locker(&mutex);
+ QMutexLocker locker(&m_mutex);
if (m_running) {
if (!m_src)
updateSource();
@@ -153,26 +115,25 @@ private:
void sendBuffer()
{
QAudioFormat fmt = m_src->format();
- qint64 time = fmt.durationForBytes(processed);
- QAudioBuffer buffer(pcm, fmt, time);
- emit input->newAudioBuffer(buffer);
- processed += bufferSize;
- pcm.clear();
+ qint64 time = fmt.durationForBytes(m_processed);
+ QAudioBuffer buffer(m_pcm, fmt, time);
+ emit m_input->newAudioBuffer(buffer);
+ m_processed += m_pcm.size();
+ m_pcm.clear();
}
- QMutex mutex;
+ QMutex m_mutex;
QAudioDevice m_device;
float m_volume = 1.;
bool m_muted = false;
bool m_running = false;
- QFFmpegAudioInput *input = nullptr;
- QAudioSource *m_src = nullptr;
+ QFFmpegAudioInput *m_input = nullptr;
+ std::unique_ptr<QAudioSource> m_src;
QAudioFormat m_format;
- int frameSize = 0;
- int bufferSize = 0;
- qint64 processed = 0;
- QByteArray pcm;
+ QAtomicInt m_bufferSize = DefaultAudioInputBufferSize;
+ qint64 m_processed = 0;
+ QByteArray m_pcm;
};
}
@@ -182,17 +143,19 @@ QFFmpegAudioInput::QFFmpegAudioInput(QAudioInput *qq)
{
qRegisterMetaType<QAudioBuffer>();
- inputThread = new QThread;
+ inputThread = std::make_unique<QThread>();
audioIO = new QFFmpeg::AudioSourceIO(this);
- audioIO->moveToThread(inputThread);
+ audioIO->moveToThread(inputThread.get());
inputThread->start();
}
QFFmpegAudioInput::~QFFmpegAudioInput()
{
+ // Ensure that COM is uninitialized by nested QWindowsResampler
+ // on the same thread that initialized it.
+ audioIO->deleteLater();
inputThread->exit();
inputThread->wait();
- delete inputThread;
}
void QFFmpegAudioInput::setAudioDevice(const QAudioDevice &device)
@@ -220,6 +183,13 @@ void QFFmpegAudioInput::setRunning(bool b)
audioIO->setRunning(b);
}
+int QFFmpegAudioInput::bufferSize() const
+{
+ return audioIO->bufferSize();
+}
+
QT_END_NAMESPACE
+#include "moc_qffmpegaudioinput_p.cpp"
+
#include "qffmpegaudioinput.moc"