Skip to content

Commit

Permalink
优化默认音频播放设备切换;
Browse files Browse the repository at this point in the history
  • Loading branch information
RealChuan committed Sep 6, 2023
1 parent ce28c40 commit 40eb03e
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 76 deletions.
2 changes: 0 additions & 2 deletions ffmpeg/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
set(PROJECT_SOURCES
audiorender/audioconfig.cc
audiorender/audioconfig.hpp
audiorender/audiooutput.cc
audiorender/audiooutput.hpp
audiorender/audiooutputthread.cc
Expand Down
11 changes: 3 additions & 8 deletions ffmpeg/audiodisplay.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "audiodisplay.hpp"
#include "audioframeconverter.h"
#include "clock.hpp"
#include "codeccontext.h"

#include <audiorender/audiooutputthread.hpp>
#include <event/seekevent.hpp>
Expand Down Expand Up @@ -83,12 +81,9 @@ void AudioDisplay::setMasterClock()
void AudioDisplay::runDecoder()
{
quint64 dropNum = 0;
int sampleSize = 0;
auto format = getAudioFormatFromCodecCtx(m_contextInfo->codecCtx(), sampleSize);
QScopedPointer<AudioOutputThread> audioOutputThreadPtr(new AudioOutputThread);
d_ptr->audioOutputThreadPtr = audioOutputThreadPtr.data();
audioOutputThreadPtr->openOutput({format, format.sampleRate() * sampleSize / 8, d_ptr->volume});
AudioFrameConverter audioConverter(m_contextInfo->codecCtx(), format);
audioOutputThreadPtr->openOutput(m_contextInfo, d_ptr->volume);
bool firstFrame = false;
while (m_runing.load()) {
d_ptr->processEvent(firstFrame);
Expand All @@ -103,7 +98,7 @@ void AudioDisplay::runDecoder()
firstFrame = true;
d_ptr->clock->reset(framePtr->pts());
}
auto audioBuf = audioConverter.convert(framePtr.data());
emit audioOutputThreadPtr->convertData(framePtr);
auto pts = framePtr->pts();
d_ptr->clock->update(pts, av_gettime_relative());
qint64 delay = 0;
Expand All @@ -123,7 +118,7 @@ void AudioDisplay::runDecoder()
}
// qDebug() << "Audio PTS:"
// << QTime::fromMSecsSinceStartOfDay(pts / 1000).toString("hh:mm:ss.zzz");
emit audioOutputThreadPtr->wirteData(audioBuf);
emit audioOutputThreadPtr->wirteData();
}
qInfo() << "Audio Drop Num:" << dropNum;
}
Expand Down
5 changes: 0 additions & 5 deletions ffmpeg/audiodisplay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
#include "decoder.h"
#include "frame.hpp"

#include <QAudio>
#include <QAudioFormat>

class QAudioDevice;

namespace Ffmpeg {

class AudioDisplay : public Decoder<FramePtr>
Expand Down
2 changes: 1 addition & 1 deletion ffmpeg/audioframeconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class AudioFrameConverter::AudioFrameConverterPrivate
};

AudioFrameConverter::AudioFrameConverter(CodecContext *codecCtx,
QAudioFormat &format,
const QAudioFormat &format,
QObject *parent)
: QObject(parent)
, d_ptr(new AudioFrameConverterPrivate(this))
Expand Down
2 changes: 1 addition & 1 deletion ffmpeg/audioframeconverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class AudioFrameConverter : public QObject
{
public:
explicit AudioFrameConverter(CodecContext *codecCtx,
QAudioFormat &format,
const QAudioFormat &format,
QObject *parent = nullptr);
~AudioFrameConverter() override;

Expand Down
2 changes: 0 additions & 2 deletions ffmpeg/audiorender/audioconfig.cc

This file was deleted.

21 changes: 0 additions & 21 deletions ffmpeg/audiorender/audioconfig.hpp

This file was deleted.

61 changes: 42 additions & 19 deletions ffmpeg/audiorender/audiooutput.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include "audiooutput.hpp"

#include <ffmpeg/audioframeconverter.h>
#include <ffmpeg/avcontextinfo.h>
#include <utils/threadsafequeue.hpp>

#include <QApplication>
#include <QAudioSink>
#include <QDebug>
Expand All @@ -25,17 +29,20 @@ class AudioOutput::AudioOutputPrivate
}
~AudioOutputPrivate() = default;

