diff options
Diffstat (limited to 'src/plugins/directshow/player')
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(); |