WMF: Recreate the MFMediaSession when loading a new media.
MFMediaSession doesn't seem to handle correctly the change of media source, causing the playback not to work afterwards. A single MFMediaSession was created and used for every loaded media, we now create a new one whenever we load a new media (releasing the old one beforehand). Task-number: QTBUG-26819 Change-Id: Id99c9dd54e161823d9580933e063f16240806529 Reviewed-by: Samuel Rødal <samuel.rodal@digia.com> Reviewed-by: Jason Barron <jason@cutehacks.com>
This commit is contained in:
committed by
The Qt Project
parent
ad83534736
commit
06b63e99e4
@@ -411,6 +411,7 @@ MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
|
||||
, m_volumeControl(0)
|
||||
, m_netsourceStatistics(0)
|
||||
, m_hCloseEvent(0)
|
||||
, m_closing(false)
|
||||
, m_pendingRate(1)
|
||||
, m_volume(1)
|
||||
, m_muted(false)
|
||||
@@ -422,10 +423,6 @@ MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
|
||||
, m_audioSampleGrabberNode(0)
|
||||
, m_videoProbeMFT(0)
|
||||
{
|
||||
m_hCloseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
m_sourceResolver = new SourceResolver();
|
||||
QObject::connect(m_sourceResolver, SIGNAL(mediaSourceReady()), this, SLOT(handleMediaSourceReady()));
|
||||
QObject::connect(m_sourceResolver, SIGNAL(error(long)), this, SLOT(handleSourceError(long)));
|
||||
QObject::connect(this, SIGNAL(sessionEvent(IMFMediaEvent *)), this, SLOT(handleSessionEvent(IMFMediaEvent *)));
|
||||
|
||||
m_pendingState = NoPending;
|
||||
@@ -438,20 +435,23 @@ MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
|
||||
m_request.prevCmd = CmdNone;
|
||||
m_request.rate = 1.0f;
|
||||
|
||||
createSession();
|
||||
PropVariantInit(&m_varStart);
|
||||
m_varStart.vt = VT_I8;
|
||||
m_varStart.uhVal.QuadPart = 0;
|
||||
|
||||
m_audioSampleGrabber = new AudioSampleGrabberCallback;
|
||||
m_videoProbeMFT = new MFTransform;
|
||||
}
|
||||
|
||||
void MFPlayerSession::close()
|
||||
{
|
||||
#ifdef DEBUG_MEDIAFOUNDATION
|
||||
qDebug() << "close";
|
||||
#endif
|
||||
|
||||
clear();
|
||||
if (!m_session)
|
||||
return;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
if (m_session) {
|
||||
m_closing = true;
|
||||
hr = m_session->Close();
|
||||
if (SUCCEEDED(hr)) {
|
||||
DWORD dwWaitResult = WaitForSingleObject(m_hCloseEvent, 100);
|
||||
@@ -459,6 +459,7 @@ void MFPlayerSession::close()
|
||||
qWarning() << "session close time out!";
|
||||
}
|
||||
}
|
||||
m_closing = false;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
@@ -475,7 +476,9 @@ void MFPlayerSession::close()
|
||||
if (m_session)
|
||||
m_session->Release();
|
||||
m_session = 0;
|
||||
CloseHandle(m_hCloseEvent);
|
||||
if (m_hCloseEvent)
|
||||
CloseHandle(m_hCloseEvent);
|
||||
m_hCloseEvent = 0;
|
||||
}
|
||||
|
||||
void MFPlayerSession::addProbe(MFAudioProbeControl *probe)
|
||||
@@ -522,6 +525,7 @@ void MFPlayerSession::load(const QMediaContent &media, QIODevice *stream)
|
||||
changeStatus(QMediaPlayer::InvalidMedia);
|
||||
emit error(QMediaPlayer::ResourceError, tr("Invalid stream source."), true);
|
||||
} else {
|
||||
createSession();
|
||||
changeStatus(QMediaPlayer::LoadingMedia);
|
||||
m_sourceResolver->load(resources, stream);
|
||||
}
|
||||
@@ -638,6 +642,7 @@ void MFPlayerSession::setupPlaybackTopology(IMFMediaSource *source, IMFPresentat
|
||||
break;
|
||||
}
|
||||
}
|
||||
outputNode->Release();
|
||||
}
|
||||
sourceNode->Release();
|
||||
}
|
||||
@@ -703,14 +708,14 @@ IMFTopologyNode* MFPlayerSession::addOutputNode(IMFStreamDescriptor *streamDesc,
|
||||
IMFActivate *activate = NULL;
|
||||
if (MFMediaType_Audio == guidMajorType) {
|
||||
mediaType = Audio;
|
||||
activate = m_playerService->audioEndpointControl()->currentActivate();
|
||||
activate = m_playerService->audioEndpointControl()->createActivate();
|
||||
} else if (MFMediaType_Video == guidMajorType) {
|
||||
mediaType = Video;
|
||||
if (m_playerService->videoRendererControl()) {
|
||||
activate = m_playerService->videoRendererControl()->currentActivate();
|
||||
activate = m_playerService->videoRendererControl()->createActivate();
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
} else if (m_playerService->videoWindowControl()) {
|
||||
activate = m_playerService->videoWindowControl()->currentActivate();
|
||||
activate = m_playerService->videoWindowControl()->createActivate();
|
||||
#endif
|
||||
} else {
|
||||
qWarning() << "no videoWindowControl or videoRendererControl, unable to add output node for video data";
|
||||
@@ -1136,6 +1141,7 @@ void MFPlayerSession::pause()
|
||||
} else {
|
||||
if (m_state.command == CmdPause)
|
||||
return;
|
||||
|
||||
if (SUCCEEDED(m_session->Pause())) {
|
||||
m_state.setCommand(CmdPause);
|
||||
m_pendingState = CmdPending;
|
||||
@@ -1163,6 +1169,14 @@ QMediaPlayer::MediaStatus MFPlayerSession::status() const
|
||||
|
||||
void MFPlayerSession::createSession()
|
||||
{
|
||||
close();
|
||||
|
||||
m_hCloseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
m_sourceResolver = new SourceResolver();
|
||||
QObject::connect(m_sourceResolver, SIGNAL(mediaSourceReady()), this, SLOT(handleMediaSourceReady()));
|
||||
QObject::connect(m_sourceResolver, SIGNAL(error(long)), this, SLOT(handleSourceError(long)));
|
||||
|
||||
Q_ASSERT(m_session == NULL);
|
||||
HRESULT hr = MFCreateMediaSession(NULL, &m_session);
|
||||
if (FAILED(hr)) {
|
||||
@@ -1176,6 +1190,10 @@ void MFPlayerSession::createSession()
|
||||
changeStatus(QMediaPlayer::UnknownMediaStatus);
|
||||
emit error(QMediaPlayer::ResourceError, tr("Unable to pull session events."), false);
|
||||
}
|
||||
|
||||
PropVariantInit(&m_varStart);
|
||||
m_varStart.vt = VT_I8;
|
||||
m_varStart.hVal.QuadPart = 0;
|
||||
}
|
||||
|
||||
qint64 MFPlayerSession::position()
|
||||
@@ -1511,7 +1529,8 @@ HRESULT MFPlayerSession::Invoke(IMFAsyncResult *pResult)
|
||||
}
|
||||
}
|
||||
|
||||
emit sessionEvent(pEvent);
|
||||
if (!m_closing)
|
||||
emit sessionEvent(pEvent);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1569,6 +1588,13 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
|
||||
case MESessionStarted:
|
||||
if (!m_scrubbing)
|
||||
updatePendingCommands(CmdStart);
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
// playback started, we can now set again the procAmpValues if they have been
|
||||
// changed previously (these are lost when loading a new media)
|
||||
if (m_playerService->videoWindowControl()) {
|
||||
m_playerService->videoWindowControl()->setProcAmpValues();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MESessionStopped:
|
||||
if (m_status != QMediaPlayer::EndOfMedia) {
|
||||
@@ -1659,9 +1685,16 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
|
||||
m_volumeControl->SetMasterVolume(m_volume);
|
||||
m_volumeControl->SetMute(m_muted);
|
||||
}
|
||||
|
||||
DWORD dwCharacteristics = 0;
|
||||
m_sourceResolver->mediaSource()->GetCharacteristics(&dwCharacteristics);
|
||||
emit seekableUpdate(MFMEDIASOURCE_CAN_SEEK & dwCharacteristics);
|
||||
|
||||
// Topology is resolved and successfuly set, this happens only after loading a new media.
|
||||
// Make sure we always start the media from the beginning
|
||||
m_varStart.vt = VT_I8;
|
||||
m_varStart.hVal.QuadPart = 0;
|
||||
|
||||
changeStatus(QMediaPlayer::LoadedMedia);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user