我目前正在开发一个使用Qt进行原始视频数据播放的多线程应用程序。有三个工作线程。一个是Reader Thread,一个是Processor Thread,另一个是Video Output Thread。读取器线程将原始数据读入缓冲区,然后处理器将处理原始数据并将可显示数据放入帧FIFO。
我的原始数据缓冲区实现为哈希表,这意味着每个帧索引都将具有其对应的原始数据。一旦处理器完成一个特定帧处理原始数据,它就会从原始数据缓冲区中删除原始数据,这样一旦读回到之前读取的帧,读者就可以将数据读入缓冲区。
我现在在实现暂停功能时遇到问题。我想做的是当视频暂停时,处理器和阅读器应该退出,视频输出线程只会在fifo中显示一个相同的帧。我现在可以正确退出处理器线程。读者似乎陷入了循环等待状态。
以下是我读者线程的一些代码。
void ReaderThread::run()
{
forever
{
//inputState_ is internal state of the reader
if (inputState_ == stop)
// return from run() if state is stop
return;
//dataBuffer is a pointer to raw data buffer object
//This grab the mutex lock of the raw data buffer
dataBuffer->lock()
//frameIndex is counter for frame
if (dataBuffer->contains(frameIndex_))
{
//mutex_ is a member variable of type QMutex
mutex_.lock();
//Wait for the data to be removed.
dataBuffer->waitForWritable();
mutex_.unlock();
}
dataBuffer->unlock();
// Read data to raw frame buffer
uchar rawDataPointer = readRawData();
dataBuffer->lock();
//insert the frame number and corresponding pointer into the hash table
dataBuffer->insert(frameIndex, rawDataPointer);
//wake up processor.
dataBuffer->wakeForReadable()
dataBuffer->unlock();
mutex_.lock();
if (inputState_ == play)
frameIndex++;
mutex_.unlock();
}
}
void ReaderThread::stop()
{
mutex_.lock();
inputState_ = stop;
//Wake up the reader if the reader is waiting
dataBuffer->wakeAllWritable();
mutex_.unlock();
// Wait for run() to return.
QThread::wait();
}
处理器线程的实现类似。我首先停止处理器并且成功了。当我想从run()返回时,我从主线程调用ReaderThread :: stop()。但是我进入了一个循环等待条件,如果读者线程正在等待缓冲区可写,它永远不会解锁这个读者线程的mutex_。结果,停止将始终阻止,程序只是挂起。我试着在dataBuffer-> waitForWritable()之前不要锁定mutex_,但是,我遇到了这样一种情况,即在调用dataBuffer-> wakeAllWritable()之后,读者线程将在可写权限上等待。
有人可以提出解决此问题的方法吗?我一直在努力弄清楚如何摆脱这种循环等待条件的情况,但由于我仍然是线程编程的新手,所以没有完全解决。
答案 0 :(得分:1)
我认为你应该在使用stop()之前锁定dataBuffer,如下所示:
void ReaderThread::stop()
{
mutex_.lock();
inputState_ = stop;
mutex_.unlock();
//Wake up the reader if the reader is waiting
dataBuffer->lock();
dataBuffer->wakeAllWritable();
dataBuffer->unlock();
// Wait for run() to return.
QThread::wait();
}
这样你可以删除mutex_.lock()&从其他方法解锁:
//dataBuffer is a pointer to raw data buffer object
//This grab the mutex lock of the raw data buffer
dataBuffer->lock()
//frameIndex is counter for frame
if (dataBuffer->contains(frameIndex_))
{
dataBuffer->waitForWritable();
}
dataBuffer->unlock();