Skip to content
Permalink
Browse files
[WinCairo][MediaFoundation] Videos are always autoplaying.
https://bugs.webkit.org/show_bug.cgi?id=156284

Reviewed by Alex Christensen.

Videos are autoplaying because the MediaFoundation implementation always starts playback
after the load method has been called. When the load method has been called, we should
only start buffering data, not automatically start the playback. This has been fixed by
implementing the prepareToPlay method, and calling this instead of the play method.

* platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp:
(WebCore::MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation):
(WebCore::MediaPlayerPrivateMediaFoundation::load):
(WebCore::MediaPlayerPrivateMediaFoundation::prepareToPlay):
(WebCore::MediaPlayerPrivateMediaFoundation::play):
(WebCore::MediaPlayerPrivateMediaFoundation::networkState):
(WebCore::MediaPlayerPrivateMediaFoundation::startSession):
(WebCore::MediaPlayerPrivateMediaFoundation::endGetEvent):
(WebCore::MediaPlayerPrivateMediaFoundation::updateReadyState):
(WebCore::MediaPlayerPrivateMediaFoundation::onTopologySet):
(WebCore::MediaPlayerPrivateMediaFoundation::onBufferingStarted):
(WebCore::MediaPlayerPrivateMediaFoundation::onBufferingStopped):
(WebCore::MediaPlayerPrivateMediaFoundation::onSessionEnded):
(WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::updateDestRect):
* platform/graphics/win/MediaPlayerPrivateMediaFoundation.h:


Canonical link: https://commits.webkit.org/174387@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@199114 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
peavo committed Apr 6, 2016
1 parent c46ce11 commit 7ac0ac264699c1bc7c05406c5ce3153a28784dd1
@@ -1,3 +1,31 @@
2016-04-06 Per Arne Vollan <peavo@outlook.com>

[WinCairo][MediaFoundation] Videos are always autoplaying.
https://bugs.webkit.org/show_bug.cgi?id=156284

Reviewed by Alex Christensen.

Videos are autoplaying because the MediaFoundation implementation always starts playback
after the load method has been called. When the load method has been called, we should
only start buffering data, not automatically start the playback. This has been fixed by
implementing the prepareToPlay method, and calling this instead of the play method.

* platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp:
(WebCore::MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation):
(WebCore::MediaPlayerPrivateMediaFoundation::load):
(WebCore::MediaPlayerPrivateMediaFoundation::prepareToPlay):
(WebCore::MediaPlayerPrivateMediaFoundation::play):
(WebCore::MediaPlayerPrivateMediaFoundation::networkState):
(WebCore::MediaPlayerPrivateMediaFoundation::startSession):
(WebCore::MediaPlayerPrivateMediaFoundation::endGetEvent):
(WebCore::MediaPlayerPrivateMediaFoundation::updateReadyState):
(WebCore::MediaPlayerPrivateMediaFoundation::onTopologySet):
(WebCore::MediaPlayerPrivateMediaFoundation::onBufferingStarted):
(WebCore::MediaPlayerPrivateMediaFoundation::onBufferingStopped):
(WebCore::MediaPlayerPrivateMediaFoundation::onSessionEnded):
(WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::updateDestRect):
* platform/graphics/win/MediaPlayerPrivateMediaFoundation.h:

2016-04-06 Zalan Bujtas <zalan@apple.com>

