Skip to content

Commit

Permalink
seek forward support. not good enough
Browse files Browse the repository at this point in the history
TODO: more accurate delay. seek backward. no crash when seeking
  • Loading branch information
wang-bin committed Nov 13, 2012
1 parent 4e863d5 commit 26d9b0e
Show file tree
Hide file tree
Showing 11 changed files with 1,005 additions and 884 deletions.
2 changes: 1 addition & 1 deletion QtAV.pro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ libqtav.file = src/libQtAV.pro
test.file = test/tst_QtAV.pro
test.depends += libqtav

OTHER_FILES += README.md
OTHER_FILES += README.md TODO.txt


250 changes: 138 additions & 112 deletions src/AVDemuxThread.cpp
Original file line number Diff line number Diff line change
@@ -1,112 +1,138 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2012 Wang Bin <[email protected]>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include <QtAV/AVDemuxThread.h>
#include <QtAV/AVDemuxer.h>
#include <QtAV/Packet.h>
#include <QtAV/AVThread.h>

namespace QtAV {

AVDemuxThread::AVDemuxThread(QObject *parent) :
QThread(parent),end(false),demuxer(0),audio_thread(0),video_thread(0)
{
}

AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) :
QThread(parent),end(false),audio_thread(0),video_thread(0)
{
setDemuxer(dmx);
}

void AVDemuxThread::setDemuxer(AVDemuxer *dmx)
{
demuxer = dmx;
connect(dmx, SIGNAL(finished()), this, SLOT(stop()), Qt::QueuedConnection);
}

void AVDemuxThread::setAudioThread(AVThread *thread)
{
if (audio_thread) {
audio_thread->stop();
delete audio_thread;
audio_thread = 0;
}
audio_thread = thread;
}

void AVDemuxThread::setVideoThread(AVThread *thread)
{
if (video_thread) {
video_thread->stop();
delete video_thread;
video_thread = 0;
}
video_thread = thread;
}

//No more data to put. So stop blocking the queue to take the reset elements
void AVDemuxThread::stop()
{
end = true;
//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);
}

void AVDemuxThread::run()
{
end = false;
Q_ASSERT(audio_thread != 0);
Q_ASSERT(video_thread != 0);
if (!audio_thread->isRunning())
audio_thread->start(QThread::HighPriority);
if (!video_thread->isRunning())
video_thread->start();

audio_stream = demuxer->audioStream();
video_stream = demuxer->videoStream();

int index = 0;
Packet pkt;
end = false;
buffer_mutex.unlock();
while (!end) {
buffer_mutex.lock();
if (!demuxer->readFrame()) {
buffer_mutex.unlock();
continue;
}
index = demuxer->stream();
pkt = *demuxer->packet(); //TODO: how to avoid additional copy?
if (index == audio_stream) {
audio_thread->packetQueue()->put(pkt); //affect video_thread
} else if (index == video_stream) {
video_thread->packetQueue()->put(pkt); //affect audio_thread
} else { //subtitle
buffer_mutex.unlock();
continue;
}
buffer_mutex.unlock();
}
qDebug("Demux thread stops running....");
}

} //namespace QtAV
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2012 Wang Bin <[email protected]>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include <QtAV/AVDemuxThread.h>
#include <QtAV/AVDemuxer.h>
#include <QtAV/Packet.h>
#include <QtAV/AVThread.h>

namespace QtAV {

AVDemuxThread::AVDemuxThread(QObject *parent) :
QThread(parent),end(false),demuxer(0),audio_thread(0),video_thread(0)
{
}

AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) :
QThread(parent),end(false),audio_thread(0),video_thread(0)
{
setDemuxer(dmx);
}

void AVDemuxThread::setDemuxer(AVDemuxer *dmx)
{
demuxer = dmx;
connect(dmx, SIGNAL(finished()), this, SLOT(stop()), Qt::QueuedConnection);
}

void AVDemuxThread::setAudioThread(AVThread *thread)
{
if (audio_thread) {
audio_thread->stop();
delete audio_thread;
audio_thread = 0;
}
audio_thread = thread;
}

void AVDemuxThread::setVideoThread(AVThread *thread)
{
if (video_thread) {
video_thread->stop();
delete video_thread;
video_thread = 0;
}
video_thread = thread;
}

void AVDemuxThread::seek(qreal pos)
{
audio_thread->packetQueue()->clear();
video_thread->packetQueue()->clear();
demuxer->seek(pos);
}

void AVDemuxThread::seekForward()
{
audio_thread->packetQueue()->clear();
video_thread->packetQueue()->clear();
demuxer->seekForward();
}

void AVDemuxThread::seekBackward()
{
audio_thread->packetQueue()->clear();
video_thread->packetQueue()->clear();
demuxer->seekBackward();
}
//No more data to put. So stop blocking the queue to take the reset elements
void AVDemuxThread::stop()
{
end = true;
//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);
}

void AVDemuxThread::run()
{
end = false;
Q_ASSERT(audio_thread != 0);
Q_ASSERT(video_thread != 0);
if (!audio_thread->isRunning())
audio_thread->start(QThread::HighPriority);
if (!video_thread->isRunning())
video_thread->start();

audio_stream = demuxer->audioStream();
video_stream = demuxer->videoStream();

int index = 0;
Packet pkt;
end = false;
buffer_mutex.unlock();
while (!end) { //TODO: mutex locker
buffer_mutex.lock();
if (!demuxer->readFrame()) {
buffer_mutex.unlock();
continue;
}
index = demuxer->stream();
pkt = *demuxer->packet(); //TODO: how to avoid additional copy?
/*1 is empty but another is enough, then do not block to
ensure the empty one can put packets immediatly.
But usually it will not happen, why?
*/
if (index == audio_stream) {
//audio_thread->packetQueue()->setBlocking(video_thread->packetQueue()->size() >= 256);
audio_thread->packetQueue()->put(pkt); //affect video_thread
} else if (index == video_stream) {
//video_thread->packetQueue()->setBlocking(audio_thread->packetQueue()->size() >= 256);
video_thread->packetQueue()->put(pkt); //affect audio_thread
} else { //subtitle
buffer_mutex.unlock();
continue;
}
buffer_mutex.unlock();
}
qDebug("Demux thread stops running....");
}

} //namespace QtAV
Loading

0 comments on commit 26d9b0e

Please sign in to comment.