Skip to content

Commit

Permalink
修改任务队列;
Browse files Browse the repository at this point in the history
  • Loading branch information
RealChuan committed Aug 24, 2023
1 parent bbab7f1 commit e89f8f2
Show file tree
Hide file tree
Showing 25 changed files with 321 additions and 280 deletions.
2 changes: 2 additions & 0 deletions ffmpeg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ set(PROJECT_SOURCES
decodersubtitleframe.hpp
decodervideoframe.cpp
decodervideoframe.h
event.cc
event.hpp
ffmepg_global.h
ffmpegutils.cc
ffmpegutils.hpp
Expand Down
25 changes: 10 additions & 15 deletions ffmpeg/audiodecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class AudioDecoder::AudioDecoderPrivate
};

AudioDecoder::AudioDecoder(QObject *parent)
: Decoder<Packet *>(parent)
: Decoder<PacketPtr>(parent)
, d_ptr(new AudioDecoderPrivate(this))
{
connect(d_ptr->decoderAudioFrame,
Expand All @@ -30,7 +30,13 @@ AudioDecoder::AudioDecoder(QObject *parent)
&AudioDecoder::positionChanged);
}

AudioDecoder::~AudioDecoder() {}
AudioDecoder::~AudioDecoder() = default;

void AudioDecoder::seek(qint64 seekTime)
{
Decoder<PacketPtr>::seek(seekTime);
d_ptr->decoderAudioFrame->seek(seekTime);
}

