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>
This commit is contained in:
committed by
The Qt Project
parent
4855707ed7
commit
04edeafade
@@ -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()));
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user