diff options
Diffstat (limited to 'src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp')
-rw-r--r-- | src/plugins/multimedia/ffmpeg/qffmpegaudioinput.cpp | 132 |
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" |