void reset(const Audio::Config &config)
void reset()
{
this->config = config;
printAudioOuputDevice();
audioDevice = QMediaDevices::defaultAudioOutput();

audioSinkPtr.reset(new QAudioSink(config.format));
audioSinkPtr->setBufferSize(config.bufferSize);
audioSinkPtr->setVolume(config.volume);
int sampleSize = 0;
auto format = getAudioFormatFromCodecCtx(contextInfo->codecCtx(), sampleSize);
audioConverterPtr.reset(new AudioFrameConverter(contextInfo->codecCtx(), format));

audioSinkPtr.reset(new QAudioSink(format));
audioSinkPtr->setBufferSize(format.sampleRate() * sampleSize / 8);
audioSinkPtr->setVolume(volume);
ioDevice = audioSinkPtr->start();
if (!ioDevice) {
if (ioDevice == nullptr) {
qWarning() << "Create AudioDevice Failed!";
}
QObject::connect(audioSinkPtr.data(),
Expand All @@ -46,45 +53,61 @@ class AudioOutput::AudioOutputPrivate

AudioOutput *q_ptr;

Audio::Config config;
AVContextInfo *contextInfo;

QScopedPointer<AudioFrameConverter> audioConverterPtr;

qreal volume = 0.5;
QScopedPointer<QAudioSink> audioSinkPtr;
QIODevice *ioDevice = nullptr;
QMediaDevices *mediaDevices;
QAudioDevice audioDevice;
QByteArray audioBuf;
};

AudioOutput::AudioOutput(const Audio::Config &config, QObject *parent)
AudioOutput::AudioOutput(AVContextInfo *contextInfo, qreal volume, QObject *parent)
: QObject{parent}
, d_ptr(new AudioOutputPrivate(this))
{
d_ptr->reset(config);

d_ptr->contextInfo = contextInfo;
d_ptr->volume = volume;
d_ptr->reset();
buildConnect();
}

AudioOutput::~AudioOutput() = default;

void AudioOutput::onWrite(const QByteArray &audioBuf)
void AudioOutput::onConvertData(const QSharedPointer<Ffmpeg::Frame> &framePtr)
{
if (!d_ptr->ioDevice) {
return;
}

auto audioBuf = d_ptr->audioConverterPtr->convert(framePtr.data());
d_ptr->audioBuf += audioBuf;
}

void AudioOutput::onWrite()
{
if (!d_ptr->ioDevice) {
return;
}
auto buf = audioBuf;
while (buf.size() > 0) {
while (d_ptr->audioBuf.size() > 0) {
int byteFree = d_ptr->audioSinkPtr->bytesFree();
if (byteFree > 0 && byteFree < buf.size()) {
d_ptr->ioDevice->write(buf.data(), byteFree);
buf = buf.sliced(byteFree);
if (byteFree > 0 && byteFree < d_ptr->audioBuf.size()) {
d_ptr->ioDevice->write(d_ptr->audioBuf.data(), byteFree);
d_ptr->audioBuf = d_ptr->audioBuf.sliced(byteFree);
} else {
d_ptr->ioDevice->write(buf);
d_ptr->ioDevice->write(d_ptr->audioBuf);
d_ptr->audioBuf.clear();
break;
}
}
}

void AudioOutput::onSetVolume(qreal value)
{
d_ptr->config.volume = value;
d_ptr->volume = value;
if (d_ptr->audioSinkPtr.isNull()) {
return;
}
Expand All @@ -109,7 +132,7 @@ void AudioOutput::onAudioOutputsChanged()
}
qInfo() << "AudioDevice Change: " << d_ptr->audioDevice.description() << "->"
<< QMediaDevices::defaultAudioOutput().description();
d_ptr->reset(d_ptr->config);
d_ptr->reset();
}

void AudioOutput::buildConnect()
Expand Down
12 changes: 7 additions & 5 deletions ffmpeg/audiorender/audiooutput.hpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
#ifndef AUDIOOUTPUT_HPP
#define AUDIOOUTPUT_HPP

#include "audioconfig.hpp"

#include <QAudio>
#include <QObject>

namespace Ffmpeg {

class AVContextInfo;
class Frame;

class AudioOutput : public QObject
{
Q_OBJECT
public:
explicit AudioOutput(const Audio::Config &config, QObject *parent = nullptr);
~AudioOutput();
explicit AudioOutput(AVContextInfo *contextInfo, qreal volume = 0.5, QObject *parent = nullptr);
~AudioOutput() override;

public slots:
void onWrite(const QByteArray &audioBuf);
void onConvertData(const QSharedPointer<Ffmpeg::Frame> &framePtr);
void onWrite();
void onSetVolume(qreal value);

private slots:
Expand Down
20 changes: 15 additions & 5 deletions ffmpeg/audiorender/audiooutputthread.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "audiooutputthread.hpp"
#include "audiooutput.hpp"

#include <ffmpeg/frame.hpp>

namespace Ffmpeg {

class AudioOutputThread::AudioOutputThreadPrivate
Expand All @@ -12,23 +14,27 @@ class AudioOutputThread::AudioOutputThreadPrivate

AudioOutputThread *q_ptr;

Audio::Config config;
AVContextInfo *contextInfo;
qreal volume = 0.5;
};

AudioOutputThread::AudioOutputThread(QObject *parent)
: QThread{parent}
, d_ptr(new AudioOutputThreadPrivate(this))
{}
{
qRegisterMetaType<QSharedPointer<Ffmpeg::Frame>>("QSharedPointer<Ffmpeg::Frame>");
}

AudioOutputThread::~AudioOutputThread()
{
closeOutput();
}

void AudioOutputThread::openOutput(const Audio::Config &config)
void AudioOutputThread::openOutput(AVContextInfo *contextInfo, qreal volume)
{
closeOutput();
d_ptr->config = config;
d_ptr->contextInfo = contextInfo;
d_ptr->volume = volume;
start();
}

Expand All @@ -42,7 +48,11 @@ void AudioOutputThread::closeOutput()

void AudioOutputThread::run()
{
QScopedPointer<AudioOutput> audioOutputPtr(new AudioOutput(d_ptr->config));
QScopedPointer<AudioOutput> audioOutputPtr(new AudioOutput(d_ptr->contextInfo, d_ptr->volume));
connect(this,
&AudioOutputThread::convertData,
audioOutputPtr.data(),
&AudioOutput::onConvertData);
connect(this, &AudioOutputThread::wirteData, audioOutputPtr.data(), &AudioOutput::onWrite);
connect(this,
&AudioOutputThread::volumeChanged,
Expand Down
10 changes: 6 additions & 4 deletions ffmpeg/audiorender/audiooutputthread.hpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
#ifndef AUDIOOUTPUTTHREAD_HPP
#define AUDIOOUTPUTTHREAD_HPP

#include "audioconfig.hpp"

#include <QThread>

namespace Ffmpeg {

class Frame;
class AVContextInfo;

class AudioOutputThread : public QThread
{
Q_OBJECT
public:
explicit AudioOutputThread(QObject *parent = nullptr);
~AudioOutputThread() override;

void openOutput(const Audio::Config &config);
void openOutput(AVContextInfo *contextInfo, qreal volume);
void closeOutput();

signals:
void wirteData(const QByteArray &data);
void convertData(const QSharedPointer<Ffmpeg::Frame> &frameptr);
void wirteData();
void volumeChanged(qreal value);

protected:
Expand Down
3 changes: 0 additions & 3 deletions ffmpeg/audiorender/audiorender.pri
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
HEADERS += \
$$PWD/audioconfig.hpp \
$$PWD/audiooutput.hpp \
$$PWD/audiooutputthread.hpp

SOURCES += \
$$PWD/audioconfig.cc \
$$PWD/audiooutput.cc \
$$PWD/audiooutputthread.cc

0 comments on commit 40eb03e

Please sign in to comment.