From ec245921865eda2bc57397c1979c92fa10adfd98 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 19 Sep 2014 09:53:53 +0200 Subject: Android: fix some problems with the media player. - Correctly emit positionChanged signal. One of the problems with this was that QMediaPlayer automatically sends periodic position updates while playing a media. There's no need to have the same logic in the backend. - Seeking after reaching the end of the media now correctly works Auto tests included. Change-Id: I6d5ecbae6e05f94a8aac1a0834cf57427adf219b Reviewed-by: Christian Stromme --- .../android/multimedia/QtAndroidMediaPlayer.java | 20 ---- .../src/mediaplayer/qandroidmediaplayercontrol.cpp | 130 +++++++++++---------- .../src/mediaplayer/qandroidmediaplayercontrol.h | 1 + 3 files changed, 69 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java index ade2517d2..5e6630de8 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java @@ -83,23 +83,6 @@ public class QtAndroidMediaPlayer private volatile int mState = State.Uninitialized; - private class ProgressWatcher - implements Runnable - { - @Override - public void run() - { - try { - while ((mState & (State.Started)) != 0) { - onProgressUpdateNative(getCurrentPosition(), mID); - Thread.sleep(1000); - } - } catch (final InterruptedException e) { - // Ignore - } - } - } - /** * MediaPlayer OnErrorListener */ @@ -257,8 +240,6 @@ public class QtAndroidMediaPlayer try { mMediaPlayer.start(); setState(State.Started); - Thread progressThread = new Thread(new ProgressWatcher()); - progressThread.start(); } catch (final IllegalStateException e) { Log.d(TAG, "" + e.getMessage()); } @@ -309,7 +290,6 @@ public class QtAndroidMediaPlayer try { mMediaPlayer.seekTo(msec); - onProgressUpdateNative(msec, mID); } catch (final IllegalStateException e) { Log.d(TAG, "" + e.getMessage()); } diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp index fb1c8b72f..eae09c64f 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -86,6 +86,7 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent) mPendingSetMedia(false), mPendingVolume(-1), mPendingMute(-1), + mReloadingMedia(false), mActiveStateChangeNotifiers(0) { connect(mMediaPlayer,SIGNAL(bufferingChanged(qint32)), @@ -138,17 +139,14 @@ qint64 QAndroidMediaPlayerControl::position() const if (mCurrentMediaStatus == QMediaPlayer::EndOfMedia) return duration(); - if ((mState & (AndroidMediaPlayer::Idle - | AndroidMediaPlayer::Initialized - | AndroidMediaPlayer::Prepared + if ((mState & (AndroidMediaPlayer::Prepared | AndroidMediaPlayer::Started | AndroidMediaPlayer::Paused - | AndroidMediaPlayer::Stopped - | AndroidMediaPlayer::PlaybackCompleted)) == 0) { - return (mPendingPosition == -1) ? 0 : mPendingPosition; + | AndroidMediaPlayer::PlaybackCompleted))) { + return mMediaPlayer->getCurrentPosition(); } - return (mCurrentState == QMediaPlayer::StoppedState) ? 0 : mMediaPlayer->getCurrentPosition(); + return (mPendingPosition == -1) ? 0 : mPendingPosition; } void QAndroidMediaPlayerControl::setPosition(qint64 position) @@ -158,26 +156,25 @@ void QAndroidMediaPlayerControl::setPosition(qint64 position) const int seekPosition = (position > INT_MAX) ? INT_MAX : position; - if ((mState & (AndroidMediaPlayer::Prepared - | AndroidMediaPlayer::Started - | AndroidMediaPlayer::Paused - | AndroidMediaPlayer::PlaybackCompleted)) == 0) { - if (mPendingPosition != seekPosition) { - mPendingPosition = seekPosition; - Q_EMIT positionChanged(seekPosition); - } + if (seekPosition == this->position()) return; - } StateChangeNotifier notifier(this); if (mCurrentMediaStatus == QMediaPlayer::EndOfMedia) setMediaStatus(QMediaPlayer::LoadedMedia); - mMediaPlayer->seekTo(seekPosition); + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { + mPendingPosition = seekPosition; + } else { + mMediaPlayer->seekTo(seekPosition); - if (mPendingPosition != -1) { - mPendingPosition = -1; + if (mPendingPosition != -1) { + mPendingPosition = -1; + } } Q_EMIT positionChanged(seekPosition); @@ -310,9 +307,9 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, { StateChangeNotifier notifier(this); - const bool reloading = (mMediaContent == mediaContent); + mReloadingMedia = (mMediaContent == mediaContent); - if (!reloading) { + if (!mReloadingMedia) { mMediaContent = mediaContent; mMediaStream = stream; } @@ -321,43 +318,45 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, if ((mState & (AndroidMediaPlayer::Idle | AndroidMediaPlayer::Uninitialized)) == 0) mMediaPlayer->release(); + QString mediaPath; + if (mediaContent.isNull()) { setMediaStatus(QMediaPlayer::NoMedia); - return; - } - - if (mVideoOutput && !mVideoOutput->isReady()) { - // if a video output is set but the video texture is not ready, delay loading the media - // since it can cause problems on some hardware - mPendingSetMedia = true; - return; - } - - const QUrl url = mediaContent.canonicalUrl(); - QString mediaPath; - if (url.scheme() == QLatin1String("qrc")) { - const QString path = url.toString().mid(3); - mTempFile.reset(QTemporaryFile::createNativeFile(path)); - if (!mTempFile.isNull()) - mediaPath = QStringLiteral("file://") + mTempFile->fileName(); } else { - mediaPath = url.toString(); - } + if (mVideoOutput && !mVideoOutput->isReady()) { + // if a video output is set but the video texture is not ready, delay loading the media + // since it can cause problems on some hardware + mPendingSetMedia = true; + return; + } - if (mVideoSize.isValid() && mVideoOutput) - mVideoOutput->setVideoSize(mVideoSize); + const QUrl url = mediaContent.canonicalUrl(); + if (url.scheme() == QLatin1String("qrc")) { + const QString path = url.toString().mid(3); + mTempFile.reset(QTemporaryFile::createNativeFile(path)); + if (!mTempFile.isNull()) + mediaPath = QStringLiteral("file://") + mTempFile->fileName(); + } else { + mediaPath = url.toString(); + } - if ((mMediaPlayer->display() == 0) && mVideoOutput) - mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); - mMediaPlayer->setDataSource(mediaPath); - mMediaPlayer->prepareAsync(); + if (mVideoSize.isValid() && mVideoOutput) + mVideoOutput->setVideoSize(mVideoSize); + + if ((mMediaPlayer->display() == 0) && mVideoOutput) + mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); + mMediaPlayer->setDataSource(mediaPath); + mMediaPlayer->prepareAsync(); + } - if (!reloading) { + if (!mReloadingMedia) { Q_EMIT mediaChanged(mMediaContent); Q_EMIT actualMediaLocationChanged(mediaPath); } resetBufferingProgress(); + + mReloadingMedia = false; } void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput) @@ -567,7 +566,8 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) case AndroidMediaPlayer::Initialized: break; case AndroidMediaPlayer::Preparing: - setMediaStatus(QMediaPlayer::LoadingMedia); + if (!mReloadingMedia) + setMediaStatus(QMediaPlayer::LoadingMedia); break; case AndroidMediaPlayer::Prepared: setMediaStatus(QMediaPlayer::LoadedMedia); @@ -588,6 +588,7 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) } else { setMediaStatus(QMediaPlayer::BufferedMedia); } + Q_EMIT positionChanged(position()); break; case AndroidMediaPlayer::Paused: setState(QMediaPlayer::PausedState); @@ -596,27 +597,32 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) setState(QMediaPlayer::StoppedState); setMediaStatus(QMediaPlayer::UnknownMediaStatus); mMediaPlayer->release(); + Q_EMIT positionChanged(0); break; case AndroidMediaPlayer::Stopped: setState(QMediaPlayer::StoppedState); setMediaStatus(QMediaPlayer::LoadedMedia); - setPosition(0); + Q_EMIT positionChanged(0); break; case AndroidMediaPlayer::PlaybackCompleted: setState(QMediaPlayer::StoppedState); - setPosition(0); setMediaStatus(QMediaPlayer::EndOfMedia); break; case AndroidMediaPlayer::Uninitialized: - // reset some properties - resetBufferingProgress(); - mPendingPosition = -1; - mPendingSetMedia = false; - mPendingState = -1; - - setAudioAvailable(false); - setVideoAvailable(false); - setSeekable(true); + // reset some properties (unless we reload the same media) + if (!mReloadingMedia) { + resetBufferingProgress(); + mPendingPosition = -1; + mPendingSetMedia = false; + mPendingState = -1; + + Q_EMIT durationChanged(0); + Q_EMIT positionChanged(0); + + setAudioAvailable(false); + setVideoAvailable(false); + setSeekable(true); + } break; default: break; @@ -655,13 +661,13 @@ void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status if (mCurrentMediaStatus == status) return; + mCurrentMediaStatus = status; + if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia) Q_EMIT durationChanged(0); if (status == QMediaPlayer::EndOfMedia) - Q_EMIT durationChanged(duration()); - - mCurrentMediaStatus = status; + Q_EMIT positionChanged(position()); updateBufferStatus(); } diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h index 7de0c2dcf..64b88f49e 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h @@ -111,6 +111,7 @@ private: bool mPendingSetMedia; int mPendingVolume; int mPendingMute; + bool mReloadingMedia; QScopedPointer mTempFile; int mActiveStateChangeNotifiers; -- cgit v1.2.3