summaryrefslogtreecommitdiffstats
path: root/src/plugins/directshow/player
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/directshow/player')
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.cpp100
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.h6
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp29
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.h1
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.cpp30
5 files changed, 100 insertions, 66 deletions
diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp
index a5fed4b95..e988cbdd3 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.cpp
+++ b/src/plugins/directshow/player/directshowplayercontrol.cpp
@@ -73,7 +73,8 @@ DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *servic
, m_status(QMediaPlayer::NoMedia)
, m_error(QMediaPlayer::NoError)
, m_streamTypes(0)
- , m_muteVolume(-1)
+ , m_volume(100)
+ , m_muted(false)
, m_position(0)
, m_pendingPosition(-1)
, m_duration(0)
@@ -113,6 +114,11 @@ qint64 DirectShowPlayerControl::position() const
void DirectShowPlayerControl::setPosition(qint64 position)
{
+ if (m_status == QMediaPlayer::EndOfMedia) {
+ m_status = QMediaPlayer::LoadedMedia;
+ emit mediaStatusChanged(m_status);
+ }
+
if (m_state == QMediaPlayer::StoppedState && m_pendingPosition != position) {
m_pendingPosition = position;
emit positionChanged(m_pendingPosition);
@@ -125,63 +131,47 @@ void DirectShowPlayerControl::setPosition(qint64 position)
int DirectShowPlayerControl::volume() const
{
- if (m_muteVolume >= 0) {
- return m_muteVolume;
- } else if (m_audio) {
- long dB = 0;
-
- m_audio->get_Volume(&dB);
-
- return decibelsToVolume(dB);
- } else {
- return 0;
- }
+ return m_volume;
}
void DirectShowPlayerControl::setVolume(int volume)
{
int boundedVolume = qBound(0, volume, 100);
- if (m_muteVolume >= 0) {
- m_muteVolume = boundedVolume;
+ if (m_volume == boundedVolume)
+ return;
+
+ m_volume = boundedVolume;
- emit volumeChanged(m_muteVolume);
- } else if (m_audio) {
- m_audio->put_Volume(volumeToDecibels(volume));
+ if (!m_muted)
+ setVolumeHelper(m_volume);
- emit volumeChanged(boundedVolume);
- }
+ emit volumeChanged(m_volume);
}
bool DirectShowPlayerControl::isMuted() const
{
- return m_muteVolume >= 0;
+ return m_muted;
}
void DirectShowPlayerControl::setMuted(bool muted)
{
- if (muted && m_muteVolume < 0) {
- if (m_audio) {
- long dB = 0;
+ if (m_muted == muted)
+ return;
- m_audio->get_Volume(&dB);
+ m_muted = muted;
- m_muteVolume = decibelsToVolume(dB);
+ setVolumeHelper(m_muted ? 0 : m_volume);
- m_audio->put_Volume(-10000);
- } else {
- m_muteVolume = 0;
- }
+ emit mutedChanged(m_muted);
+}
- emit mutedChanged(muted);
- } else if (!muted && m_muteVolume >= 0) {
- if (m_audio) {
- m_audio->put_Volume(volumeToDecibels(m_muteVolume));
- }
- m_muteVolume = -1;
+void DirectShowPlayerControl::setVolumeHelper(int volume)
+{
+ if (!m_audio)
+ return;
- emit mutedChanged(muted);
- }
+ m_audio->put_Volume(volumeToDecibels(volume));
}
int DirectShowPlayerControl::bufferStatus() const
@@ -235,6 +225,8 @@ const QIODevice *DirectShowPlayerControl::mediaStream() const
void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
{
+ m_pendingPosition = -1;
+
m_media = media;
m_stream = stream;
@@ -248,30 +240,35 @@ void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *st
void DirectShowPlayerControl::play()
{
- if (m_status == QMediaPlayer::NoMedia)
- 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);
+ playOrPause(QMediaPlayer::PlayingState);
}
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;
if (m_status == QMediaPlayer::InvalidMedia) {
setMedia(m_media, m_stream);
if (m_error != QMediaPlayer::NoError)
return;
}
- m_service->pause();
- emit stateChanged(m_state = QMediaPlayer::PausedState);
+
+ m_state = state;
+
+ if (m_pendingPosition != -1)
+ setPosition(m_pendingPosition);
+
+ if (state == QMediaPlayer::PausedState)
+ m_service->pause();
+ else
+ m_service->play();
+
+ emit stateChanged(m_state);
}
void DirectShowPlayerControl::stop()
@@ -389,6 +386,7 @@ void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
m_audio->Release();
m_audio = com_cast<IBasicAudio>(filter, IID_IBasicAudio);
+ setVolumeHelper(m_muted ? 0 : m_volume);
}
void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString)
diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h
index a42d3c7b1..ab842f511 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.h
+++ b/src/plugins/directshow/player/directshowplayercontrol.h
@@ -114,8 +114,11 @@ private:
PropertiesChanged = QEvent::User
};
+ void playOrPause(QMediaPlayer::State state);
+
void scheduleUpdate(int properties);
void emitPropertyChanges();
+ void setVolumeHelper(int volume);
DirectShowPlayerService *m_service;
IBasicAudio *m_audio;
@@ -125,7 +128,8 @@ private:
QMediaPlayer::MediaStatus m_status;
QMediaPlayer::Error m_error;
int m_streamTypes;
- int m_muteVolume;
+ int m_volume;
+ bool m_muted;
qint64 m_position;
qint64 m_pendingPosition;
qint64 m_duration;
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
index 67aea6e9a..b73fa5c4c 100644
--- a/src/plugins/directshow/player/directshowplayerservice.cpp
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -98,6 +98,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
, m_videoOutput(0)
, m_rate(1.0)
, m_position(0)
+ , m_seekPosition(-1)
, m_duration(0)
, m_buffering(false)
, m_seekable(false)
@@ -217,6 +218,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream
m_error = QMediaPlayer::NoError;
m_errorString = QString();
m_position = 0;
+ m_seekPosition = -1;
m_duration = 0;
m_streamTypes = 0;
m_executedTasks = 0;
@@ -665,8 +667,10 @@ void DirectShowPlayerService::play()
if (m_executedTasks & Render) {
if (m_executedTasks & Stop) {
m_atEnd = false;
- m_position = 0;
- m_pendingTasks |= Seek;
+ if (m_seekPosition == -1) {
+ m_seekPosition = 0;
+ m_pendingTasks |= Seek;
+ }
m_executedTasks ^= Stop;
}
@@ -709,8 +713,10 @@ void DirectShowPlayerService::pause()
if (m_executedTasks & Render) {
if (m_executedTasks & Stop) {
m_atEnd = false;
- m_position = 0;
- m_pendingTasks |= Seek;
+ if (m_seekPosition == -1) {
+ m_seekPosition = 0;
+ m_pendingTasks |= Seek;
+ }
m_executedTasks ^= Stop;
}
@@ -780,7 +786,7 @@ void DirectShowPlayerService::doStop(QMutexLocker *locker)
control->Release();
}
- m_position = 0;
+ m_seekPosition = 0;
m_pendingTasks |= Seek;
m_executedTasks &= ~(Play | Pause);
@@ -884,7 +890,7 @@ void DirectShowPlayerService::seek(qint64 position)
{
QMutexLocker locker(&m_mutex);
- m_position = position;
+ m_seekPosition = position;
m_pendingTasks |= Seek;
@@ -894,8 +900,11 @@ void DirectShowPlayerService::seek(qint64 position)
void DirectShowPlayerService::doSeek(QMutexLocker *locker)
{
+ if (m_seekPosition == -1)
+ return;
+
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
// possibility of a deadlock when flushing the VideoSurfaceFilter.
@@ -919,11 +928,11 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker)
m_position = currentPosition / qt_directShowTimeScale;
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
diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h
index c9d10351e..f4da103dc 100644
--- a/src/plugins/directshow/player/directshowplayerservice.h
+++ b/src/plugins/directshow/player/directshowplayerservice.h
@@ -194,6 +194,7 @@ private:
int m_streamTypes;
qreal m_rate;
qint64 m_position;
+ qint64 m_seekPosition;
qint64 m_duration;
bool m_buffering;
bool m_seekable;
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp
index 2f52e33de..901d2e908 100644
--- a/src/plugins/directshow/player/videosurfacefilter.cpp
+++ b/src/plugins/directshow/player/videosurfacefilter.cpp
@@ -147,6 +147,14 @@ HRESULT VideoSurfaceFilter::Stop()
m_sampleScheduler.stop();
+ if (thread() == QThread::currentThread()) {
+ flush();
+ } else {
+ QMutexLocker locker(&m_mutex);
+ m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
+ m_wait.wait(&m_mutex);
+ }
+
return S_OK;
}
@@ -606,10 +614,24 @@ void VideoSurfaceFilter::sampleReady()
IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
if (sample) {
- m_surface->present(QVideoFrame(
- new MediaSampleVideoBuffer(sample, m_bytesPerLine),
- m_surfaceFormat.frameSize(),
- m_surfaceFormat.pixelFormat()));
+ QVideoFrame frame(new MediaSampleVideoBuffer(sample, m_bytesPerLine),
+ m_surfaceFormat.frameSize(),
+ m_surfaceFormat.pixelFormat());
+
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ frame.setStartTime(position * 0.1);
+
+ REFERENCE_TIME startTime = -1;
+ REFERENCE_TIME endTime = -1;
+ if (sample->GetTime(&startTime, &endTime) == S_OK)
+ frame.setEndTime(frame.startTime() + (endTime - startTime) * 0.1);
+ }
+
+ m_surface->present(frame);
sample->Release();