summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2014-03-17 18:38:10 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-18 14:48:02 +0100
commit04edeafade9058bde6d6dd58e6b1a89bace2fd50 (patch)
tree21d44555bf5bdf27691286d27a6907544d3ca88e
parent4855707ed751df93a314d875b7c1721bef738136 (diff)
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>
-rw-r--r--src/plugins/wmf/player/mfvideorenderercontrol.cpp47
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) {