Skip to content

Commit

Permalink
BlockingQueue: block for full/empty separately
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Jan 18, 2013
1 parent a3e4207 commit 0423522
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 10 deletions.
12 changes: 8 additions & 4 deletions src/AVDemuxThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ void AVDemuxThread::stop()
//this will not affect the pause state if we pause the output
audio_thread->setDemuxEnded(true);
video_thread->setDemuxEnded(true);
audio_thread->packetQueue()->setBlocking(false);
video_thread->packetQueue()->setBlocking(false);
audio_thread->packetQueue()->blockFull(false); //??
video_thread->packetQueue()->blockFull(false); //?
pause(false);
}

Expand Down Expand Up @@ -139,6 +139,8 @@ void AVDemuxThread::run()
pause(false);
PacketQueue *aqueue = audio_thread->packetQueue();
PacketQueue *vqueue = video_thread->packetQueue();
aqueue->setBlocking(true);
vqueue->setBlocking(true);
bool _has_audio = audio_thread->decoder()->isAvailable();
bool _has_video = video_thread->decoder()->isAvailable();
while (!end) {
Expand All @@ -156,10 +158,12 @@ void AVDemuxThread::run()
But usually it will not happen, why?
*/
if (index == audio_stream) {
aqueue->setBlocking(!_has_video || vqueue->size() >= vqueue->threshold());
if (_has_video)
aqueue->blockFull(vqueue->size() >= vqueue->threshold());
aqueue->put(pkt); //affect video_thread
} else if (index == video_stream) {
vqueue->setBlocking(!_has_audio || aqueue->size() >= aqueue->threshold());
if (_has_audio)
vqueue->blockFull(aqueue->size() >= aqueue->threshold());
vqueue->put(pkt); //affect audio_thread
} else { //subtitle
continue;
Expand Down
37 changes: 31 additions & 6 deletions src/QtAV/BlockingQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <QtCore/QReadWriteLock>
#include <QtCore/QWaitCondition>

//TODO: block full and empty condition separately
template<typename T> class QQueue;
namespace QtAV {

Expand All @@ -38,6 +39,8 @@ class BlockingQueue
void put(const T& t);
T take();
void setBlocking(bool block); //will wake if false. called when no more data can enqueue
void blockEmpty(bool block);
void blockFull(bool block);
//TODO:setMinBlock,MaxBlock
inline void clear();
inline bool isEmpty() const;
Expand All @@ -46,7 +49,7 @@ class BlockingQueue
inline int capacity() const;

private:
bool block;
bool block_empty, block_full;
int cap, thres; //static?
Container<T> queue;
mutable QReadWriteLock lock; //locker in const func
Expand All @@ -56,7 +59,7 @@ class BlockingQueue

template <typename T, template <typename> class Container>
BlockingQueue<T, Container>::BlockingQueue()
:block(true),cap(512),thres(128)
:block_empty(true),block_full(true),cap(128*3),thres(128)
{
}

Expand All @@ -81,7 +84,7 @@ void BlockingQueue<T, Container>::put(const T& t)
{
QWriteLocker locker(&lock);
Q_UNUSED(locker);
if (block && queue.size() >= cap)
if (block_full && queue.size() >= cap)
cond_full.wait(&lock);
queue.enqueue(t);
cond_empty.wakeAll();
Expand All @@ -94,7 +97,7 @@ T BlockingQueue<T, Container>::take()
Q_UNUSED(locker);
if (queue.size() < thres)
cond_full.wakeAll();
if (/*block && */queue.isEmpty())//TODO:always block?
if (block_empty && queue.isEmpty())//TODO:always block?
cond_empty.wait(&lock);
//TODO: Why still empty?
if (queue.isEmpty()) {
Expand All @@ -109,9 +112,31 @@ void BlockingQueue<T, Container>::setBlocking(bool block)
{
QWriteLocker locker(&lock);
Q_UNUSED(locker);
this->block = block;
block_empty = block_full = block;
if (!block) {
cond_empty.wakeAll(); //empty still wait. setBlock=>setCapacity(-1)
cond_full.wakeAll();
}
}

template <typename T, template <typename> class Container>
void BlockingQueue<T, Container>::blockEmpty(bool block)
{
QWriteLocker locker(&lock);
Q_UNUSED(locker);
block_empty = block;
if (!block) {
cond_empty.wakeAll();
}
}

template <typename T, template <typename> class Container>
void BlockingQueue<T, Container>::blockFull(bool block)
{
QWriteLocker locker(&lock);
Q_UNUSED(locker);
block_full = block;
if (!block) {
//cond_empty.wakeAll(); //empty still wait. setBlock=>setCapacity(-1)
cond_full.wakeAll();
}
}
Expand Down

0 comments on commit 0423522

Please sign in to comment.