From d2c4d070be09ef1ef660b10ee6eaeb482abb0cbb Mon Sep 17 00:00:00 2001 From: wang-bin Date: Tue, 14 Apr 2015 14:39:58 +0800 Subject: [PATCH] handle error in 1 place. correctly detect network error --- src/AVDemuxer.cpp | 38 +++++++++++++++----------------------- src/AVPlayer.cpp | 4 ++-- src/QtAV/AVDemuxer.h | 12 ++++++++---- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/AVDemuxer.cpp b/src/AVDemuxer.cpp index bd6d360e..08bcd2b5 100644 --- a/src/AVDemuxer.cpp +++ b/src/AVDemuxer.cpp @@ -129,7 +129,7 @@ public: return -1; } //check manual interruption - if (handler->getStatus() > 0) { + if (handler->getStatus() < 0) { qDebug("User Interrupt: -> quit!"); // DO NOT call setMediaStatus() here. /* MUST make sure blocking functions (open, read) return before we change the status @@ -165,15 +165,14 @@ public: return 0; qDebug("Timeout expired: %lld/%lld -> quit!", handler->mTimer.elapsed(), handler->mTimeout); handler->mTimer.invalidate(); - AVError err; + handler->mStatus = int(AVError::ReadTimedout); if (handler->mAction == Open) { - err.setError(AVError::OpenTimedout); + handler->mStatus = int(AVError::OpenTimedout); } else if (handler->mAction == FindStreamInfo) { - err.setError(AVError::FindStreamInfoTimedout); + handler->mStatus = int(AVError::FindStreamInfoTimedout); } else if (handler->mAction == Read) { - err.setError(AVError::ReadTimedout); + handler->mStatus = int(AVError::ReadTimedout); } - QMetaObject::invokeMethod(handler->mpDemuxer, "error", Qt::AutoConnection, Q_ARG(QtAV::AVError, err)); return 1; } private: @@ -967,23 +966,14 @@ void AVDemuxer::setInterruptTimeout(qint64 timeout) d->interrupt_hanlder->setTimeout(timeout); } -/** - * @brief getInterruptStatus return the interrupt status - * @return - */ -bool AVDemuxer::getInterruptStatus() const +int AVDemuxer::getInterruptStatus() const { - return d->interrupt_hanlder->getStatus() == 1 ? true : false; + return d->interrupt_hanlder->getStatus(); } -/** - * @brief setInterruptStatus set the interrupt status - * @param interrupt - * @return - */ -void AVDemuxer::setInterruptStatus(bool interrupt) +void AVDemuxer::setInterruptStatus(int interrupt) { - d->interrupt_hanlder->setStatus(interrupt ? 1 : 0); + d->interrupt_hanlder->setStatus(interrupt); } void AVDemuxer::setOptions(const QVariantHash &dict) @@ -1127,18 +1117,20 @@ void AVDemuxer::handleError(int averr, AVError::ErrorCode *errorCode, QString &m if (interrupted) { // interrupted by callback, so can not determine whether the media is valid // insufficient buffering or other interruptions setMediaStatus(StalledMedia); - if (getInterruptStatus()) + if (getInterruptStatus() < 0) { + emit userInterrupted(); err_msg += " [" + tr("interrupted by user") + "]"; - else + } else { + // averr is eof for open timeout err_msg += " [" + tr("timeout") + "]"; - emit userInterrupted(); + } } else { if (mediaStatus() == LoadingMedia) setMediaStatus(InvalidMedia); } if (!errorCode) return; - AVError::ErrorCode ec(AVError::OpenError); + AVError::ErrorCode ec(*errorCode); if (averr == AVERROR_INVALIDDATA) { // leave it if reading if (*errorCode == AVError::OpenError) ec = AVError::FormatError; diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index 164e9a00..f2b2a3e8 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -630,7 +630,7 @@ void AVPlayer::unload() connect(&d->demuxer, SIGNAL(loaded()), this, SLOT(unloadInternal())); // user interrupt if still loading connect(&d->demuxer, SIGNAL(userInterrupted()), this, SLOT(unloadInternal())); - d->demuxer.setInterruptStatus(1); + d->demuxer.setInterruptStatus(-1); } void AVPlayer::unloadInternal() @@ -1105,7 +1105,7 @@ void AVPlayer::aboutToQuitApp() pause(false); // may be paused. then aboutToQuitApp will not finish stop(); } - d->demuxer.setInterruptStatus(true); + d->demuxer.setInterruptStatus(-1); loaderThreadPool()->waitForDone(); } diff --git a/src/QtAV/AVDemuxer.h b/src/QtAV/AVDemuxer.h index 7466900d..c665c743 100644 --- a/src/QtAV/AVDemuxer.h +++ b/src/QtAV/AVDemuxer.h @@ -148,14 +148,18 @@ public: */ void setInterruptTimeout(qint64 timeout); /** - * @brief getInterruptStatus return the interrupt status + * @brief getInterruptStatus return the interrupt status. + * \return -1: interrupted by user + * 0: not interrupted + * >0: timeout value of AVError::ErrorCode */ - bool getInterruptStatus() const; + int getInterruptStatus() const; /** * @brief setInterruptStatus set the interrupt status - * @param interrupt true: abort current operation like loading and reading packets. false: no interrupt + * @param interrupt <0: abort current operation like loading and reading packets. + * 0: no interrupt */ - void setInterruptStatus(bool interrupt); + void setInterruptStatus(int interrupt); /*! * \brief setOptions * libav's AVDictionary. we can ignore the flags used in av_dict_xxx because we can use hash api.