void AudioDecoder::pause(bool state)
{
Expand All @@ -52,25 +58,14 @@ void AudioDecoder::runDecoder()
d_ptr->decoderAudioFrame->startDecoder(m_formatContext, m_contextInfo);

while (m_runing) {
if (m_seek) {
clear();
d_ptr->decoderAudioFrame->seek(m_seekTime, m_latchPtr.lock());
seekFinish();
}

QScopedPointer<Packet> packetPtr(m_queue.dequeue());
auto packetPtr(m_queue.take());
if (packetPtr.isNull()) {
msleep(Sleep_Queue_Empty_Milliseconds);
continue;
}
auto frames(m_contextInfo->decodeFrame(packetPtr.data()));
for (auto frame : frames) {
Ffmpeg::calculateTime(frame, m_contextInfo, m_formatContext);
d_ptr->decoderAudioFrame->append(frame);
}

while (m_runing && d_ptr->decoderAudioFrame->size() > Max_Frame_Size && !m_seek) {
msleep(Sleep_Queue_Full_Milliseconds);
d_ptr->decoderAudioFrame->append(FramePtr(frame));
}
}
while (m_runing && d_ptr->decoderAudioFrame->size() != 0) {
Expand Down
4 changes: 3 additions & 1 deletion ffmpeg/audiodecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@

namespace Ffmpeg {

class AudioDecoder : public Decoder<Packet *>
class AudioDecoder : public Decoder<PacketPtr>
{
Q_OBJECT
public:
explicit AudioDecoder(QObject *parent = nullptr);
~AudioDecoder() override;

void seek(qint64 seekTime) override;

void pause(bool state) override;

void setVolume(qreal volume);
Expand Down
40 changes: 18 additions & 22 deletions ffmpeg/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@
#include <QSharedPointer>
#include <QThread>

#include <utils/countdownlatch.hpp>
#include <utils/taskqueue.h>
#include <utils/boundedblockingqueue.hpp>

#include "avcontextinfo.h"
#include "codeccontext.h"
#include "formatcontext.h"

#define Sleep_Queue_Full_Milliseconds 50
#define Sleep_Queue_Empty_Milliseconds 10
#define Max_Frame_Size 25
#define UnWait_Microseconds (50 * 1000)
#define Drop_Microseconds (-100 * 1000)

namespace Ffmpeg {

static const auto g_frameQueueSize = 25;

void calculateTime(Frame *frame, AVContextInfo *contextInfo, FormatContext *formatContext);
void calculateTime(Packet *packet, AVContextInfo *contextInfo);

Expand All @@ -34,6 +33,7 @@ class Decoder : public QThread
public:
explicit Decoder(QObject *parent = nullptr)
: QThread(parent)
, m_queue(g_frameQueueSize)
{}
~Decoder() override { stopDecoder(); }

Expand All @@ -49,37 +49,37 @@ class Decoder : public QThread
virtual void stopDecoder()
{
m_runing = false;
clear();
wakeup();
if (isRunning()) {
quit();
wait();
}
clear();
m_seekTime = 0;
}

void append(const T &t) { m_queue.enqueue(t); }
void append(const T &t) { m_queue.put(t); }
void append(const T &&t) { m_queue.put(t); }

auto size() -> int { return m_queue.size(); }
auto size() -> size_t { return m_queue.size(); }

void clear() { m_queue.clearPoints(); }
void clear() { m_queue.clear(); }

void wakeup() { m_queue.put(T()); }

virtual void pause(bool state) = 0;

void seek(qint64 seekTime, QSharedPointer<Utils::CountDownLatch> latchPtr) // microsecond
virtual void seek(qint64 seekTime) // microsecond
{
clear();
m_seekTime = seekTime;
assertVaild();
if (!m_contextInfo->isIndexVaild()) {
latchPtr->countDown();
return;
}
m_seek = true;
m_seekTime = seekTime;
m_latchPtr = latchPtr;
pause(false);
}

auto isSeek() -> bool { return m_seek; }

protected:
virtual void runDecoder() = 0;

Expand All @@ -92,21 +92,17 @@ class Decoder : public QThread
runDecoder();
}

void seekFinish() { m_seek = false; }

void assertVaild()
{
Q_ASSERT(m_formatContext != nullptr);
Q_ASSERT(m_contextInfo != nullptr);
}

Utils::Queue<T> m_queue;
Utils::BoundedBlockingQueue<T> m_queue;
AVContextInfo *m_contextInfo = nullptr;
FormatContext *m_formatContext = nullptr;
volatile bool m_runing = true;
volatile bool m_seek = false;
qint64 m_seekTime = 0; // seconds
QWeakPointer<Utils::CountDownLatch> m_latchPtr;
std::atomic_bool m_runing = true;
qint64 m_seekTime = 0; // microsecond
};

} // namespace Ffmpeg
Expand Down
89 changes: 46 additions & 43 deletions ffmpeg/decoderaudioframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <QCoreApplication>
#include <QMediaDevices>
#include <QMediaFormat>
#include <QTime>
#include <QWaitCondition>

namespace Ffmpeg {
Expand All @@ -25,21 +26,22 @@ class DecoderAudioFrame::DecoderAudioFramePrivate
QIODevice *audioDevice = nullptr;
qreal volume = 0.5;

volatile bool pause = false;
std::atomic_bool pause = false;
double speed = 0;
qint64 pauseTime;
QMutex mutex;
QWaitCondition waitCondition;

qint64 seekTime = 0; // milliseconds
volatile bool firstSeekFrame = false;
std::atomic_bool firstSeekFrame = false;

QScopedPointer<QMediaDevices> mediaDevicesPtr;
volatile bool audioOutputsChanged = false;
volatile bool isLocalFile = true;
std::atomic_bool audioOutputsChanged = false;
std::atomic_bool isLocalFile = true;
};

DecoderAudioFrame::DecoderAudioFrame(QObject *parent)
: Decoder<Frame *>(parent)
: Decoder<FramePtr>(parent)
, d_ptr(new DecoderAudioFramePrivate(this))
{
buildConnect();
Expand All @@ -50,7 +52,15 @@ DecoderAudioFrame::~DecoderAudioFrame() = default;
void DecoderAudioFrame::stopDecoder()
{
pause(false);
Decoder<Frame *>::stopDecoder();
Decoder<FramePtr>::stopDecoder();
}

void DecoderAudioFrame::seek(qint64 seekTime)
{
Decoder<FramePtr>::seek(seekTime);
setMediaClock(m_seekTime);
d_ptr->firstSeekFrame = true;
d_ptr->pauseTime = 0;
}

void DecoderAudioFrame::pause(bool state)
Expand Down Expand Up @@ -112,22 +122,21 @@ void DecoderAudioFrame::onAudioOutputsChanged()

void DecoderAudioFrame::runDecoder()
{
quint64 dropNum = 0;
QAudioDevice audioDevice(QMediaDevices::defaultAudioOutput());
auto format = resetAudioOutput();
d_ptr->seekTime = 0;
d_ptr->pauseTime = 0;
AudioFrameConverter audioConverter(m_contextInfo->codecCtx(), format);
QElapsedTimer timer;
if (d_ptr->isLocalFile) { // 音频播放依赖外部时钟,适用于本地文件播放
qint64 pauseTime = 0;
while (m_runing) {
checkDefaultAudioOutput(audioDevice);
checkPause(pauseTime);
checkSeek(pauseTime);
checkSpeed(timer, pauseTime);
checkPause(d_ptr->pauseTime);
checkSpeed(timer, d_ptr->pauseTime);

QScopedPointer<Frame> framePtr(m_queue.dequeue());
auto framePtr(m_queue.take());
if (framePtr.isNull()) {
msleep(Sleep_Queue_Empty_Milliseconds);
continue;
}
if (!timer.isValid()) {
Expand All @@ -144,17 +153,24 @@ void DecoderAudioFrame::runDecoder()
}

auto audioBuf = audioConverter.convert(framePtr.data());
auto diff = pts - d_ptr->seekTime - (timer.elapsed() - pauseTime) * d_ptr->speed * 1000;
auto diff = pts - d_ptr->seekTime
- (timer.elapsed() - d_ptr->pauseTime) * d_ptr->speed * 1000;
// qDebug() << "PTS:"
// << QTime::fromMSecsSinceStartOfDay(pts / 1000).toString("hh:mm:ss.zzz")
// << "SeekTime:"
// << QTime::fromMSecsSinceStartOfDay(d_ptr->seekTime / 1000)
// .toString("hh:mm:ss.zzz")
// << "Diff:" << diff;
{
auto cleanup = qScopeGuard([&] {
setMediaClock(pts);
emit positionChanged(pts);
});
if (qAbs(diff) > UnWait_Microseconds && !m_seek && !d_ptr->pause) {
if (qAbs(diff) > UnWait_Microseconds && !d_ptr->pause) {
QMutexLocker locker(&d_ptr->mutex);
d_ptr->waitCondition.wait(&d_ptr->mutex, diff / 1000);
//msleep(diff);
d_ptr->waitCondition.wait(&d_ptr->mutex, qAbs(diff) / 1000);
} else if (d_ptr->speed > 1.0) {
dropNum++;
continue; // speed > 1.0 drop
}
}
Expand All @@ -165,25 +181,28 @@ void DecoderAudioFrame::runDecoder()
qint64 lastPts = 0;
while (m_runing) {
checkDefaultAudioOutput(audioDevice);
qint64 pauseTime = 0;
checkPause(pauseTime);
checkSeek(lastPts);
checkPause(d_ptr->pauseTime);
checkSpeed(timer, lastPts);

QScopedPointer<Frame> framePtr(m_queue.dequeue());
auto framePtr(m_queue.take());
if (framePtr.isNull()) {
msleep(Sleep_Queue_Empty_Milliseconds);
continue;
}
auto pts = framePtr->pts();
if (m_seekTime > pts) {
continue;
}
if (d_ptr->firstSeekFrame) {
d_ptr->seekTime = pts;
d_ptr->firstSeekFrame = false;
lastPts = 0;
}

QByteArray audioBuf = audioConverter.convert(framePtr.data());
auto audioBuf = audioConverter.convert(framePtr.data());
double diff = 0;
if (lastPts > 0) {
diff = pts - lastPts - (durationTimer.elapsed() - pauseTime) * d_ptr->speed * 1000;
diff = pts - lastPts
- (durationTimer.elapsed() - d_ptr->pauseTime) * d_ptr->speed * 1000;
}
lastPts = pts;
{
Expand All @@ -192,18 +211,19 @@ void DecoderAudioFrame::runDecoder()
setMediaClock(pts);
emit positionChanged(pts);
});
if (diff > 0 && !m_seek && !d_ptr->pause) {
if (diff > 0 && !d_ptr->pause) {
QMutexLocker locker(&d_ptr->mutex);
d_ptr->waitCondition.wait(&d_ptr->mutex, diff / 1000);
//msleep(diff);
} else if (d_ptr->speed > 1.0) {
dropNum++;
continue; // speed > 1.0 drop
}
}
writeToDevice(audioBuf);
}
}
d_ptr->audioSinkPtr.reset();
qInfo() << "Audio Drop Num:" << dropNum;
}

void DecoderAudioFrame::buildConnect()
Expand Down Expand Up @@ -245,23 +265,6 @@ void DecoderAudioFrame::checkPause(qint64 &pauseTime)
}
}

void DecoderAudioFrame::checkSeek(qint64 &pauseTime)
{
if (!m_seek) {
return;
}
clear();
pauseTime = 0;
setMediaClock(m_seekTime);
d_ptr->seekTime = m_seekTime * 1000;
auto latchPtr = m_latchPtr.lock();
if (latchPtr) {
latchPtr->countDown();
}
seekFinish();
d_ptr->firstSeekFrame = true;
}

void DecoderAudioFrame::checkSpeed(QElapsedTimer &timer, qint64 &pauseTime)
{
auto speed = mediaSpeed();
Expand All @@ -279,7 +282,7 @@ void DecoderAudioFrame::writeToDevice(QByteArray &audioBuf)
if (!d_ptr->audioDevice) {
return;
}
while (audioBuf.size() > 0 && !m_seek && !d_ptr->pause) {
while (audioBuf.size() > 0 && !d_ptr->pause) {
int byteFree = d_ptr->audioSinkPtr->bytesFree();
if (byteFree > 0 && byteFree < audioBuf.size()) {
d_ptr->audioDevice->write(audioBuf.data(), byteFree); // Memory leak
Expand Down
Loading

0 comments on commit e89f8f2

Please sign in to comment.