Fixed some crash with WMF backend
authorLing Hu <ling.hu@nokia.com>
Thu, 21 Jun 2012 06:18:05 +0000 (16:18 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 25 Jun 2012 04:39:08 +0000 (06:39 +0200)
Change-Id: I721ba049e2ecafff53ee70d5b930fb52c15fbe09
Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
src/plugins/wmf/player/mfplayerservice.cpp
src/plugins/wmf/player/mfplayerservice.h
src/plugins/wmf/player/mfplayersession.cpp
src/plugins/wmf/player/mfplayersession.h
src/plugins/wmf/player/mfvideorenderercontrol.cpp
src/plugins/wmf/player/sourceresolver.cpp

index c5f24cc..c4c3fbd 100644 (file)
@@ -52,6 +52,7 @@
 #include "mfplayerservice.h"
 #include "mfplayersession.h"
 #include "mfmetadatacontrol.h"
+int MFPlayerService::s_refCount = 0;
 
 MFPlayerService::MFPlayerService(QObject *parent)
     : QMediaService(parent)
@@ -61,17 +62,19 @@ MFPlayerService::MFPlayerService(QObject *parent)
 #endif
     , m_videoRendererControl(0)
 {
-    CoInitialize(NULL);
-    MFStartup(MF_VERSION);
+    s_refCount++;
+    if (s_refCount == 1) {
+        CoInitialize(NULL);
+        MFStartup(MF_VERSION);
+    }
+    m_audioEndpointControl = new MFAudioEndpointControl(this);
     m_session = new MFPlayerSession(this);
     m_player = new MFPlayerControl(m_session);
-    m_audioEndpointControl = new MFAudioEndpointControl(this);
     m_metaDataControl = new MFMetaDataControl(this);
 }
 
 MFPlayerService::~MFPlayerService()
 {
-
 #ifndef Q_WS_SIMULATOR
     if (m_videoWindowControl)
         delete m_videoWindowControl;
@@ -80,10 +83,14 @@ MFPlayerService::~MFPlayerService()
     if (m_videoRendererControl)
         delete m_videoRendererControl;
 
-    delete m_session;
+    m_session->close();
+    m_session->Release();
 
-    MFShutdown();
-    CoUninitialize();
+    s_refCount--;
+    if (s_refCount == 0) {
+        MFShutdown();
+        CoUninitialize();
+    }
 }
 
 QMediaControl* MFPlayerService::requestControl(const char *name)
index 587e592..65f3b34 100644 (file)
@@ -91,6 +91,7 @@ private:
 #endif
     MFPlayerControl        *m_player;
     MFMetaDataControl      *m_metaDataControl;
+    static int                s_refCount;
 };
 
 #endif
index 3b96b83..c8c99e2 100644 (file)
@@ -399,8 +399,9 @@ namespace
 }
 
 
-MFPlayerSession::MFPlayerSession(QObject *parent)
-    : QObject(parent)
+MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
+    : m_playerService(playerService)
+    , m_cRef(1)
     , m_session(0)
     , m_presentationClock(0)
     , m_rateControl(0)
@@ -438,9 +439,8 @@ MFPlayerSession::MFPlayerSession(QObject *parent)
     m_varStart.uhVal.QuadPart = 0;
 }
 
-MFPlayerSession::~MFPlayerSession()
+void MFPlayerSession::close()
 {
-    m_sourceResolver->Release();
     clear();
     HRESULT hr = S_OK;
     if (m_session) {
@@ -454,17 +454,22 @@ MFPlayerSession::~MFPlayerSession()
     }
 
     if (SUCCEEDED(hr)) {
-        m_sourceResolver->shutdown();
         if (m_session)
             m_session->Shutdown();
+        m_sourceResolver->shutdown();
     }
+    m_sourceResolver->Release();
 
     if (m_session)
         m_session->Release();
-
+    m_session = 0;
     CloseHandle(m_hCloseEvent);
 }
 
