From 9a2c018fe87f8b7cc22bd9cb93ac23633bcdb388 Mon Sep 17 00:00:00 2001 From: wang-bin Date: Sat, 3 Nov 2012 11:21:05 +0800 Subject: [PATCH] Limit buffered packets size when demuxing. Result in less memory usage TODO: configurable threshold --- src/AVDemuxThread.cpp | 17 +++++++++++++++++ src/AVThread.cpp | 10 ++++++++++ src/AudioThread.cpp | 8 +++++++- src/QtAV/AVDemuxThread.h | 5 +++++ src/QtAV/AVThread.h | 8 ++++++++ src/QtAV/private/AVThread_p.h | 5 ++++- src/VideoThread.cpp | 6 ++++++ 7 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index 714515c7..60a366fd 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -23,6 +23,8 @@ namespace QtAV { +const int kPktBufferSize = 512; + AVDemuxThread::AVDemuxThread(QObject *parent) : QThread(parent),end(false),demuxer(0),audio_thread(0),video_thread(0) { @@ -48,6 +50,7 @@ void AVDemuxThread::setAudioThread(AVThread *thread) audio_thread = 0; } audio_thread = thread; + audio_thread->setDemuxThread(this); } void AVDemuxThread::setVideoThread(AVThread *thread) @@ -58,6 +61,12 @@ void AVDemuxThread::setVideoThread(AVThread *thread) video_thread = 0; } video_thread = thread; + video_thread->setDemuxThread(this); +} + +void AVDemuxThread::readMoreFrames() +{ + buffer_cond.wakeAll(); } void AVDemuxThread::stop() @@ -81,7 +90,13 @@ void AVDemuxThread::run() int index = 0; Packet pkt; while (!end) { + buffer_mutex.lock(); + if (audio_thread->packetQueue()->size() > kPktBufferSize + && video_thread->packetQueue()->size() > kPktBufferSize) { + buffer_cond.wait(&buffer_mutex); + } if (!demuxer->readFrame()) { + buffer_mutex.unlock(); continue; } index = demuxer->stream(); @@ -93,8 +108,10 @@ void AVDemuxThread::run() video_thread->packetQueue()->enqueue(pkt); video_thread->wakeAll(); //need it? } else { //subtitle + buffer_mutex.unlock(); continue; } + buffer_mutex.unlock(); } qDebug("Demux thread stops running...."); } diff --git a/src/AVThread.cpp b/src/AVThread.cpp index 46bcb70b..21a0eb8d 100644 --- a/src/AVThread.cpp +++ b/src/AVThread.cpp @@ -46,6 +46,16 @@ void AVThread::wakeAll() d_ptr->condition.wakeAll(); } +void AVThread::setDemuxThread(AVDemuxThread *thread) +{ + d_ptr->demux_thread = thread; +} + +AVDemuxThread* AVThread::demuxThread() const +{ + return d_ptr->demux_thread; +} + void AVThread::setClock(AVClock *clock) { d_ptr->clock = clock; diff --git a/src/AudioThread.cpp b/src/AudioThread.cpp index d080d67a..9dd4c480 100644 --- a/src/AudioThread.cpp +++ b/src/AudioThread.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -35,6 +36,8 @@ extern "C" namespace QtAV { +const int kAPktBufferMin = 256; + class AudioThreadPrivate : public AVThreadPrivate { public: @@ -52,7 +55,7 @@ void AudioThread::run() if (!d_ptr->dec || !d_ptr->writer) return; Q_ASSERT(d_ptr->clock != 0); - + Q_ASSERT(d_ptr->demux_thread != 0); int sample_rate = d_ptr->dec->codecContext()->sample_rate; int channels = d_ptr->dec->codecContext()->channels; int csf = channels * sample_rate * sizeof(float); @@ -68,6 +71,9 @@ void AudioThread::run() break; } Packet pkt = d_ptr->packets.dequeue(); + if (d_ptr->packets.size() < kAPktBufferMin) { + d_ptr->demux_thread->readMoreFrames(); + } d_ptr->clock->updateValue(pkt.pts); if (d_ptr->dec->decode(pkt.data)) { QByteArray decoded(d_ptr->dec->data()); diff --git a/src/QtAV/AVDemuxThread.h b/src/QtAV/AVDemuxThread.h index f9e9a24c..d59383e8 100644 --- a/src/QtAV/AVDemuxThread.h +++ b/src/QtAV/AVDemuxThread.h @@ -19,7 +19,9 @@ #ifndef QAV_DEMUXTHREAD_H #define QAV_DEMUXTHREAD_H +#include #include +#include #include namespace QtAV { @@ -35,6 +37,7 @@ public: void setDemuxer(AVDemuxer *dmx); void setAudioThread(AVThread *thread); void setVideoThread(AVThread *thread); + void readMoreFrames(); //called by AVThread to demux more public slots: void stop(); @@ -47,6 +50,8 @@ private: AVDemuxer *demuxer; AVThread *audio_thread, *video_thread; int audio_stream, video_stream; + QMutex buffer_mutex; + QWaitCondition buffer_cond; }; } //namespace QtAV diff --git a/src/QtAV/AVThread.h b/src/QtAV/AVThread.h index 0a595ef7..aeb921a2 100644 --- a/src/QtAV/AVThread.h +++ b/src/QtAV/AVThread.h @@ -24,10 +24,12 @@ #include namespace QtAV { + class AVDecoder; class AVThreadPrivate; class AVOutput; class AVClock; +class AVDemuxThread; class Q_EXPORT AVThread : public QThread { Q_OBJECT @@ -50,6 +52,12 @@ public: void setOutput(AVOutput *out); AVOutput* output() const; +private: + friend class AVDemuxThread; + //notify demux thread to read more packets. call it internally when demux thread sets the avthread + void setDemuxThread(AVDemuxThread *thread); + AVDemuxThread* demuxThread() const; + protected: AVThread(AVThreadPrivate& d, QObject *parent = 0); diff --git a/src/QtAV/private/AVThread_p.h b/src/QtAV/private/AVThread_p.h index 5a59be85..3d5efe62 100644 --- a/src/QtAV/private/AVThread_p.h +++ b/src/QtAV/private/AVThread_p.h @@ -33,10 +33,12 @@ namespace QtAV { class AVDecoder; class Packet; class AVClock; +class AVDemuxThread; class AVThreadPrivate { public: - AVThreadPrivate():stop(false),clock(0),dec(0),writer(0) {} + AVThreadPrivate():stop(false),clock(0),dec(0),writer(0),demux_thread(0){ + } virtual ~AVThreadPrivate() { /*if (dec) { delete dec; @@ -63,6 +65,7 @@ public: AVOutput *writer; QMutex mutex; QWaitCondition condition; + AVDemuxThread *demux_thread; //notify it to read more packets }; } //namespace QtAV diff --git a/src/VideoThread.cpp b/src/VideoThread.cpp index 9e8492ff..321d4ec3 100644 --- a/src/VideoThread.cpp +++ b/src/VideoThread.cpp @@ -20,9 +20,11 @@ #include #include #include +#include namespace QtAV { +const int kVPktBufferMin = 256; const double kSyncThreshold = 0.005; // 5 ms class VideoThreadPrivate : public AVThreadPrivate @@ -49,6 +51,7 @@ void VideoThread::run() if (!d_ptr->dec || !d_ptr->writer) return; Q_ASSERT(d_ptr->clock != 0); + Q_ASSERT(d_ptr->demux_thread != 0); Q_D(VideoThread); while (!d_ptr->stop) { @@ -61,6 +64,9 @@ void VideoThread::run() break; } Packet pkt = d_ptr->packets.dequeue(); + if (d_ptr->packets.size() < kVPktBufferMin) { + d_ptr->demux_thread->readMoreFrames(); + } //Compare to the clock if (pkt.pts <= 0) { d_ptr->mutex.unlock();