diff options
author | Yoann Lopes <yoann.lopes@digia.com> | 2014-03-17 18:38:10 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-18 14:48:02 +0100 |
commit | 04edeafade9058bde6d6dd58e6b1a89bace2fd50 (patch) | |
tree | 21d44555bf5bdf27691286d27a6907544d3ca88e /src/plugins | |
parent | 4855707ed751df93a314d875b7c1721bef738136 (diff) | |
download | qtmultimedia-04edeafade9058bde6d6dd58e6b1a89bace2fd50.tar.gz |
WMF: fix some issues with our custom video sink.
- When scrubbing, request frames only one at a time.
- Discard frames when too late or too much in advance
- Fix integer overflow causing undefined behavior
[ChangeLog][QtMultimedia][Windows] Fixed video playback playing at
twice the normal rate after reaching 3:34.
[ChangeLog][QtMultimedia][Windows] Fixed video playback that could
freeze after seeking to a different position.
Task-number: QTBUG-31800
Change-Id: Ie620c684c58ee790537969ffc40f01610b6745ea
Reviewed-by: Christian Stromme <christian.stromme@digia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/wmf/player/mfvideorenderercontrol.cpp | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index a28dcca25..1705b2a48 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -257,6 +257,7 @@ namespace , m_bufferStartTime(-1) , m_bufferDuration(-1) , m_presentationClock(0) + , m_sampleRequested(false) , m_currentMediaType(0) , m_prerolling(false) , m_prerollTargetTime(0) @@ -854,6 +855,15 @@ namespace schedulePresentation(true); } + void clearScheduledFrame() + { + QMutexLocker locker(&m_mutex); + if (m_scheduledBuffer) { + m_scheduledBuffer->Release(); + m_scheduledBuffer = NULL; + } + } + enum { StartSurface = QEvent::User, @@ -871,7 +881,7 @@ namespace { } - int targetTime() + MFTIME targetTime() { return m_time; } @@ -1317,6 +1327,8 @@ namespace HRESULT processSampleData(IMFSample *pSample) { + m_sampleRequested = false; + LONGLONG time, duration = -1; HRESULT hr = pSample->GetSampleTime(&time); if (SUCCEEDED(hr)) @@ -1406,13 +1418,16 @@ namespace break; } } - if (requestSample && m_bufferCache.size() < BUFFER_CACHE_SIZE) + if (requestSample && !m_sampleRequested && m_bufferCache.size() < BUFFER_CACHE_SIZE) { + m_sampleRequested = true; queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); + } } IMFMediaBuffer *m_scheduledBuffer; MFTIME m_bufferStartTime; MFTIME m_bufferDuration; IMFPresentationClock *m_presentationClock; + bool m_sampleRequested; float m_rate; }; @@ -1480,6 +1495,14 @@ namespace m_stream->present(); } + void clearScheduledFrame() + { + QMutexLocker locker(&m_mutex); + if (m_shutdown) + return; + m_stream->clearScheduledFrame(); + } + MFTIME getTime() { QMutexLocker locker(&m_mutex); @@ -2066,6 +2089,14 @@ namespace m_sink->present(); } + void clearScheduledFrame() + { + QMutexLocker locker(&m_mutex); + if (!m_sink) + return; + m_sink->clearScheduledFrame(); + } + MFTIME getTime() { if (m_sink) @@ -2170,10 +2201,16 @@ void MFVideoRendererControl::customEvent(QEvent *event) MFTIME targetTime = static_cast<MediaStream::PresentEvent*>(event)->targetTime(); MFTIME currentTime = static_cast<VideoRendererActivate*>(m_currentActivate)->getTime(); float playRate = static_cast<VideoRendererActivate*>(m_currentActivate)->getPlayRate(); - if (playRate > 0.0001f && targetTime > currentTime) - QTimer::singleShot(int((float)((targetTime - currentTime) / 10000) / playRate), this, SLOT(present())); - else + if (!qFuzzyIsNull(playRate)) { + // If the scheduled frame is too late or too much in advance, skip it + const int diff = (targetTime - currentTime) / 10000; + if (diff < 0 || diff > 500) + static_cast<VideoRendererActivate*>(m_currentActivate)->clearScheduledFrame(); + else + QTimer::singleShot(diff / playRate, this, SLOT(present())); + } else { present(); + } return; } if (event->type() >= MediaStream::StartSurface) { |