From: Yoann Lopes Date: Mon, 17 Mar 2014 17:38:10 +0000 (+0100) Subject: WMF: fix some issues with our custom video sink. X-Git-Tag: upstream/5.2.95+rc1~3^2~21 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=04edeafade9058bde6d6dd58e6b1a89bace2fd50;p=platform%2Fupstream%2Fqtmultimedia.git 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 --- diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index a28dcca..1705b2a 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(event)->targetTime(); MFTIME currentTime = static_cast(m_currentActivate)->getTime(); float playRate = static_cast(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(m_currentActivate)->clearScheduledFrame(); + else + QTimer::singleShot(diff / playRate, this, SLOT(present())); + } else { present(); + } return; } if (event->type() >= MediaStream::StartSurface) {