From 8892d0ee9c1f4ca8b7647ce6340963306f164bbf Mon Sep 17 00:00:00 2001 From: "Dimitri E. Prado" Date: Fri, 25 Oct 2013 12:31:55 -0700 Subject: [PATCH] Fix corrupt initial frames https://github.com/wang-bin/QtAV/issues/70 There is a race condition where AVDemuxThread starts queueing packets before AVThread::resetState is called from VideoThread. When AVThread:: resetState gets called, all collected frames get dropped. This patch waits on a conditional variable for AVThreads to start properly. --- src/AVPlayer.cpp | 2 ++ src/AVThread.cpp | 15 ++++++++++++++- src/QtAV/AVThread.h | 2 ++ src/QtAV/private/AVThread_p.h | 4 ++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index 2d146a791..3f91ae2b9 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -676,10 +676,12 @@ void AVPlayer::play() if (aCodecCtx && audio_thread) { qDebug("Starting audio thread..."); audio_thread->start(); + audio_thread->waitForReady(); } if (vCodecCtx && video_thread) { qDebug("Starting video thread..."); video_thread->start(); + video_thread->waitForReady(); } demuxer_thread->start(); //blockSignals(false); diff --git a/src/AVThread.cpp b/src/AVThread.cpp index eaf52b3f0..104402d4d 100644 --- a/src/AVThread.cpp +++ b/src/AVThread.cpp @@ -36,6 +36,7 @@ AVThreadPrivate::~AVThreadPrivate() { next_pause = false; cond.wakeAll(); } + ready_cond.wakeAll(); packets.setBlocking(true); //??? packets.clear(); //not neccesary context is managed by filters. @@ -120,8 +121,9 @@ void AVThread::stop() pause(false); if (d.writer) d.writer->pause(false); //stop waiting + QMutexLocker lock(&d.ready_mutex); + d.ready = false; //terminate(); - } //TODO: output set @@ -227,6 +229,9 @@ void AVThread::resetState() d.packets.clear(); //not neccesary context is managed by filters. d.filter_context = 0; + QMutexLocker lock(&d.ready_mutex); + d.ready = true; + d.ready_cond.wakeOne(); } bool AVThread::tryPause(int timeout) @@ -260,4 +265,12 @@ void AVThread::setStatistics(Statistics *statistics) d.statistics = statistics; } +void AVThread::waitForReady() +{ + QMutexLocker lock(&d_func().ready_mutex); + while (!d_func().ready) { + d_func().ready_cond.wait(&d_func().ready_mutex); + } +} + } //namespace QtAV diff --git a/src/QtAV/AVThread.h b/src/QtAV/AVThread.h index 68c72dbf7..d160f0cdc 100644 --- a/src/QtAV/AVThread.h +++ b/src/QtAV/AVThread.h @@ -68,6 +68,8 @@ class Q_AV_EXPORT AVThread : public QThread bool isPaused() const; + void waitForReady(); + bool installFilter(Filter *filter, bool lock = true); bool uninstallFilter(Filter *filter, bool lock = true); const QList &filters() const; diff --git a/src/QtAV/private/AVThread_p.h b/src/QtAV/private/AVThread_p.h index d6b88c20a..6e7aca00d 100644 --- a/src/QtAV/private/AVThread_p.h +++ b/src/QtAV/private/AVThread_p.h @@ -56,6 +56,7 @@ class Q_AV_EXPORT AVThreadPrivate : public DPtrPrivate , delay(0) , filter_context(0) , statistics(0) + , ready(false) { } //DO NOT delete dec and writer. We do not own them @@ -77,6 +78,9 @@ class Q_AV_EXPORT AVThreadPrivate : public DPtrPrivate Statistics *statistics; //not obj. Statistics is unique for the player, which is in AVPlayer QList update_outputs; QList tasks; + QWaitCondition ready_cond; + QMutex ready_mutex; + bool ready; }; } //namespace QtAV