DirectShow: fix media player seeking.
Correctly handle seek requests happening when the media is not playing. Change-Id: I82c508dae41792b75a26e86512da66a4871f6352 Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
This commit is contained in:
@@ -225,6 +225,8 @@ const QIODevice *DirectShowPlayerControl::mediaStream() const
|
|||||||
|
|
||||||
void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
|
void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
|
||||||
{
|
{
|
||||||
|
m_pendingPosition = -1;
|
||||||
|
|
||||||
m_media = media;
|
m_media = media;
|
||||||
m_stream = stream;
|
m_stream = stream;
|
||||||
|
|
||||||
@@ -238,30 +240,35 @@ void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *st
|
|||||||
|
|
||||||
void DirectShowPlayerControl::play()
|
void DirectShowPlayerControl::play()
|
||||||
{
|
{
|
||||||
if (m_status == QMediaPlayer::NoMedia)
|
playOrPause(QMediaPlayer::PlayingState);
|
||||||
return;
|
|
||||||
if (m_status == QMediaPlayer::InvalidMedia) {
|
|
||||||
setMedia(m_media, m_stream);
|
|
||||||
if (m_error != QMediaPlayer::NoError)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_service->play();
|
|
||||||
if (m_pendingPosition != -1)
|
|
||||||
setPosition(m_pendingPosition);
|
|
||||||
emit stateChanged(m_state = QMediaPlayer::PlayingState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectShowPlayerControl::pause()
|
void DirectShowPlayerControl::pause()
|
||||||
{
|
{
|
||||||
if (m_status == QMediaPlayer::NoMedia)
|
playOrPause(QMediaPlayer::PausedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectShowPlayerControl::playOrPause(QMediaPlayer::State state)
|
||||||
|
{
|
||||||
|
if (m_status == QMediaPlayer::NoMedia || state == QMediaPlayer::StoppedState)
|
||||||
return;
|
return;
|
||||||
if (m_status == QMediaPlayer::InvalidMedia) {
|
if (m_status == QMediaPlayer::InvalidMedia) {
|
||||||
setMedia(m_media, m_stream);
|
setMedia(m_media, m_stream);
|
||||||
if (m_error != QMediaPlayer::NoError)
|
if (m_error != QMediaPlayer::NoError)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_state = state;
|
||||||
|
|
||||||
|
if (m_pendingPosition != -1)
|
||||||
|
setPosition(m_pendingPosition);
|
||||||
|
|
||||||
|
if (state == QMediaPlayer::PausedState)
|
||||||
m_service->pause();
|
m_service->pause();
|
||||||
emit stateChanged(m_state = QMediaPlayer::PausedState);
|
else
|
||||||
|
m_service->play();
|
||||||
|
|
||||||
|
emit stateChanged(m_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectShowPlayerControl::stop()
|
void DirectShowPlayerControl::stop()
|
||||||
|
|||||||
@@ -114,6 +114,8 @@ private:
|
|||||||
PropertiesChanged = QEvent::User
|
PropertiesChanged = QEvent::User
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void playOrPause(QMediaPlayer::State state);
|
||||||
|
|
||||||
void scheduleUpdate(int properties);
|
void scheduleUpdate(int properties);
|
||||||
void emitPropertyChanges();
|
void emitPropertyChanges();
|
||||||
void setVolumeHelper(int volume);
|
void setVolumeHelper(int volume);
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
|
|||||||
, m_videoOutput(0)
|
, m_videoOutput(0)
|
||||||
, m_rate(1.0)
|
, m_rate(1.0)
|
||||||
, m_position(0)
|
, m_position(0)
|
||||||
|
, m_seekPosition(-1)
|
||||||
, m_duration(0)
|
, m_duration(0)
|
||||||
, m_buffering(false)
|
, m_buffering(false)
|
||||||
, m_seekable(false)
|
, m_seekable(false)
|
||||||
@@ -217,6 +218,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream
|
|||||||
m_error = QMediaPlayer::NoError;
|
m_error = QMediaPlayer::NoError;
|
||||||
m_errorString = QString();
|
m_errorString = QString();
|
||||||
m_position = 0;
|
m_position = 0;
|
||||||
|
m_seekPosition = -1;
|
||||||
m_duration = 0;
|
m_duration = 0;
|
||||||
m_streamTypes = 0;
|
m_streamTypes = 0;
|
||||||
m_executedTasks = 0;
|
m_executedTasks = 0;
|
||||||
@@ -665,8 +667,10 @@ void DirectShowPlayerService::play()
|
|||||||
if (m_executedTasks & Render) {
|
if (m_executedTasks & Render) {
|
||||||
if (m_executedTasks & Stop) {
|
if (m_executedTasks & Stop) {
|
||||||
m_atEnd = false;
|
m_atEnd = false;
|
||||||
m_position = 0;
|
if (m_seekPosition == -1) {
|
||||||
|
m_seekPosition = 0;
|
||||||
m_pendingTasks |= Seek;
|
m_pendingTasks |= Seek;
|
||||||
|
}
|
||||||
m_executedTasks ^= Stop;
|
m_executedTasks ^= Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,8 +713,10 @@ void DirectShowPlayerService::pause()
|
|||||||
if (m_executedTasks & Render) {
|
if (m_executedTasks & Render) {
|
||||||
if (m_executedTasks & Stop) {
|
if (m_executedTasks & Stop) {
|
||||||
m_atEnd = false;
|
m_atEnd = false;
|
||||||
m_position = 0;
|
if (m_seekPosition == -1) {
|
||||||
|
m_seekPosition = 0;
|
||||||
m_pendingTasks |= Seek;
|
m_pendingTasks |= Seek;
|
||||||
|
}
|
||||||
m_executedTasks ^= Stop;
|
m_executedTasks ^= Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,7 +786,7 @@ void DirectShowPlayerService::doStop(QMutexLocker *locker)
|
|||||||
control->Release();
|
control->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_position = 0;
|
m_seekPosition = 0;
|
||||||
m_pendingTasks |= Seek;
|
m_pendingTasks |= Seek;
|
||||||
|
|
||||||
m_executedTasks &= ~(Play | Pause);
|
m_executedTasks &= ~(Play | Pause);
|
||||||
@@ -884,7 +890,7 @@ void DirectShowPlayerService::seek(qint64 position)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
m_position = position;
|
m_seekPosition = position;
|
||||||
|
|
||||||
m_pendingTasks |= Seek;
|
m_pendingTasks |= Seek;
|
||||||
|
|
||||||
@@ -894,8 +900,11 @@ void DirectShowPlayerService::seek(qint64 position)
|
|||||||
|
|
||||||
void DirectShowPlayerService::doSeek(QMutexLocker *locker)
|
void DirectShowPlayerService::doSeek(QMutexLocker *locker)
|
||||||
{
|
{
|
||||||
|
if (m_seekPosition == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
|
if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
|
||||||
LONGLONG seekPosition = LONGLONG(m_position) * qt_directShowTimeScale;
|
LONGLONG seekPosition = LONGLONG(m_seekPosition) * qt_directShowTimeScale;
|
||||||
|
|
||||||
// Cache current values as we can't query IMediaSeeking during a seek due to the
|
// Cache current values as we can't query IMediaSeeking during a seek due to the
|
||||||
// possibility of a deadlock when flushing the VideoSurfaceFilter.
|
// possibility of a deadlock when flushing the VideoSurfaceFilter.
|
||||||
@@ -919,13 +928,13 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker)
|
|||||||
m_position = currentPosition / qt_directShowTimeScale;
|
m_position = currentPosition / qt_directShowTimeScale;
|
||||||
|
|
||||||
seeking->Release();
|
seeking->Release();
|
||||||
} else {
|
|
||||||
m_position = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
|
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_seekPosition = -1;
|
||||||
|
}
|
||||||
|
|
||||||
int DirectShowPlayerService::bufferStatus() const
|
int DirectShowPlayerService::bufferStatus() const
|
||||||
{
|
{
|
||||||
#ifndef QT_NO_WMSDK
|
#ifndef QT_NO_WMSDK
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ private:
|
|||||||
int m_streamTypes;
|
int m_streamTypes;
|
||||||
qreal m_rate;
|
qreal m_rate;
|
||||||
qint64 m_position;
|
qint64 m_position;
|
||||||
|
qint64 m_seekPosition;
|
||||||
qint64 m_duration;
|
qint64 m_duration;
|
||||||
bool m_buffering;
|
bool m_buffering;
|
||||||
bool m_seekable;
|
bool m_seekable;
|
||||||
|
|||||||
Reference in New Issue
Block a user