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 <christian.stromme@digia.com>
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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 (mVideoSize.isValid() && mVideoOutput)
|
||||
mVideoOutput->setVideoSize(mVideoSize);
|
||||
|
||||
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;
|
||||
// reset some properties (unless we reload the same media)
|
||||
if (!mReloadingMedia) {
|
||||
resetBufferingProgress();
|
||||
mPendingPosition = -1;
|
||||
mPendingSetMedia = false;
|
||||
mPendingState = -1;
|
||||
|
||||
setAudioAvailable(false);
|
||||
setVideoAvailable(false);
|
||||
setSeekable(true);
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ private:
|
||||
bool mPendingSetMedia;
|
||||
int mPendingVolume;
|
||||
int mPendingMute;
|
||||
bool mReloadingMedia;
|
||||
QScopedPointer<QTemporaryFile> mTempFile;
|
||||
int mActiveStateChangeNotifiers;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user