WebKit Bugzilla
Attachment 370410 Details for
Bug 193312
: Multiple videos (with audios) with autoplay & playinline not working. Only one video play at a time.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-193312-20190522095024.patch (text/plain), 37.26 KB, created by
youenn fablet
on 2019-05-22 09:50:25 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
youenn fablet
Created:
2019-05-22 09:50:25 PDT
Size:
37.26 KB
patch
obsolete
>Subversion Revision: 245568 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 67afe4ebcb4c491de915d240392cfa703c149e68..3bd5d4a494c038a72f33f4a196ec20790ce81e67 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,82 @@ >+2019-05-22 Youenn Fablet <youenn@apple.com> >+ >+ Multiple videos (with audios) with autoplay & playinline not working. Only one video play at a time. >+ https://bugs.webkit.org/show_bug.cgi?id=193312 >+ <rdar://problem/47189864> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Allow all MediaStream backed video elements to play together. >+ Any non MediaStream backed video will stop all MediaStream backed video elements. >+ Conversely, all non MediaStream backed videos will stop when playing one MediaStream backed video. >+ >+ Refactor PlatformMediaSessionManager as the way to iterate through sessions >+ is not safe when pausing a session: if playing, the session will be moved in the array of sessions. >+ >+ To handle this, copy the list of sessions before iterating through them. >+ For extra safety, make sessions WeakPtr. >+ >+ Add routines for the case of filtering with a predicate taking a const session. >+ In that case, we do not copy the vector but iterate through it as a small optimization. >+ >+ Test: webrtc/concurrentVideoPlayback.html >+ >+ * html/HTMLMediaElement.cpp: >+ (WebCore::HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager): >+ (WebCore::HTMLMediaElement::hasMediaStreamSource const): >+ * html/HTMLMediaElement.h: >+ * platform/audio/PlatformMediaSession.cpp: >+ (WebCore::PlatformMediaSession::activeAudioSessionRequired const): >+ (WebCore::PlatformMediaSession::canPlayConcurrently const): >+ (WebCore::PlatformMediaSession::activeAudioSessionRequired): Deleted. >+ * platform/audio/PlatformMediaSession.h: >+ (WebCore::PlatformMediaSessionClient::hasMediaStreamSource const): >+ * platform/audio/PlatformMediaSessionManager.cpp: >+ (WebCore::PlatformMediaSessionManager::has const): >+ (WebCore::PlatformMediaSessionManager::activeAudioSessionRequired const): >+ (WebCore::PlatformMediaSessionManager::canProduceAudio const): >+ (WebCore::PlatformMediaSessionManager::count const): >+ (WebCore::PlatformMediaSessionManager::beginInterruption): >+ (WebCore::PlatformMediaSessionManager::endInterruption): >+ (WebCore::PlatformMediaSessionManager::addSession): >+ (WebCore::PlatformMediaSessionManager::removeSession): >+ (WebCore::PlatformMediaSessionManager::sessionWillBeginPlayback): >+ (WebCore::PlatformMediaSessionManager::sessionWillEndPlayback): >+ (WebCore::PlatformMediaSessionManager::setCurrentSession): >+ (WebCore::PlatformMediaSessionManager::currentSession const): >+ (WebCore::PlatformMediaSessionManager::applicationWillBecomeInactive): >+ (WebCore::PlatformMediaSessionManager::applicationDidBecomeActive): >+ (WebCore::PlatformMediaSessionManager::applicationDidEnterBackground): >+ (WebCore::PlatformMediaSessionManager::applicationWillEnterForeground): >+ (WebCore::PlatformMediaSessionManager::systemWillSleep): >+ (WebCore::PlatformMediaSessionManager::systemDidWake): >+ (WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForDocument): >+ (WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForProcess): >+ (WebCore::PlatformMediaSessionManager::suspendAllMediaPlaybackForDocument): >+ (WebCore::PlatformMediaSessionManager::resumeAllMediaPlaybackForDocument): >+ (WebCore::PlatformMediaSessionManager::suspendAllMediaBufferingForDocument): >+ (WebCore::PlatformMediaSessionManager::resumeAllMediaBufferingForDocument): >+ (WebCore::PlatformMediaSessionManager::currentSessionsMatching const): >+ (WebCore::PlatformMediaSessionManager::forEachMatchingSession): >+ (WebCore::PlatformMediaSessionManager::forEachMatchingSession const): >+ (WebCore::PlatformMediaSessionManager::forEachSession): >+ (WebCore::PlatformMediaSessionManager::anyOfSessions const): >+ (): Deleted. >+ (WebCore::PlatformMediaSessionManager::applicationWillBecomeInactive const): Deleted. >+ (WebCore::PlatformMediaSessionManager::applicationDidBecomeActive const): Deleted. >+ (WebCore::PlatformMediaSessionManager::applicationDidEnterBackground const): Deleted. >+ (WebCore::PlatformMediaSessionManager::applicationWillEnterForeground const): Deleted. >+ (WebCore::PlatformMediaSessionManager::forEachSession const): Deleted. >+ (WebCore::PlatformMediaSessionManager::findSession const): Deleted. >+ * platform/audio/PlatformMediaSessionManager.h: >+ (WebCore::PlatformMediaSessionManager::anyOfSessions const): Deleted. >+ * platform/audio/cocoa/MediaSessionManagerCocoa.mm: >+ (MediaSessionManagerCocoa::updateSessionState): >+ (MediaSessionManagerCocoa::beginInterruption): >+ * platform/audio/ios/MediaSessionManagerIOS.mm: >+ (WebCore::MediaSessionManageriOS::configureWireLessTargetMonitoring): >+ (WebCore::MediaSessionManageriOS::externalOutputDeviceAvailableDidChange): >+ > 2019-05-21 Youenn Fablet <youenn@apple.com> > > Implement Feature policy self/none/* parsing >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index 92605852d261272f53fbd52638f111cabd9c64c6..98b2a9a8babcba668fc3bbe75a3aaf1f2039c3b7 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -1694,7 +1694,7 @@ void Document::allowsMediaDocumentInlinePlaybackChanged() > void Document::stopAllMediaPlayback() > { > if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists()) >- platformMediaSessionManager->stopAllMediaPlaybackForDocument(this); >+ platformMediaSessionManager->stopAllMediaPlaybackForDocument(*this); > } > > void Document::suspendAllMediaPlayback() >diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp >index cb845878e62e1da12b149d0c048f86d41b4db2fd..f00d81ca0889bb4927f3473a2b5401ec8ee8a4b5 100644 >--- a/Source/WebCore/html/HTMLMediaElement.cpp >+++ b/Source/WebCore/html/HTMLMediaElement.cpp >@@ -657,19 +657,17 @@ HTMLMediaElement::~HTMLMediaElement() > } > RefPtr<HTMLMediaElement> HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose purpose) > { >- auto allSessions = PlatformMediaSessionManager::sharedManager().currentSessionsMatching([] (const PlatformMediaSession& session) { >- return is<MediaElementSession>(session); >- }); >- > Vector<MediaElementSessionInfo> candidateSessions; > bool atLeastOneNonCandidateMayBeConfusedForMainContent = false; >- for (auto& session : allSessions) { >- auto mediaElementSessionInfo = mediaElementSessionInfoForSession(downcast<MediaElementSession>(*session), purpose); >+ PlatformMediaSessionManager::sharedManager().forEachMatchingSession([](auto& session) { >+ return is<MediaElementSession>(session); >+ }, [&](auto& session) { >+ auto mediaElementSessionInfo = mediaElementSessionInfoForSession(downcast<MediaElementSession>(session), purpose); > if (mediaElementSessionInfo.canShowControlsManager) > candidateSessions.append(mediaElementSessionInfo); > else if (mediaSessionMayBeConfusedWithMainContent(mediaElementSessionInfo, purpose)) > atLeastOneNonCandidateMayBeConfusedForMainContent = true; >- } >+ }); > > if (!candidateSessions.size()) > return nullptr; >@@ -8137,6 +8135,15 @@ HTMLMediaElementEnums::BufferingPolicy HTMLMediaElement::bufferingPolicy() const > return m_bufferingPolicy; > } > >+bool HTMLMediaElement::hasMediaStreamSource() const >+{ >+#if ENABLE(MEDIA_STREAM) >+ return hasMediaStreamSrcObject(); >+#else >+ return false; >+#endif >+} >+ > } > > #endif >diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h >index c15dc2412203aa477e5cb4fe5d7feaa4f5bf6501..2fff3633083a64099289e2a5795933deba595bdb 100644 >--- a/Source/WebCore/html/HTMLMediaElement.h >+++ b/Source/WebCore/html/HTMLMediaElement.h >@@ -892,6 +892,7 @@ private: > bool shouldOverrideBackgroundLoadingRestriction() const override; > bool canProduceAudio() const final; > bool processingUserGestureForMedia() const final; >+ bool hasMediaStreamSource() const final; > > void pageMutedStateDidChange() override; > >diff --git a/Source/WebCore/platform/audio/PlatformMediaSession.cpp b/Source/WebCore/platform/audio/PlatformMediaSession.cpp >index ba363791873449498f9b359fd18c9d860d33ff7e..e02394aa5b149cd1596912a25681ff5ea44ad8d2 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSession.cpp >+++ b/Source/WebCore/platform/audio/PlatformMediaSession.cpp >@@ -342,7 +342,7 @@ PlatformMediaSession::DisplayType PlatformMediaSession::displayType() const > return m_client.displayType(); > } > >-bool PlatformMediaSession::activeAudioSessionRequired() >+bool PlatformMediaSession::activeAudioSessionRequired() const > { > if (mediaType() == PlatformMediaSession::None) > return false; >@@ -388,6 +388,11 @@ void PlatformMediaSession::clientCharacteristicsChanged() > PlatformMediaSessionManager::sharedManager().clientCharacteristicsChanged(*this); > } > >+bool PlatformMediaSession::canPlayConcurrently(const PlatformMediaSession& otherSession) const >+{ >+ return m_client.hasMediaStreamSource() && otherSession.m_client.hasMediaStreamSource(); >+} >+ > #if !RELEASE_LOG_DISABLED > WTFLogChannel& PlatformMediaSession::logChannel() const > { >diff --git a/Source/WebCore/platform/audio/PlatformMediaSession.h b/Source/WebCore/platform/audio/PlatformMediaSession.h >index 469824d290d69f4c916713fa101d80084c3d9b82..9c3511765ad09ab252c16a9cf3395af7ed7a14c3 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSession.h >+++ b/Source/WebCore/platform/audio/PlatformMediaSession.h >@@ -29,6 +29,7 @@ > #include "Timer.h" > #include <wtf/LoggerHelper.h> > #include <wtf/Noncopyable.h> >+#include <wtf/WeakPtr.h> > #include <wtf/text/WTFString.h> > > #if ENABLE(WIRELESS_PLAYBACK_TARGET) >@@ -42,8 +43,9 @@ class MediaPlaybackTarget; > class PlatformMediaSessionClient; > > class PlatformMediaSession >+ : public CanMakeWeakPtr<PlatformMediaSession> > #if ENABLE(WIRELESS_PLAYBACK_TARGET) >- : public MediaPlaybackTargetClient >+ , public MediaPlaybackTargetClient > #endif > #if !RELEASE_LOG_DISABLED > , private LoggerHelper >@@ -170,7 +172,7 @@ public: > virtual bool requiresPlaybackTargetRouteMonitoring() const { return false; } > #endif > >- bool activeAudioSessionRequired(); >+ bool activeAudioSessionRequired() const; > bool canProduceAudio() const; > void canProduceAudioChanged(); > >@@ -189,6 +191,8 @@ public: > WTFLogChannel& logChannel() const final; > #endif > >+ bool canPlayConcurrently(const PlatformMediaSession&) const; >+ > protected: > PlatformMediaSessionClient& client() const { return m_client; } > >@@ -253,6 +257,8 @@ public: > > virtual bool processingUserGestureForMedia() const = 0; > >+ virtual bool hasMediaStreamSource() const { return false; } >+ > protected: > virtual ~PlatformMediaSessionClient() = default; > }; >diff --git a/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp b/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp >index 665c38c1194746baa37d35487fe1d092a079ffe4..426a6745a05d8bebea67540b522ad294dbe917d4 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp >+++ b/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp >@@ -79,21 +79,21 @@ bool PlatformMediaSessionManager::has(PlatformMediaSession::MediaType type) cons > { > ASSERT(type >= PlatformMediaSession::None && type <= PlatformMediaSession::MediaStreamCapturingAudio); > >- return anyOfSessions([type] (PlatformMediaSession& session, size_t) { >+ return anyOfSessions([type] (auto& session) { > return session.mediaType() == type; > }); > } > > bool PlatformMediaSessionManager::activeAudioSessionRequired() const > { >- return anyOfSessions([] (PlatformMediaSession& session, size_t) { >+ return anyOfSessions([] (auto& session) { > return session.activeAudioSessionRequired(); > }); > } > > bool PlatformMediaSessionManager::canProduceAudio() const > { >- return anyOfSessions([] (PlatformMediaSession& session, size_t) { >+ return anyOfSessions([] (auto& session) { > return session.canProduceAudio(); > }); > } >@@ -103,7 +103,7 @@ int PlatformMediaSessionManager::count(PlatformMediaSession::MediaType type) con > ASSERT(type >= PlatformMediaSession::None && type <= PlatformMediaSession::MediaStreamCapturingAudio); > > int count = 0; >- for (auto* session : m_sessions) { >+ for (const auto& session : m_sessions) { > if (session->mediaType() == type) > ++count; > } >@@ -116,7 +116,7 @@ void PlatformMediaSessionManager::beginInterruption(PlatformMediaSession::Interr > ALWAYS_LOG(LOGIDENTIFIER); > > m_interrupted = true; >- forEachSession([type] (PlatformMediaSession& session, size_t) { >+ forEachSession([type] (auto& session) { > session.beginInterruption(type); > }); > updateSessionState(); >@@ -127,7 +127,7 @@ void PlatformMediaSessionManager::endInterruption(PlatformMediaSession::EndInter > ALWAYS_LOG(LOGIDENTIFIER); > > m_interrupted = false; >- forEachSession([flags] (PlatformMediaSession& session, size_t) { >+ forEachSession([flags] (auto& session) { > session.endInterruption(flags); > }); > } >@@ -135,8 +135,7 @@ void PlatformMediaSessionManager::endInterruption(PlatformMediaSession::EndInter > void PlatformMediaSessionManager::addSession(PlatformMediaSession& session) > { > ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier()); >- >- m_sessions.append(&session); >+ m_sessions.append(makeWeakPtr(session)); > if (m_interrupted) > session.setState(PlatformMediaSession::Interrupted); > >@@ -156,15 +155,12 @@ void PlatformMediaSessionManager::addSession(PlatformMediaSession& session) > void PlatformMediaSessionManager::removeSession(PlatformMediaSession& session) > { > ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier()); >- >+ > size_t index = m_sessions.find(&session); > if (index == notFound) > return; > >- if (m_iteratingOverSessions) >- m_sessions.at(index) = nullptr; >- else >- m_sessions.remove(index); >+ m_sessions.remove(index); > > if (m_sessions.isEmpty() || std::all_of(m_sessions.begin(), m_sessions.end(), std::logical_not<void>())) { > m_remoteCommandListener = nullptr; >@@ -233,15 +229,16 @@ bool PlatformMediaSessionManager::sessionWillBeginPlayback(PlatformMediaSession& > if (m_interrupted) > endInterruption(PlatformMediaSession::NoFlags); > >- forEachSession([&] (PlatformMediaSession& oneSession, size_t) { >- if (&oneSession == &session) >- return; >- if (oneSession.mediaType() == sessionType >- && restrictions & ConcurrentPlaybackNotPermitted >- && oneSession.state() == PlatformMediaSession::Playing) >+ if (restrictions & ConcurrentPlaybackNotPermitted) { >+ forEachMatchingSession([&session, sessionType](auto& oneSession) { >+ return &oneSession != &session >+ && oneSession.mediaType() == sessionType >+ && oneSession.state() == PlatformMediaSession::Playing >+ && !oneSession.canPlayConcurrently(session); >+ }, [](auto& oneSession) { > oneSession.pauseSession(); >- }); >- >+ }); >+ } > ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning true"); > return true; > } >@@ -255,25 +252,27 @@ void PlatformMediaSessionManager::sessionWillEndPlayback(PlatformMediaSession& s > > size_t pausingSessionIndex = notFound; > size_t lastPlayingSessionIndex = notFound; >- anyOfSessions([&] (PlatformMediaSession& oneSession, size_t i) { >+ for (size_t i = 0, size = m_sessions.size(); i < size; ++i) { >+ const auto& oneSession = *m_sessions[i]; > if (&oneSession == &session) { > pausingSessionIndex = i; >- return false; >+ break; > } > if (oneSession.state() == PlatformMediaSession::Playing) { > lastPlayingSessionIndex = i; >- return false; >+ break; > } >- return oneSession.state() != PlatformMediaSession::Playing; >- }); >+ if (oneSession.state() != PlatformMediaSession::Playing) >+ break; >+ } > if (lastPlayingSessionIndex == notFound || pausingSessionIndex == notFound) > return; > > if (pausingSessionIndex > lastPlayingSessionIndex) > return; >- >+ > m_sessions.remove(pausingSessionIndex); >- m_sessions.insert(lastPlayingSessionIndex, &session); >+ m_sessions.append(makeWeakPtr(session)); > > ALWAYS_LOG(LOGIDENTIFIER, "session moved from index ", pausingSessionIndex, " to ", lastPlayingSessionIndex); > } >@@ -296,7 +295,7 @@ void PlatformMediaSessionManager::setCurrentSession(PlatformMediaSession& sessio > return; > > m_sessions.remove(index); >- m_sessions.insert(0, &session); >+ m_sessions.insert(0, makeWeakPtr(session)); > if (m_remoteCommandListener) > m_remoteCommandListener->updateSupportedCommands(); > >@@ -308,40 +307,32 @@ PlatformMediaSession* PlatformMediaSessionManager::currentSession() const > if (!m_sessions.size()) > return nullptr; > >- return m_sessions[0]; >-} >- >-Vector<PlatformMediaSession*> PlatformMediaSessionManager::currentSessionsMatching(const WTF::Function<bool(const PlatformMediaSession&)>& filter) >-{ >- Vector<PlatformMediaSession*> matchingSessions; >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if (filter(session)) >- matchingSessions.append(&session); >- }); >- return matchingSessions; >+ return m_sessions[0].get(); > } > >-void PlatformMediaSessionManager::applicationWillBecomeInactive() const >+void PlatformMediaSessionManager::applicationWillBecomeInactive() > { > ALWAYS_LOG(LOGIDENTIFIER); > >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if (m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted) >- session.beginInterruption(PlatformMediaSession::ProcessInactive); >+ forEachMatchingSession([&](auto& session) { >+ return m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted; >+ }, [](auto& session) { >+ session.beginInterruption(PlatformMediaSession::ProcessInactive); > }); > } > >-void PlatformMediaSessionManager::applicationDidBecomeActive() const >+void PlatformMediaSessionManager::applicationDidBecomeActive() > { > ALWAYS_LOG(LOGIDENTIFIER); > >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if (m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted) >- session.endInterruption(PlatformMediaSession::MayResumePlaying); >+ forEachMatchingSession([&](auto& session) { >+ return m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted; >+ }, [](auto& session) { >+ session.endInterruption(PlatformMediaSession::MayResumePlaying); > }); > } > >-void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUnderLock) const >+void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUnderLock) > { > ALWAYS_LOG(LOGIDENTIFIER, "suspendedUnderLock: ", suspendedUnderLock); > >@@ -350,7 +341,7 @@ void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUn > > m_isApplicationInBackground = true; > >- forEachSession([&] (PlatformMediaSession& session, size_t) { >+ forEachSession([&] (auto& session) { > if (suspendedUnderLock && m_restrictions[session.mediaType()] & SuspendedUnderLockPlaybackRestricted) > session.beginInterruption(PlatformMediaSession::SuspendedUnderLock); > else if (m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted) >@@ -358,7 +349,7 @@ void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUn > }); > } > >-void PlatformMediaSessionManager::applicationWillEnterForeground(bool suspendedUnderLock) const >+void PlatformMediaSessionManager::applicationWillEnterForeground(bool suspendedUnderLock) > { > ALWAYS_LOG(LOGIDENTIFIER, "suspendedUnderLock: ", suspendedUnderLock); > >@@ -367,9 +358,10 @@ void PlatformMediaSessionManager::applicationWillEnterForeground(bool suspendedU > > m_isApplicationInBackground = false; > >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if ((suspendedUnderLock && m_restrictions[session.mediaType()] & SuspendedUnderLockPlaybackRestricted) || m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted) >- session.endInterruption(PlatformMediaSession::MayResumePlaying); >+ forEachMatchingSession([&](auto& session) { >+ return (suspendedUnderLock && m_restrictions[session.mediaType()] & SuspendedUnderLockPlaybackRestricted) || m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted; >+ }, [](auto& session) { >+ session.endInterruption(PlatformMediaSession::MayResumePlaying); > }); > } > >@@ -438,7 +430,7 @@ void PlatformMediaSessionManager::systemWillSleep() > if (m_interrupted) > return; > >- forEachSession([] (PlatformMediaSession& session, size_t) { >+ forEachSession([] (auto& session) { > session.beginInterruption(PlatformMediaSession::SystemSleep); > }); > } >@@ -448,7 +440,7 @@ void PlatformMediaSessionManager::systemDidWake() > if (m_interrupted) > return; > >- forEachSession([] (PlatformMediaSession& session, size_t) { >+ forEachSession([] (auto& session) { > session.endInterruption(PlatformMediaSession::MayResumePlaying); > }); > } >@@ -458,91 +450,91 @@ void PlatformMediaSessionManager::audioOutputDeviceChanged() > updateSessionState(); > } > >-void PlatformMediaSessionManager::stopAllMediaPlaybackForDocument(const Document* document) >+void PlatformMediaSessionManager::stopAllMediaPlaybackForDocument(const Document& document) > { >- forEachSession([document] (PlatformMediaSession& session, size_t) { >- if (session.client().hostingDocument() == document) >- session.pauseSession(); >+ forEachDocumentSession(document, [](auto& session) { >+ session.pauseSession(); > }); > } > > void PlatformMediaSessionManager::stopAllMediaPlaybackForProcess() > { >- forEachSession([] (PlatformMediaSession& session, size_t) { >+ forEachSession([] (auto& session) { > session.stopSession(); > }); > } > > void PlatformMediaSessionManager::suspendAllMediaPlaybackForDocument(const Document& document) > { >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if (session.client().hostingDocument() == &document) >- session.beginInterruption(PlatformMediaSession::PlaybackSuspended); >+ forEachDocumentSession(document, [](auto& session) { >+ session.beginInterruption(PlatformMediaSession::PlaybackSuspended); > }); > } > > void PlatformMediaSessionManager::resumeAllMediaPlaybackForDocument(const Document& document) > { >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if (session.client().hostingDocument() == &document) >- session.endInterruption(PlatformMediaSession::MayResumePlaying); >+ forEachDocumentSession(document, [](auto& session) { >+ session.endInterruption(PlatformMediaSession::MayResumePlaying); > }); > } > > void PlatformMediaSessionManager::suspendAllMediaBufferingForDocument(const Document& document) > { >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if (session.client().hostingDocument() == &document) >- session.suspendBuffering(); >+ forEachDocumentSession(document, [](auto& session) { >+ session.suspendBuffering(); > }); > } > > void PlatformMediaSessionManager::resumeAllMediaBufferingForDocument(const Document& document) > { >- forEachSession([&] (PlatformMediaSession& session, size_t) { >- if (session.client().hostingDocument() == &document) >- session.resumeBuffering(); >+ forEachDocumentSession(document, [](auto& session) { >+ session.resumeBuffering(); > }); > } > >-void PlatformMediaSessionManager::forEachSession(const Function<void(PlatformMediaSession&, size_t)>& predicate) const >+Vector<WeakPtr<PlatformMediaSession>> PlatformMediaSessionManager::sessionsMatching(const WTF::Function<bool(const PlatformMediaSession&)>& filter) const > { >- ++m_iteratingOverSessions; >- >- for (size_t i = 0, size = m_sessions.size(); i < size; ++i) { >- auto session = m_sessions[i]; >- if (!session) >- continue; >- predicate(*session, i); >+ Vector<WeakPtr<PlatformMediaSession>> matchingSessions; >+ for (auto& session : m_sessions) { >+ if (filter(*session)) >+ matchingSessions.append(session); > } >- >- --m_iteratingOverSessions; >- if (!m_iteratingOverSessions) >- m_sessions.removeAll(nullptr); >+ return matchingSessions; > } > >-PlatformMediaSession* PlatformMediaSessionManager::findSession(const Function<bool(PlatformMediaSession&, size_t)>& predicate) const >+void PlatformMediaSessionManager::forEachMatchingSession(const Function<bool(const PlatformMediaSession&)>& predicate, const Function<void(PlatformMediaSession&)>& callback) > { >- ++m_iteratingOverSessions; >- >- PlatformMediaSession* foundSession = nullptr; >- for (size_t i = 0, size = m_sessions.size(); i < size; ++i) { >- auto session = m_sessions[i]; >- if (!session) >- continue; >+ for (auto& session : sessionsMatching(predicate)) { >+ ASSERT(session); >+ if (session) >+ callback(*session); >+ } >+} > >- if (!predicate(*session, i)) >- continue; >+void PlatformMediaSessionManager::forEachDocumentSession(const Document& document, const Function<void(PlatformMediaSession&)>& callback) >+{ >+ forEachMatchingSession([&document](auto& session) { >+ return session.client().hostingDocument() == &document; >+ }, [&callback](auto& session) { >+ callback(session); >+ }); >+} > >- foundSession = session; >- break; >+void PlatformMediaSessionManager::forEachSession(const Function<void(PlatformMediaSession&)>& callback) >+{ >+ auto sessions = m_sessions; >+ for (auto& session : sessions) { >+ ASSERT(session); >+ if (session) >+ callback(*session); > } >+} > >- --m_iteratingOverSessions; >- if (!m_iteratingOverSessions) >- m_sessions.removeAll(nullptr); >- >- return foundSession; >+bool PlatformMediaSessionManager::anyOfSessions(const Function<bool(const PlatformMediaSession&)>& predicate) const >+{ >+ return WTF::anyOf(m_sessions, [&predicate](const auto& session) { >+ return predicate(*session); >+ }); > } > > static bool& deactivateAudioSession() >diff --git a/Source/WebCore/platform/audio/PlatformMediaSessionManager.h b/Source/WebCore/platform/audio/PlatformMediaSessionManager.h >index 98f1f5e0321d29436186b5435c34674cf223254f..3685307b7308d0e3908ca36ef5fa13b728512178 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSessionManager.h >+++ b/Source/WebCore/platform/audio/PlatformMediaSessionManager.h >@@ -81,14 +81,14 @@ public: > WEBCORE_EXPORT virtual void beginInterruption(PlatformMediaSession::InterruptionType); > WEBCORE_EXPORT void endInterruption(PlatformMediaSession::EndInterruptionFlags); > >- WEBCORE_EXPORT void applicationWillBecomeInactive() const; >- WEBCORE_EXPORT void applicationDidBecomeActive() const; >- WEBCORE_EXPORT void applicationWillEnterForeground(bool suspendedUnderLock) const; >- WEBCORE_EXPORT void applicationDidEnterBackground(bool suspendedUnderLock) const; >+ WEBCORE_EXPORT void applicationWillBecomeInactive(); >+ WEBCORE_EXPORT void applicationDidBecomeActive(); >+ WEBCORE_EXPORT void applicationWillEnterForeground(bool suspendedUnderLock); >+ WEBCORE_EXPORT void applicationDidEnterBackground(bool suspendedUnderLock); > WEBCORE_EXPORT void processWillSuspend(); > WEBCORE_EXPORT void processDidResume(); > >- void stopAllMediaPlaybackForDocument(const Document*); >+ void stopAllMediaPlaybackForDocument(const Document&); > WEBCORE_EXPORT void stopAllMediaPlaybackForProcess(); > > void suspendAllMediaPlaybackForDocument(const Document&); >@@ -127,10 +127,10 @@ public: > void setCurrentSession(PlatformMediaSession&); > PlatformMediaSession* currentSession() const; > >- Vector<PlatformMediaSession*> currentSessionsMatching(const WTF::Function<bool(const PlatformMediaSession&)>&); >- > void sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession&); > >+ void forEachMatchingSession(const Function<bool(const PlatformMediaSession&)>& predicate, const Function<void(PlatformMediaSession&)>& matchingCallback); >+ > protected: > friend class PlatformMediaSession; > explicit PlatformMediaSessionManager(); >@@ -138,9 +138,9 @@ protected: > void addSession(PlatformMediaSession&); > virtual void removeSession(PlatformMediaSession&); > >- void forEachSession(const Function<void(PlatformMediaSession&, size_t)>&) const; >- PlatformMediaSession* findSession(const Function<bool(PlatformMediaSession&, size_t)>&) const; >- bool anyOfSessions(const Function<bool(PlatformMediaSession&, size_t)>& predicate) const { return findSession(predicate); } >+ void forEachSession(const Function<void(PlatformMediaSession&)>&); >+ void forEachDocumentSession(const Document&, const Function<void(PlatformMediaSession&)>&); >+ bool anyOfSessions(const Function<bool(const PlatformMediaSession&)>&) const; > > AudioHardwareListener* audioHardwareListener() { return m_audioHardwareListener.get(); } > >@@ -171,8 +171,10 @@ private: > void systemWillSleep() override; > void systemDidWake() override; > >+ Vector<WeakPtr<PlatformMediaSession>> sessionsMatching(const Function<bool(const PlatformMediaSession&)>&) const; >+ > SessionRestrictions m_restrictions[PlatformMediaSession::MediaStreamCapturingAudio + 1]; >- mutable Vector<PlatformMediaSession*> m_sessions; >+ mutable Vector<WeakPtr<PlatformMediaSession>> m_sessions; > std::unique_ptr<RemoteCommandListener> m_remoteCommandListener; > std::unique_ptr<PAL::SystemSleepListener> m_systemSleepListener; > RefPtr<AudioHardwareListener> m_audioHardwareListener; >@@ -185,7 +187,6 @@ private: > bool m_interrupted { false }; > mutable bool m_isApplicationInBackground { false }; > bool m_willIgnoreSystemInterruptions { false }; >- mutable int m_iteratingOverSessions { 0 }; > bool m_processIsSuspended { false }; > > #if USE(AUDIO_SESSION) >diff --git a/Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.mm b/Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.mm >index 374d4cbb8200d309061584fd6a6d6021b75cb522..ee22386fa97a0673f7deb2791e4014ac748f3971 100644 >--- a/Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.mm >+++ b/Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.mm >@@ -97,7 +97,7 @@ void MediaSessionManagerCocoa::updateSessionState() > return; > > bool hasAudibleAudioOrVideoMediaType = false; >- forEachSession([&hasAudibleAudioOrVideoMediaType] (PlatformMediaSession& session, size_t) mutable { >+ forEachSession([&hasAudibleAudioOrVideoMediaType] (auto& session) mutable { > auto type = session.mediaType(); > if ((type == PlatformMediaSession::VideoAudio || type == PlatformMediaSession::Audio) && session.canProduceAudio() && session.hasPlayedSinceLastInterruption()) > hasAudibleAudioOrVideoMediaType = true; >@@ -122,7 +122,7 @@ void MediaSessionManagerCocoa::updateSessionState() > void MediaSessionManagerCocoa::beginInterruption(PlatformMediaSession::InterruptionType type) > { > if (type == PlatformMediaSession::InterruptionType::SystemInterruption) { >- forEachSession([] (PlatformMediaSession& session, size_t) { >+ forEachSession([] (auto& session) { > session.clearHasPlayedSinceLastInterruption(); > }); > } >diff --git a/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm b/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm >index e1a9fb411f18ed70bd58685573d3534cda749095..0043904a53025e4450015af0068b63c532447853 100644 >--- a/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm >+++ b/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm >@@ -146,7 +146,7 @@ bool MediaSessionManageriOS::hasWirelessTargetsAvailable() > void MediaSessionManageriOS::configureWireLessTargetMonitoring() > { > #if HAVE(MEDIA_PLAYER) && !PLATFORM(WATCHOS) >- bool requiresMonitoring = anyOfSessions([] (PlatformMediaSession& session, size_t) { >+ bool requiresMonitoring = anyOfSessions([] (auto& session) { > return session.requiresPlaybackTargetRouteMonitoring(); > }); > >@@ -187,7 +187,7 @@ void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange() > bool haveTargets = [m_objcObserver hasWirelessTargetsAvailable]; > ALWAYS_LOG(LOGIDENTIFIER, haveTargets); > >- forEachSession([haveTargets] (PlatformMediaSession& session, size_t) { >+ forEachSession([haveTargets] (auto& session) { > session.externalOutputDeviceAvailableDidChange(haveTargets); > }); > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index be07c80a8975a008754f6563605f321cf59178ec..1f593031de31273bc38d9d32f03bc51f05c9ee9b 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,14 @@ >+2019-05-22 Youenn Fablet <youenn@apple.com> >+ >+ Multiple videos (with audios) with autoplay & playinline not working. Only one video play at a time. >+ https://bugs.webkit.org/show_bug.cgi?id=193312 >+ <rdar://problem/47189864> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * webrtc/concurrentVideoPlayback-expected.txt: Added. >+ * webrtc/concurrentVideoPlayback.html: Added. >+ > 2019-05-22 Youenn Fablet <youenn@apple.com> > > Layout Test http/wpt/cache-storage/cache-put-stream.https.any.html is a flaky failure >diff --git a/LayoutTests/webrtc/concurrentVideoPlayback-expected.txt b/LayoutTests/webrtc/concurrentVideoPlayback-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..7ec7dfb3d44277d196bed71527aec008e45d53d0 >--- /dev/null >+++ b/LayoutTests/webrtc/concurrentVideoPlayback-expected.txt >@@ -0,0 +1,7 @@ >+ >+ >+PASS Basic audio/video exchange >+PASS Play MediaStream backed streams concurrently >+PASS Play regular video content should pause MediaStream backed video elements >+PASS Play MediaStream backed video elements should pause regular video content >+ >diff --git a/LayoutTests/webrtc/concurrentVideoPlayback.html b/LayoutTests/webrtc/concurrentVideoPlayback.html >new file mode 100644 >index 0000000000000000000000000000000000000000..59610c4dcd354d9ae2ad8b5c3b8e2b5e45b92640 >--- /dev/null >+++ b/LayoutTests/webrtc/concurrentVideoPlayback.html >@@ -0,0 +1,80 @@ >+<!doctype html> >+<html> >+ <head> >+ <meta charset="utf-8"> >+ <title>Testing concurrent video playing</title> >+ <script src="../resources/testharness.js"></script> >+ <script src="../resources/testharnessreport.js"></script> >+ <script src="../media/media-file.js"></script> >+ </head> >+ <body> >+ <video id="video1" autoplay controls></video> >+ <video id="video2" autoplay controls></video> >+ <video id="video3" autoplay controls></video> >+ <script src ="routines.js"></script> >+ <script> >+promise_test(async (test) => { >+ if (window.testRunner) >+ testRunner.setUserMediaPermission(true); >+ >+ localStream = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); >+ >+ const remoteStream = await new Promise((resolve, reject) => { >+ createConnections((firstConnection) => { >+ firstConnection.addTrack(localStream.getVideoTracks()[0], localStream); >+ firstConnection.addTrack(localStream.getAudioTracks()[0], localStream); >+ }, (secondConnection) => { >+ secondConnection.ontrack = (trackEvent) => { >+ resolve(trackEvent.streams[0]); >+ }; >+ }); >+ setTimeout(() => reject("Test timed out"), 5000); >+ }); >+ >+ video1.srcObject = localStream; >+ video2.srcObject = remoteStream; >+}, "Basic audio/video exchange"); >+ >+promise_test(async (test) => { >+ await video1.play(); >+ await video2.play(); >+ >+ assert_false(video1.paused, "video1 paused"); >+ assert_false(video2.paused, "video2 paused"); >+}, "Play MediaStream backed streams concurrently"); >+ >+promise_test(async (test) => { >+ >+ if (window.internals) >+ internals.setMediaSessionRestrictions('videoaudio', 'ConcurrentPlaybackNotPermitted'); >+ >+ video3.src = findMediaFile('video', '../media/content/audio-tracks'); >+ await video3.play(); >+ >+ let counter = 0; >+ while (!video1.paused && ++counter < 20) >+ await new Promise(resolve => setTimeout(resolve, 50)); >+ >+ assert_true(video1.paused, "video1 paused"); >+ assert_true(video2.paused, "video2 paused"); >+ assert_false(video3.paused, "video3 paused"); >+}, "Play regular video content should pause MediaStream backed video elements"); >+ >+promise_test(async (test) => { >+ await video1.play(); >+ >+ assert_true(video3.paused, "video3 paused"); >+ >+ await video2.play(); >+ >+ let counter = 0; >+ while (!video3.paused && ++counter < 20) >+ await new Promise(resolve => setTimeout(resolve, 50)); >+ >+ assert_false(video1.paused, "video1 paused"); >+ assert_false(video2.paused, "video2 paused"); >+ assert_true(video3.paused, "video3 paused"); >+}, "Play MediaStream backed video elements should pause regular video content"); >+ </script> >+ </body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 193312
:
358783
|
370397
|
370409
| 370410