Add ASSERT_WITH_SECURITY_IMPLICATION when a float box is referenced by multiple RootInlineBoxes.
@@ -88,10 +88,12 @@ MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation(MediaPlayer
: m_player(player)
, m_visible(false)
, m_loadingProgress(false)
, m_paused(false)
, m_paused(true)
, m_hasAudio(false)
, m_hasVideo(false)
, m_preparingToPlay(false)
, m_hwndVideo(nullptr)
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
, m_weakPtrFactory(this)
{
@@ -167,28 +169,32 @@ MediaPlayer::SupportsType MediaPlayerPrivateMediaFoundation::supportsType(const
void MediaPlayerPrivateMediaFoundation::load(const String& url)
{
startCreateMediaSource(url);

m_networkState = MediaPlayer::Loading;
m_player->networkStateChanged();
m_readyState = MediaPlayer::HaveNothing;
m_player->readyStateChanged();
}

void MediaPlayerPrivateMediaFoundation::cancelLoad()
{
notImplemented();
}

void MediaPlayerPrivateMediaFoundation::play()
void MediaPlayerPrivateMediaFoundation::prepareToPlay()
{
if (!m_mediaSession)
return;

PROPVARIANT varStart;
PropVariantInit(&varStart);
varStart.vt = VT_EMPTY;

HRESULT hr = m_mediaSession->Start(nullptr, &varStart);
ASSERT(SUCCEEDED(hr));
// We call startSession() to start buffering video data.
// When we have received enough data, we pause, so that we don't actually start the playback.
ASSERT(m_paused);
ASSERT(!m_preparingToPlay);
m_preparingToPlay = startSession();
}

PropVariantClear(&varStart);
void MediaPlayerPrivateMediaFoundation::play()
{
m_paused = !startSession();

m_paused = !SUCCEEDED(hr);
m_preparingToPlay = false;
}

void MediaPlayerPrivateMediaFoundation::pause()
@@ -319,8 +325,7 @@ void MediaPlayerPrivateMediaFoundation::setMuted(bool muted)

MediaPlayer::NetworkState MediaPlayerPrivateMediaFoundation::networkState() const
{
notImplemented();
return MediaPlayer::Empty;
return m_networkState;
}

MediaPlayer::ReadyState MediaPlayerPrivateMediaFoundation::readyState() const
@@ -413,6 +418,23 @@ bool MediaPlayerPrivateMediaFoundation::createSession()
return true;
}

bool MediaPlayerPrivateMediaFoundation::startSession()
{
if (!m_mediaSession)
return false;

PROPVARIANT varStart;
PropVariantInit(&varStart);
varStart.vt = VT_EMPTY;

HRESULT hr = m_mediaSession->Start(nullptr, &varStart);
ASSERT(SUCCEEDED(hr));

PropVariantClear(&varStart);

return SUCCEEDED(hr);
}

bool MediaPlayerPrivateMediaFoundation::endSession()
{
if (m_mediaSession) {
@@ -503,11 +525,44 @@ bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
break;
}

case MESessionClosed:
case MEBufferingStarted: {
auto weakPtr = m_weakPtrFactory.createWeakPtr();
callOnMainThread([weakPtr] {
if (!weakPtr)
return;
weakPtr->onBufferingStarted();
});
break;
}

case MEBufferingStopped: {
auto weakPtr = m_weakPtrFactory.createWeakPtr();
callOnMainThread([weakPtr] {
if (!weakPtr)
return;
weakPtr->onBufferingStopped();
});
break;
}

case MESessionEnded: {
auto weakPtr = m_weakPtrFactory.createWeakPtr();
callOnMainThread([weakPtr] {
if (!weakPtr)
return;
weakPtr->onSessionEnded();
});
break;
}

case MEMediaSample:
break;

case MEError: {
HRESULT status = S_OK;
event->GetStatus(&status);
break;
}
}

if (mediaEventType != MESessionClosed) {
@@ -764,6 +819,49 @@ bool MediaPlayerPrivateMediaFoundation::createSourceStreamNode(COMPtr<IMFStreamD
return true;
}

void MediaPlayerPrivateMediaFoundation::updateReadyState()
{
if (!MFGetServicePtr())
return;

COMPtr<IPropertyStore> prop;

// Get the property store from the media session.
HRESULT hr = MFGetServicePtr()(m_mediaSession.get(), MFNETSOURCE_STATISTICS_SERVICE, IID_PPV_ARGS(&prop));

if (FAILED(hr))
return;

PROPERTYKEY key;
key.fmtid = MFNETSOURCE_STATISTICS;
key.pid = MFNETSOURCE_BUFFERPROGRESS_ID;

PROPVARIANT var;
hr = prop->GetValue(key, &var);

const LONG percentageOfPlaybackBufferFilled = var.lVal;

PropVariantClear(&var);

if (FAILED(hr))
return;

MediaPlayer::ReadyState oldReadyState = m_readyState;
if (percentageOfPlaybackBufferFilled >= 100) {
m_readyState = MediaPlayer::HaveEnoughData;
if (m_preparingToPlay) {
pause();
m_preparingToPlay = false;
}
} else if (percentageOfPlaybackBufferFilled > 0)
m_readyState = MediaPlayer::HaveFutureData;
else
m_readyState = MediaPlayer::HaveCurrentData;

if (m_readyState != oldReadyState)
m_player->readyStateChanged();
}

COMPtr<IMFVideoDisplayControl> MediaPlayerPrivateMediaFoundation::videoDisplay()
{
if (m_videoDisplay)
@@ -789,17 +887,33 @@ void MediaPlayerPrivateMediaFoundation::onCreatedMediaSource()

void MediaPlayerPrivateMediaFoundation::onTopologySet()
{
// This method is called on the main thread as a result of load() being called.

if (auto videoDisplay = this->videoDisplay()) {
RECT rc = { 0, 0, m_size.width(), m_size.height() };
videoDisplay->SetVideoPosition(nullptr, &rc);
}

m_readyState = MediaPlayer::HaveFutureData;
// It is expected that we start buffering data from the network now.
prepareToPlay();
}

ASSERT(m_player);
m_player->readyStateChanged();
void MediaPlayerPrivateMediaFoundation::onBufferingStarted()
{
updateReadyState();
}

play();
void MediaPlayerPrivateMediaFoundation::onBufferingStopped()
{
updateReadyState();
}

void MediaPlayerPrivateMediaFoundation::onSessionEnded()
{
m_networkState = MediaPlayer::Loaded;
m_player->networkStateChanged();

m_paused = true;
m_player->playbackStateChanged();
}

@@ -2974,7 +3088,8 @@ HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::updateDestRect()
return S_FALSE;

RECT rcView;
GetClientRect(m_hwnd, &rcView);
if (!GetClientRect(m_hwnd, &rcView))
return E_FAIL;

// Clip to the client area of the window.
if (m_destRect.right > rcView.right)
@@ -60,6 +60,8 @@ class MediaPlayerPrivateMediaFoundation : public MediaPlayerPrivateInterface {
void load(const String& url) override;
void cancelLoad() override;

void prepareToPlay() override;

void play() override;
void pause() override;

@@ -109,7 +111,9 @@ class MediaPlayerPrivateMediaFoundation : public MediaPlayerPrivateInterface {
bool m_paused;
bool m_hasAudio;
bool m_hasVideo;
bool m_preparingToPlay;
HWND m_hwndVideo;
MediaPlayer::NetworkState m_networkState;
MediaPlayer::ReadyState m_readyState;
FloatRect m_lastPaintRect;

@@ -126,6 +130,7 @@ class MediaPlayerPrivateMediaFoundation : public MediaPlayerPrivateInterface {
COMPtr<IMFVideoDisplayControl> m_videoDisplay;

bool createSession();
bool startSession();
bool endSession();
bool startCreateMediaSource(const String& url);
bool endCreatedMediaSource(IMFAsyncResult*);
@@ -135,10 +140,15 @@ class MediaPlayerPrivateMediaFoundation : public MediaPlayerPrivateInterface {
bool createOutputNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>&);
bool createSourceStreamNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>&);

void updateReadyState();

COMPtr<IMFVideoDisplayControl> videoDisplay();

void onCreatedMediaSource();
void onTopologySet();
void onBufferingStarted();
void onBufferingStopped();
void onSessionEnded();

LPCWSTR registerVideoWindowClass();
void createVideoWindow();

0 comments on commit 7ac0ac2

Please sign in to comment.