Modified: trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp (293764 => 293765)
--- trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp 2022-05-04 07:14:50 UTC (rev 293764)
+++ trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp 2022-05-04 08:31:55 UTC (rev 293765)
@@ -27,6 +27,8 @@
#include "config.h"
#include "MediaPlayerPrivateMediaFoundation.h"
+#if USE(MEDIA_FOUNDATION)
+
#include "CachedResourceLoader.h"
#include "FrameView.h"
#include "GraphicsContext.h"
@@ -33,16 +35,15 @@
#include "HWndDC.h"
#include "HostWindow.h"
#include "NotImplemented.h"
+#include <shlwapi.h>
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+
#if USE(CAIRO)
#include "CairoOperations.h"
#include <cairo.h>
#endif
-#if USE(MEDIA_FOUNDATION)
-
-#include <wtf/MainThread.h>
-#include <wtf/NeverDestroyed.h>
-
// MFSamplePresenterSampleCounter
// Data type: UINT32
//
@@ -56,6 +57,53 @@
namespace WebCore {
+class MediaPlayerPrivateMediaFoundation::AsyncCallback : public IMFAsyncCallback {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ AsyncCallback(Function<void(IMFAsyncResult*)>&& callback)
+ : m_callback(WTFMove(callback))
+ {
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(_In_ REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) override
+ {
+ static const QITAB qit[] = {
+ QITABENT(AsyncCallback, IMFAsyncCallback),
+ { }
+ };
+ return QISearch(this, qit, riid, ppvObject);
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef() override
+ {
+ return InterlockedIncrement(&m_refCount);
+ }
+
+ ULONG STDMETHODCALLTYPE Release() override
+ {
+ long refCount = InterlockedDecrement(&m_refCount);
+ if (!refCount)
+ delete this;
+ return refCount;
+ }
+
+ HRESULT STDMETHODCALLTYPE GetParameters(__RPC__out DWORD *pdwFlags, __RPC__out DWORD *pdwQueue) override
+ {
+ // Implementation of this method is optional. Returning E_NOTIMPL gives default values.
+ return E_NOTIMPL;
+ }
+
+ HRESULT STDMETHODCALLTYPE Invoke(__RPC__in_opt IMFAsyncResult *pAsyncResult) override
+ {
+ m_callback(pAsyncResult);
+ return S_OK;
+ }
+
+private:
+ ULONG m_refCount { 1 };
+ Function<void(IMFAsyncResult*)> m_callback;
+};
+
MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation(MediaPlayer* player)
: m_weakThis(this)
, m_player(player)
@@ -363,6 +411,105 @@
return DestinationColorSpace::SRGB();
}
+HRESULT beginGetEvent(WeakPtr<MediaPlayerPrivateMediaFoundation> weakThis, COMPtr<IMFMediaSession> mediaSession)
+{
+ auto callback = adoptCOM(new MediaPlayerPrivateMediaFoundation::AsyncCallback([weakThis, mediaSession](IMFAsyncResult* asyncResult) {
+ COMPtr<IMFMediaEvent> event;
+
+ // Get the event from the event queue.
+ HRESULT hr = mediaSession->EndGetEvent(asyncResult, &event);
+ if (FAILED(hr))
+ return;
+
+ // Get the event type.
+ MediaEventType mediaEventType;
+ hr = event->GetType(&mediaEventType);
+ if (FAILED(hr))
+ return;
+
+ HRESULT status;
+ hr = event->GetStatus(&status);
+ if (FAILED(hr))
+ return;
+
+ if (status == MF_E_TOPO_CODEC_NOT_FOUND) {
+ callOnMainThread([weakThis] {
+ if (!weakThis)
+ return;
+ weakThis->onNetworkStateChanged(MediaPlayer::NetworkState::FormatError);
+ });
+ return;
+ }
+
+ switch (mediaEventType) {
+ case MESessionTopologySet: {
+ callOnMainThread([weakThis] {
+ if (!weakThis)
+ return;
+ weakThis->onTopologySet();
+ });
+ break;
+ }
+
+ case MESessionStarted: {
+ callOnMainThread([weakThis] {
+ if (!weakThis)
+ return;
+ weakThis->onSessionStarted();
+ });
+ break;
+ }
+
+ case MEBufferingStarted: {
+ callOnMainThread([weakThis] {
+ if (!weakThis)
+ return;
+ weakThis->onBufferingStarted();
+ });
+ break;
+ }
+
+ case MEBufferingStopped: {
+ callOnMainThread([weakThis] {
+ if (!weakThis)
+ return;
+ weakThis->onBufferingStopped();
+ });
+ break;
+ }
+
+ case MESessionEnded: {
+ callOnMainThread([weakThis] {
+ if (!weakThis)
+ return;
+ weakThis->onSessionEnded();
+ });
+ break;
+ }
+
+ case MEMediaSample:
+ break;
+
+ case MEError:
+ callOnMainThread([weakThis] {
+ if (!weakThis)
+ return;
+ weakThis->onNetworkStateChanged(MediaPlayer::NetworkState::DecodeError);
+ });
+ return;
+ }
+
+ if (mediaEventType != MESessionClosed) {
+ // For all other events, ask the media session for the
+ // next event in the queue.
+ hr = beginGetEvent(weakThis, mediaSession.get());
+ if (FAILED(hr))
+ return;
+ }
+ }));
+ return mediaSession->BeginGetEvent(callback.get(), nullptr);
+}
+
bool MediaPlayerPrivateMediaFoundation::createSession()
{
if (FAILED(MFStartup(MF_VERSION, MFSTARTUP_FULL)))
@@ -372,8 +519,7 @@
return false;
// Get next event.
- AsyncCallback* callback = new AsyncCallback(this, true);
- HRESULT hr = m_mediaSession->BeginGetEvent(callback, nullptr);
+ HRESULT hr = beginGetEvent(m_weakThis, m_mediaSession);
ASSERT_UNUSED(hr, SUCCEEDED(hr));
return true;
@@ -417,151 +563,38 @@
COMPtr<IUnknown> cancelCookie;
Vector<wchar_t> urlSource = url.wideCharacters();
- AsyncCallback* callback = new AsyncCallback(this, false);
+ auto callback = adoptCOM(new AsyncCallback([this, weakThis = m_weakThis, sourceResolver = m_sourceResolver](IMFAsyncResult* asyncResult) {
+ MF_OBJECT_TYPE objectType;
+ COMPtr<IUnknown> source;
- if (FAILED(m_sourceResolver->BeginCreateObjectFromURL(urlSource.data(), MF_RESOLUTION_MEDIASOURCE, nullptr, &cancelCookie, callback, nullptr)))
- return false;
+ HRESULT hr = sourceResolver->EndCreateObjectFromURL(asyncResult, &objectType, &source);
+ if (FAILED(hr)) {
+ callOnMainThread([this, weakThis = weakThis, hr] {
+ if (!weakThis)
+ return;
+ onNetworkStateChanged(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE ? MediaPlayer::NetworkState::FormatError : MediaPlayer::NetworkState::NetworkError);
+ });
+ return;
+ }
- return true;
-}
-
-bool MediaPlayerPrivateMediaFoundation::endCreatedMediaSource(IMFAsyncResult* asyncResult)
-{
- MF_OBJECT_TYPE objectType;
- COMPtr<IUnknown> source;
-
- HRESULT hr = m_sourceResolver->EndCreateObjectFromURL(asyncResult, &objectType, &source);
- if (FAILED(hr)) {
- callOnMainThread([this, weakPtr = m_weakThis, hr] {
- if (!weakPtr)
- return;
- if (hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE)
- m_networkState = MediaPlayer::NetworkState::FormatError;
- else
- m_networkState = MediaPlayer::NetworkState::NetworkError;
- m_player->networkStateChanged();
- });
- return false;
- }
-
- hr = source->QueryInterface(IID_PPV_ARGS(&m_mediaSource));
- if (FAILED(hr))
- return false;
-
- hr = asyncResult->GetStatus();
- m_loadingProgress = SUCCEEDED(hr);
-
- callOnMainThread([weakPtr = m_weakThis] {
- if (!weakPtr)
+ COMPtr<IMFMediaSource> mediaSource;
+ hr = source->QueryInterface(IID_PPV_ARGS(&mediaSource));
+ if (FAILED(hr))
return;
- weakPtr->onCreatedMediaSource();
- });
- return true;
-}
+ hr = asyncResult->GetStatus();
+ bool loadingProgress = SUCCEEDED(hr);
-bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
-{
- COMPtr<IMFMediaEvent> event;
-
- if (!m_mediaSession)
- return false;
-
- // Get the event from the event queue.
- HRESULT hr = m_mediaSession->EndGetEvent(asyncResult, &event);
- if (FAILED(hr))
- return false;
-
- // Get the event type.
- MediaEventType mediaEventType;
- hr = event->GetType(&mediaEventType);
- if (FAILED(hr))
- return false;
-
- HRESULT status;
- hr = event->GetStatus(&status);
- if (FAILED(hr))
- return false;
-
- if (status == MF_E_TOPO_CODEC_NOT_FOUND) {
- callOnMainThread([this, weakPtr = m_weakThis] {
- if (!weakPtr)
+ callOnMainThread([this, weakThis, mediaSource = WTFMove(mediaSource), loadingProgress]() mutable {
+ if (!weakThis)
return;
- m_networkState = MediaPlayer::NetworkState::FormatError;
- m_player->networkStateChanged();
+ onCreatedMediaSource(WTFMove(mediaSource), loadingProgress);
});
- return false;
- }
+ }));
- switch (mediaEventType) {
- case MESessionTopologySet: {
- callOnMainThread([weakPtr = m_weakThis] {
- if (!weakPtr)
- return;
- weakPtr->onTopologySet();
- });
- break;
- }
-
- case MESessionStarted: {
- callOnMainThread([weakPtr = m_weakThis] {
- if (!weakPtr)
- return;
- weakPtr->onSessionStarted();
- });
- break;
- }
-
- case MEBufferingStarted: {
- callOnMainThread([weakPtr = m_weakThis] {
- if (!weakPtr)
- return;
- weakPtr->onBufferingStarted();
- });
- break;
- }
-
- case MEBufferingStopped: {
- callOnMainThread([weakPtr = m_weakThis] {
- if (!weakPtr)
- return;
- weakPtr->onBufferingStopped();
- });
- break;
- }
-
- case MESessionEnded: {
- callOnMainThread([weakPtr = m_weakThis] {
- if (!weakPtr)
- return;
- weakPtr->onSessionEnded();
- });
- break;
- }
-
- case MEMediaSample:
- break;
-
- case MEError:
- callOnMainThread([this, weakPtr = m_weakThis] {
- if (!weakPtr)
- return;
- m_networkState = MediaPlayer::NetworkState::DecodeError;
- m_player->networkStateChanged();
- });
+ if (FAILED(m_sourceResolver->BeginCreateObjectFromURL(urlSource.data(), MF_RESOLUTION_MEDIASOURCE, nullptr, &cancelCookie, callback.get(), nullptr)))
return false;
- }
- if (mediaEventType != MESessionClosed) {
- // For all other events, ask the media session for the
- // next event in the queue.
- AsyncCallback* callback = new AsyncCallback(this, true);
-
- hr = m_mediaSession->BeginGetEvent(callback, nullptr);
- if (FAILED(hr))
- return false;
- }
-
return true;
}
@@ -795,8 +828,11 @@
return m_videoDisplay;
}
-void MediaPlayerPrivateMediaFoundation::onCreatedMediaSource()
+void MediaPlayerPrivateMediaFoundation::onCreatedMediaSource(COMPtr<IMFMediaSource>&& mediaSource, bool loadingProgress)
{
+ m_loadingProgress = loadingProgress;
+ m_mediaSource = WTFMove(mediaSource);
+
if (!createTopologyFromSource())
return;
@@ -805,6 +841,12 @@
ASSERT_UNUSED(hr, SUCCEEDED(hr));
}
+void MediaPlayerPrivateMediaFoundation::onNetworkStateChanged(MediaPlayer::NetworkState state)
+{
+ m_networkState = state;
+ m_player->networkStateChanged();
+}
+
void MediaPlayerPrivateMediaFoundation::onTopologySet()
{
// This method is called on the main thread as a result of load() being called.
@@ -856,77 +898,6 @@
m_player->timeChanged();
}
-MediaPlayerPrivateMediaFoundation::AsyncCallback::AsyncCallback(MediaPlayerPrivateMediaFoundation* mediaPlayer, bool event)
- : m_refCount(0)
- , m_mediaPlayer(mediaPlayer)
- , m_event(event)
-{
- if (m_mediaPlayer)
- m_mediaPlayer->addListener(this);
-}
-
-MediaPlayerPrivateMediaFoundation::AsyncCallback::~AsyncCallback()
-{
- if (m_mediaPlayer)
- m_mediaPlayer->removeListener(this);
-}
-
-HRESULT MediaPlayerPrivateMediaFoundation::AsyncCallback::QueryInterface(_In_ REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
-{
- if (!ppvObject)
- return E_POINTER;
- if (!IsEqualGUID(riid, IID_IMFAsyncCallback)) {
- *ppvObject = nullptr;
- return E_NOINTERFACE;
- }
- *ppvObject = this;
- AddRef();
- return S_OK;
-}
-
-ULONG STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::AddRef()
-{
- m_refCount++;
- return m_refCount;
-}
-
-ULONG STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::Release()
-{
- m_refCount--;
- ULONG refCount = m_refCount;
- if (!refCount)
- delete this;
- return refCount;
-}
-
-HRESULT STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::GetParameters(__RPC__out DWORD *pdwFlags, __RPC__out DWORD *pdwQueue)
-{
- // Returning E_NOTIMPL gives default values.
- return E_NOTIMPL;
-}
-
-HRESULT STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::Invoke(__RPC__in_opt IMFAsyncResult *pAsyncResult)
-{
- Locker locker { m_mutex };
-
- if (!m_mediaPlayer)
- return S_OK;
-
- if (m_event)
- m_mediaPlayer->endGetEvent(pAsyncResult);
- else
- m_mediaPlayer->endCreatedMediaSource(pAsyncResult);
-
- return S_OK;
-}
-
-void MediaPlayerPrivateMediaFoundation::AsyncCallback::onMediaPlayerDeleted()
-{
- Locker locker { m_mutex };
-
- m_mediaPlayer = nullptr;
-}
-
MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::CustomVideoPresenter(MediaPlayerPrivateMediaFoundation* mediaPlayer)
: m_mediaPlayer(mediaPlayer)
{
Modified: trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h (293764 => 293765)
--- trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h 2022-05-04 07:14:50 UTC (rev 293764)
+++ trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h 2022-05-04 08:31:55 UTC (rev 293765)
@@ -102,6 +102,17 @@
DestinationColorSpace colorSpace() final;
+protected:
+ void onCreatedMediaSource(COMPtr<IMFMediaSource>&&, bool loadingProgress);
+ void onNetworkStateChanged(MediaPlayer::NetworkState);
+ void onTopologySet();
+ void onBufferingStarted();
+ void onBufferingStopped();
+ void onSessionStarted();
+ void onSessionEnded();
+
+ friend HRESULT beginGetEvent(WeakPtr<MediaPlayerPrivateMediaFoundation>, COMPtr<IMFMediaSession>);
+
private:
float maxTimeLoaded() const { return m_maxTimeLoaded; }
@@ -138,8 +149,6 @@
bool startSession();
bool endSession();
bool startCreateMediaSource(const String& url);
- bool endCreatedMediaSource(IMFAsyncResult*);
- bool endGetEvent(IMFAsyncResult*);
bool createTopologyFromSource();
bool addBranchToPartialTopology(int stream);
bool createOutputNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>&);
@@ -149,13 +158,6 @@
COMPtr<IMFVideoDisplayControl> videoDisplay();
- void onCreatedMediaSource();
- void onTopologySet();
- void onBufferingStarted();
- void onBufferingStopped();
- void onSessionStarted();
- void onSessionEnded();
-
HWND hostWindow();
void invalidateVideoArea();
@@ -174,28 +176,8 @@
virtual void onMediaPlayerDeleted() { }
};
- class AsyncCallback : public IMFAsyncCallback, public MediaPlayerListener {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- AsyncCallback(MediaPlayerPrivateMediaFoundation*, bool event);
- ~AsyncCallback();
+ class AsyncCallback;
- HRESULT STDMETHODCALLTYPE QueryInterface(_In_ REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) override;
- ULONG STDMETHODCALLTYPE AddRef() override;
- ULONG STDMETHODCALLTYPE Release() override;
-
- HRESULT STDMETHODCALLTYPE GetParameters(__RPC__out DWORD *pdwFlags, __RPC__out DWORD *pdwQueue) override;
- HRESULT STDMETHODCALLTYPE Invoke(__RPC__in_opt IMFAsyncResult *pAsyncResult) override;
-
- void onMediaPlayerDeleted() override;
-
- private:
- ULONG m_refCount;
- MediaPlayerPrivateMediaFoundation* m_mediaPlayer;
- bool m_event;
- Lock m_mutex;
- };
-
typedef Deque<COMPtr<IMFSample>> VideoSampleList;
class VideoSamplePool {