+MFPlayerSession::~MFPlayerSession()
+{
+}
+
 
 void MFPlayerSession::load(const QMediaContent &media, QIODevice *stream)
 {
@@ -525,7 +530,7 @@ void MFPlayerSession::handleMediaSourceReady()
     hr = mediaSource->CreatePresentationDescriptor(&sourcePD);
     if (SUCCEEDED(hr)) {
         m_duration = 0;
-        static_cast<MFPlayerService*>(this->parent())->metaDataControl()->updateSource(sourcePD, mediaSource);
+        m_playerService->metaDataControl()->updateSource(sourcePD, mediaSource);
         sourcePD->GetUINT64(MF_PD_DURATION, &m_duration);
         //convert from 100 nanosecond to milisecond
         emit durationUpdate(qint64(m_duration / 10000));
@@ -645,17 +650,16 @@ IMFTopologyNode* MFPlayerSession::addOutputNode(IMFStreamDescriptor *streamDesc,
         hr = handler->GetMajorType(&guidMajorType);
         if (SUCCEEDED(hr)) {
             IMFActivate *activate = NULL;
-            MFPlayerService *service = static_cast<MFPlayerService*>(this->parent());
             if (MFMediaType_Audio == guidMajorType) {
                 mediaType = Audio;
-                activate = service->audioEndpointControl()->currentActivate();
+                activate = m_playerService->audioEndpointControl()->currentActivate();
             } else if (MFMediaType_Video == guidMajorType) {
                 mediaType = Video;
-                if (service->videoRendererControl()) {
-                    activate = service->videoRendererControl()->currentActivate();
+                if (m_playerService->videoRendererControl()) {
+                    activate = m_playerService->videoRendererControl()->currentActivate();
 #ifndef Q_WS_SIMULATOR
-                } else if (service->videoWindowControl()) {
-                    activate = service->videoWindowControl()->currentActivate();
+                } else if (m_playerService->videoWindowControl()) {
+                    activate = m_playerService->videoWindowControl()->currentActivate();
 #endif
                 } else {
                     qWarning() << "no videoWindowControl or videoRendererControl, unable to add output node for video data";
@@ -1085,12 +1089,15 @@ HRESULT MFPlayerSession::QueryInterface(REFIID riid, void** ppvObject)
 
 ULONG MFPlayerSession::AddRef(void)
 {
-    return 1;
+    return InterlockedIncrement(&m_cRef);
 }
 
 ULONG MFPlayerSession::Release(void)
 {
-    return 1;
+    LONG cRef = InterlockedDecrement(&m_cRef);
+    if (cRef == 0)
+        this->deleteLater();
+    return cRef;
 }
 
 HRESULT MFPlayerSession::Invoke(IMFAsyncResult *pResult)
@@ -1114,6 +1121,7 @@ HRESULT MFPlayerSession::Invoke(IMFAsyncResult *pResult)
 
     if (meType == MESessionClosed) {
         SetEvent(m_hCloseEvent);
+        pEvent->Release();
         return S_OK;
     } else {
         hr = m_session->BeginGetEvent(this, m_session);
index 911230e..70ce925 100644 (file)
@@ -69,13 +69,14 @@ class MFAudioEndpointControl;
 class MFVideoRendererControl;
 class MFPlayerControl;
 class MFMetaDataControl;
+class MFPlayerService;
 
 class MFPlayerSession : public QObject, public IMFAsyncCallback
 {
     Q_OBJECT
     friend class SourceResolver;
 public:
-    MFPlayerSession(QObject *parent = 0);
+    MFPlayerSession(MFPlayerService *playerService = 0);
     ~MFPlayerSession();
 
     STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObject);
@@ -112,6 +113,8 @@ public:
 
     void changeStatus(QMediaPlayer::MediaStatus newStatus);
 
+    void close();
+
 Q_SIGNALS:
     void error(QMediaPlayer::Error error, QString errorString, bool isFatal);
     void sessionEvent(IMFMediaEvent  *sessionEvent);
@@ -132,6 +135,8 @@ private Q_SLOTS:
     void handleSourceError(long hr);
 
 private:
+    long m_cRef;
+    MFPlayerService *m_playerService;
     IMFMediaSession *m_session;
     IMFPresentationClock *m_presentationClock;
     IMFRateControl *m_rateControl;
index 74ac715..56228e9 100644 (file)
@@ -836,6 +836,8 @@ namespace
             QMutexLocker locker(&m_mutex);
             m_pixelFormats.clear();
             clearMediaTypes();
+            if (!m_surface)
+                return;
             QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
             foreach (QVideoFrame::PixelFormat format, formats) {
                 IMFMediaType *mediaType;
index fe304af..8db973a 100644 (file)
@@ -66,6 +66,11 @@ SourceResolver::SourceResolver(QObject *parent)
 SourceResolver::~SourceResolver()
 {
     shutdown();
+    if (m_mediaSource) {
+        m_mediaSource->Release();
+        m_mediaSource = NULL;
+    }
+
     if (m_cancelCookie)
         m_cancelCookie->Release();
     if (m_sourceResolver)
@@ -249,8 +254,6 @@ void SourceResolver::shutdown()
 {
     if (m_mediaSource) {
         m_mediaSource->Shutdown();
-        m_mediaSource->Release();
-        m_mediaSource = NULL;
     }
 
     if (m_stream) {