Title: [283033] trunk
Revision
283033
Author
[email protected]
Date
2021-09-24 02:39:18 -0700 (Fri, 24 Sep 2021)

Log Message

[IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
https://bugs.webkit.org/show_bug.cgi?id=230538
<rdar://problem/83355705>

Reviewed by Eric Carlson.

Source/WebCore:

Add support for interrupting mock cameras.
Update internals to handle the case of out of main thread videoSampleAvailable calls.

Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
This ensures we can restart capture in case a track is muted without the page being muted itself.

When a source is muted and is in producing data state, it is interrupted.
When setMuted(false) is called, we need to uninterrupt.
To do so, we do a stop/start cycle

Test: fast/mediastream/media-stream-video-track-interrupted.html

* page/Page.cpp:
(WebCore::Page::setMuted):
* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::setMuted):
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
* platform/mock/MockRealtimeMediaSourceCenter.h:
* platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
(WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
(WebCore::MockRealtimeVideoSource::setIsInterrupted):
* platform/mock/MockRealtimeVideoSource.h:
* testing/Internals.cpp:
(WebCore::Internals::videoSampleAvailable):
* testing/Internals.h:

Source/WebKit:

Add support for mock capture interruption.
When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
It is important to not stop the source so that it can continue receiving interruption notifications.

* GPUProcess/GPUProcess.cpp:
(WebKit::GPUProcess::setMockCameraIsInterrupted):
* GPUProcess/GPUProcess.h:
* GPUProcess/GPUProcess.messages.in:
* UIProcess/API/C/WKPage.cpp:
(WKPageIsMockRealtimeMediaSourceCenterEnabled):
(WKPageSetMockCameraIsInterrupted):
* UIProcess/API/C/WKPagePrivate.h:
* UIProcess/GPU/GPUProcessProxy.cpp:
(WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
* UIProcess/GPU/GPUProcessProxy.h:
* WebProcess/cocoa/RemoteRealtimeAudioSource.h:
* WebProcess/cocoa/RemoteRealtimeVideoSource.h:
* WebProcess/cocoa/UserMediaCaptureManager.cpp:
(WebKit::UserMediaCaptureManager::sourceMutedChanged):

Tools:

Add mock API to mock camera interruption.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setMockCameraIsInterrupted):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::setMockCameraIsInterrupted):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

* fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
* fast/mediastream/media-stream-video-track-interrupted.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (283032 => 283033)


--- trunk/LayoutTests/ChangeLog	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/LayoutTests/ChangeLog	2021-09-24 09:39:18 UTC (rev 283033)
@@ -1,3 +1,14 @@
+2021-09-24  Youenn Fablet  <[email protected]>
+
+        [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+        https://bugs.webkit.org/show_bug.cgi?id=230538
+        <rdar://problem/83355705>
+
+        Reviewed by Eric Carlson.
+
+        * fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
+        * fast/mediastream/media-stream-video-track-interrupted.html: Added.
+
 2021-09-24  Brandon Stewart  <[email protected]>
 
         [RenderTreeUpdater] NULL ptr deref in updateRenderTree

Added: trunk/LayoutTests/fast/mediastream/media-stream-video-track-interrupted-expected.txt (0 => 283033)


--- trunk/LayoutTests/fast/mediastream/media-stream-video-track-interrupted-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/media-stream-video-track-interrupted-expected.txt	2021-09-24 09:39:18 UTC (rev 283033)
@@ -0,0 +1,4 @@
+
+PASS Interrupt/resume video track
+PASS Interrupt video track then uninterrupt it using page unmuting
+

Added: trunk/LayoutTests/fast/mediastream/media-stream-video-track-interrupted.html (0 => 283033)


--- trunk/LayoutTests/fast/mediastream/media-stream-video-track-interrupted.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/media-stream-video-track-interrupted.html	2021-09-24 09:39:18 UTC (rev 283033)
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Capture source interruption.</title>
+    <script src=""
+    <script src=""
+ </head>
+<body>
+    <script>
+    promise_test(async (test) => {
+        const stream = await navigator.mediaDevices.getUserMedia({video: true});
+        const track = stream.getVideoTracks()[0];
+        if (!window.testRunner)
+            return;
+
+        let promise = new Promise((resolve, reject) => { track._onmute_ = resolve; setTimeout(() => reject("no mute"), 5000) });
+        testRunner.setMockCameraIsInterrupted(true);
+        await promise;
+
+        assert_true(track.muted, "track is muted");
+
+        promise = new Promise((resolve, reject) => { track._onunmute_ = resolve; setTimeout(() => reject("no unmute"), 5000) });
+        testRunner.setMockCameraIsInterrupted(false);
+        await promise;
+
+        assert_false(track.muted, "track is not muted");
+
+        track.stop();
+    }, "Interrupt/resume video track");
+
+    promise_test(async (test) => {
+        const stream = await navigator.mediaDevices.getUserMedia({video: true});
+        const track = stream.getVideoTracks()[0];
+        if (!window.testRunner || !window.internals)
+            return;
+        internals.observeMediaStreamTrack(track);
+
+        // video frames should flow.
+        let current = internals.trackVideoSampleCount;
+        let counter = 0;
+        while (internals.trackVideoSampleCount === current && ++counter < 50)
+            await new Promise(resolve => setTimeout(resolve, 50));
+        assert_less_than(counter, 50, "first live check");
+
+        // getting an interruption, track should be muted.
+        let promise = new Promise((resolve, reject) => { track._onmute_ = resolve; setTimeout(() => reject("no mute"), 5000) });
+        testRunner.setMockCameraIsInterrupted(true);
+        await promise;
+
+        assert_true(track.muted, "track is muted");
+
+        // video frames should not flow.
+        counter = 0;
+        while (internals.trackVideoSampleCount !== current && ++counter < 50) {
+            current = internals.trackVideoSampleCount;
+            await new Promise(resolve => setTimeout(resolve, 200));
+        }
+        assert_less_than(counter, 50, "first muted check");
+
+        // Unmuting page should restart capture.
+        promise = new Promise((resolve, reject) => { track._onunmute_ = resolve; setTimeout(() => reject("no unmute"), 5000) });
+        internals.setPageMuted('');
+        await promise;
+
+        assert_false(track.muted, "track is not muted");
+
+        current = internals.trackVideoSampleCount;
+        counter = 0;
+        while (internals.trackVideoSampleCount === current && ++counter < 50)
+            await new Promise(resolve => setTimeout(resolve, 50));
+        assert_less_than(counter, 50, "second live check");
+
+        track.stop();
+    }, "Interrupt video track then uninterrupt it using page unmuting");
+    </script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (283032 => 283033)


--- trunk/Source/WebCore/ChangeLog	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/ChangeLog	2021-09-24 09:39:18 UTC (rev 283033)
@@ -1,3 +1,39 @@
+2021-09-24  Youenn Fablet  <[email protected]>
+
+        [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+        https://bugs.webkit.org/show_bug.cgi?id=230538
+        <rdar://problem/83355705>
+
+        Reviewed by Eric Carlson.
+
+        Add support for interrupting mock cameras.
+        Update internals to handle the case of out of main thread videoSampleAvailable calls.
+
+        Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
+        This ensures we can restart capture in case a track is muted without the page being muted itself.
+
+        When a source is muted and is in producing data state, it is interrupted.
+        When setMuted(false) is called, we need to uninterrupt.
+        To do so, we do a stop/start cycle
+
+        Test: fast/mediastream/media-stream-video-track-interrupted.html
+
+        * page/Page.cpp:
+        (WebCore::Page::setMuted):
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::setMuted):
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
+        * platform/mock/MockRealtimeMediaSourceCenter.h:
+        * platform/mock/MockRealtimeVideoSource.cpp:
+        (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
+        (WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
+        (WebCore::MockRealtimeVideoSource::setIsInterrupted):
+        * platform/mock/MockRealtimeVideoSource.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::videoSampleAvailable):
+        * testing/Internals.h:
+
 2021-09-24  Myles C. Maxfield  <[email protected]>
 
         Handle CSSOM style mutation of font-palette-values

Modified: trunk/Source/WebCore/page/Page.cpp (283032 => 283033)


--- trunk/Source/WebCore/page/Page.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/page/Page.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -2207,9 +2207,6 @@
 
 void Page::setMuted(MediaProducer::MutedStateFlags muted)
 {
-    if (m_mutedState == muted)
-        return;
-
     m_mutedState = muted;
 
     forEachDocument([] (Document& document) {

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (283032 => 283033)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -107,8 +107,11 @@
     // Changed m_muted before calling start/stop so muted() will reflect the correct state.
     bool changed = m_muted != muted;
 
-    if (changed)
-        ALWAYS_LOG_IF(m_logger, LOGIDENTIFIER, muted);
+    ALWAYS_LOG_IF(m_logger && changed, LOGIDENTIFIER, muted);
+    if (changed && !muted && m_isProducingData) {
+        // Let's uninterrupt by doing a stop/start cycle.
+        stop();
+    }
 
     m_muted = muted;
     if (muted)

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (283032 => 283033)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -311,6 +311,11 @@
     RealtimeMediaSourceCenter::singleton().captureDevicesChanged();
 }
 
+void MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    MockRealtimeVideoSource::setIsInterrupted(isInterrupted);
+}
+
 void MockRealtimeMediaSourceCenter::setDevices(Vector<MockMediaDevice>&& newMockDevices)
 {
     microphoneDevices().clear();

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h (283032 => 283033)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -47,6 +47,7 @@
     WEBCORE_EXPORT static void addDevice(const MockMediaDevice&);
     WEBCORE_EXPORT static void removeDevice(const String& persistentId);
     WEBCORE_EXPORT static void resetDevices();
+    WEBCORE_EXPORT static void setMockCameraIsInterrupted(bool);
 
     void setMockAudioCaptureEnabled(bool isEnabled) { m_isMockAudioCaptureEnabled = isEnabled; }
     void setMockVideoCaptureEnabled(bool isEnabled) { m_isMockVideoCaptureEnabled = isEnabled; }

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (283032 => 283033)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -67,10 +67,19 @@
 }
 #endif
 
+static HashSet<MockRealtimeVideoSource*>& allMockRealtimeVideoSource()
+{
+    static NeverDestroyed<HashSet<MockRealtimeVideoSource*>> videoSources;
+    return videoSources;
+}
+
 MockRealtimeVideoSource::MockRealtimeVideoSource(String&& deviceID, String&& name, String&& hashSalt)
     : RealtimeVideoCaptureSource(WTFMove(name), WTFMove(deviceID), WTFMove(hashSalt))
     , m_emitFrameTimer(RunLoop::current(), this, &MockRealtimeVideoSource::generateFrame)
 {
+    ASSERT(isMainThread());
+    allMockRealtimeVideoSource().add(this);
+
     auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(persistentID());
     ASSERT(device);
     m_device = *device;
@@ -93,6 +102,12 @@
     m_fillColor = properties.fillColor;
 }
 
+MockRealtimeVideoSource::~MockRealtimeVideoSource()
+{
+    ASSERT(isMainThread());
+    allMockRealtimeVideoSource().remove(this);
+}
+
 bool MockRealtimeVideoSource::supportsSizeAndFrameRate(std::optional<int> width, std::optional<int> height, std::optional<double> rate)
 {
     // FIXME: consider splitting mock display into another class so we don't don't have to do this silly dance
@@ -511,6 +526,19 @@
     orientationChanged(notifier.orientation());
 }
 
+void MockRealtimeVideoSource::setIsInterrupted(bool isInterrupted)
+{
+    for (auto* source : allMockRealtimeVideoSource()) {
+        if (!source->isProducingData())
+            continue;
+        if (isInterrupted)
+            source->m_emitFrameTimer.stop();
+        else
+            source->startCaptureTimer();
+        source->notifyMutedChange(isInterrupted);
+    }
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (283032 => 283033)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -49,7 +49,10 @@
 class MockRealtimeVideoSource : public RealtimeVideoCaptureSource, private OrientationNotifier::Observer {
 public:
     static CaptureSourceOrError create(String&& deviceID, String&& name, String&& hashSalt, const MediaConstraints*);
+    ~MockRealtimeVideoSource();
 
+    static void setIsInterrupted(bool);
+
     ImageBuffer* imageBuffer() const;
 
 protected:

Modified: trunk/Source/WebCore/testing/Internals.cpp (283032 => 283033)


--- trunk/Source/WebCore/testing/Internals.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/testing/Internals.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -5438,24 +5438,28 @@
 
 void Internals::videoSampleAvailable(MediaSample& sample)
 {
-    m_trackVideoSampleCount++;
-    if (!m_nextTrackFramePromise)
-        return;
+    callOnMainThread([this, weakThis = makeWeakPtr(this), sample = Ref { sample }] {
+        if (!weakThis)
+            return;
+        m_trackVideoSampleCount++;
+        if (!m_nextTrackFramePromise)
+            return;
 
-    auto& videoSettings = m_trackSource->settings();
-    if (!videoSettings.width() || !videoSettings.height())
-        return;
-    
-    auto rgba = sample.getRGBAImageData();
-    if (!rgba)
-        return;
-    
-    auto imageData = ImageData::create(rgba.releaseNonNull(), videoSettings.width(), videoSettings.height(), { { PredefinedColorSpace::SRGB } });
-    if (!imageData.hasException())
-        m_nextTrackFramePromise->resolve(imageData.releaseReturnValue());
-    else
-        m_nextTrackFramePromise->reject(imageData.exception().code());
-    m_nextTrackFramePromise = nullptr;
+        auto& videoSettings = m_trackSource->settings();
+        if (!videoSettings.width() || !videoSettings.height())
+            return;
+
+        auto rgba = sample->getRGBAImageData();
+        if (!rgba)
+            return;
+
+        auto imageData = ImageData::create(rgba.releaseNonNull(), videoSettings.width(), videoSettings.height(), { { PredefinedColorSpace::SRGB } });
+        if (!imageData.hasException())
+            m_nextTrackFramePromise->resolve(imageData.releaseReturnValue());
+        else
+            m_nextTrackFramePromise->reject(imageData.exception().code());
+        m_nextTrackFramePromise = nullptr;
+    });
 }
 
 void Internals::delayMediaStreamTrackSamples(MediaStreamTrack& track, float delay)

Modified: trunk/Source/WebCore/testing/Internals.h (283032 => 283033)


--- trunk/Source/WebCore/testing/Internals.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebCore/testing/Internals.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -148,7 +148,7 @@
 
 class Internals final : public RefCounted<Internals>, private ContextDestructionObserver
 #if ENABLE(MEDIA_STREAM)
-    , private RealtimeMediaSource::Observer
+    , public RealtimeMediaSource::Observer
     , private RealtimeMediaSource::AudioSampleObserver
     , private RealtimeMediaSource::VideoSampleObserver
 #endif

Modified: trunk/Source/WebKit/ChangeLog (283032 => 283033)


--- trunk/Source/WebKit/ChangeLog	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/ChangeLog	2021-09-24 09:39:18 UTC (rev 283033)
@@ -1,3 +1,32 @@
+2021-09-24  Youenn Fablet  <[email protected]>
+
+        [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+        https://bugs.webkit.org/show_bug.cgi?id=230538
+        <rdar://problem/83355705>
+
+        Reviewed by Eric Carlson.
+
+        Add support for mock capture interruption.
+        When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
+        In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
+        It is important to not stop the source so that it can continue receiving interruption notifications.
+
+        * GPUProcess/GPUProcess.cpp:
+        (WebKit::GPUProcess::setMockCameraIsInterrupted):
+        * GPUProcess/GPUProcess.h:
+        * GPUProcess/GPUProcess.messages.in:
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageIsMockRealtimeMediaSourceCenterEnabled):
+        (WKPageSetMockCameraIsInterrupted):
+        * UIProcess/API/C/WKPagePrivate.h:
+        * UIProcess/GPU/GPUProcessProxy.cpp:
+        (WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
+        * UIProcess/GPU/GPUProcessProxy.h:
+        * WebProcess/cocoa/RemoteRealtimeAudioSource.h:
+        * WebProcess/cocoa/RemoteRealtimeVideoSource.h:
+        * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+        (WebKit::UserMediaCaptureManager::sourceMutedChanged):
+
 2021-09-24  Sihui Liu  <[email protected]>
 
         Add initial support for File System Access API

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.cpp (283032 => 283033)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -343,6 +343,12 @@
 {
     MockRealtimeMediaSourceCenter::resetDevices();
 }
+
+void GPUProcess::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted(isInterrupted);
+}
+
 #endif
 
 #if PLATFORM(MAC)

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.h (283032 => 283033)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -131,6 +131,7 @@
     void clearMockMediaDevices();
     void removeMockMediaDevice(const String& persistentId);
     void resetMockMediaDevices();
+    void setMockCameraIsInterrupted(bool);
     bool setCaptureAttributionString(const String&);
 #endif
 #if PLATFORM(MAC)

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in (283032 => 283033)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in	2021-09-24 09:39:18 UTC (rev 283033)
@@ -43,6 +43,7 @@
     ClearMockMediaDevices();
     RemoveMockMediaDevice(String persistentId);
     ResetMockMediaDevices();
+    SetMockCameraIsInterrupted(bool isInterrupted);
 #endif
 #if PLATFORM(MAC)
     DisplayConfigurationChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags)

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp (283032 => 283033)


--- trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -3146,7 +3146,7 @@
 #endif
 }
 
-WK_EXPORT bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef)
+bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef)
 {
 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
     return MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled();
@@ -3155,6 +3155,15 @@
 #endif
 }
 
+void WKPageSetMockCameraIsInterrupted(WKPageRef pageRef, bool isInterrupted)
+{
+    CRASH_IF_SUSPENDED;
+#if ENABLE(MEDIA_STREAM) && ENABLE(GPU_PROCESS)
+    auto& gpuProcess = toImpl(pageRef)->process().processPool().ensureGPUProcess();
+    gpuProcess.setMockCameraIsInterrupted(isInterrupted);
+#endif
+}
+
 void WKPageLoadedSubresourceDomains(WKPageRef pageRef, WKPageLoadedSubresourceDomainsFunction callback, void* callbackContext)
 {
     CRASH_IF_SUSPENDED;

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h (283032 => 283033)


--- trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -195,6 +195,7 @@
 
 WK_EXPORT void WKPageSetMockCameraOrientation(WKPageRef page, uint64_t orientation);
 WK_EXPORT bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef page);
+WK_EXPORT void WKPageSetMockCameraIsInterrupted(WKPageRef page, bool isInterrupted);
 
 typedef void (*WKPageLoadedSubresourceDomainsFunction)(WKArrayRef domains, void* functionContext);
 WK_EXPORT void WKPageLoadedSubresourceDomains(WKPageRef page, WKPageLoadedSubresourceDomainsFunction callback, void* callbackContext);

Modified: trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp (283032 => 283033)


--- trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -310,6 +310,11 @@
 {
     send(Messages::GPUProcess::ResetMockMediaDevices { }, 0);
 }
+
+void GPUProcessProxy::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    send(Messages::GPUProcess::SetMockCameraIsInterrupted { isInterrupted }, 0);
+}
 #endif
 
 void GPUProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)

Modified: trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h (283032 => 283033)


--- trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -82,6 +82,7 @@
     void clearMockMediaDevices();
     void removeMockMediaDevice(const String&);
     void resetMockMediaDevices();
+    void setMockCameraIsInterrupted(bool);
 #endif
 
     void removeSession(PAL::SessionID);

Modified: trunk/Source/WebKit/WebProcess/cocoa/RemoteRealtimeAudioSource.h (283032 => 283033)


--- trunk/Source/WebKit/WebProcess/cocoa/RemoteRealtimeAudioSource.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/WebProcess/cocoa/RemoteRealtimeAudioSource.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -69,6 +69,7 @@
     void captureFailed() final;
 
     void remoteAudioSamplesAvailable(const MediaTime&, const WebCore::PlatformAudioData&, const WebCore::AudioStreamDescription&, size_t);
+    void sourceMutedChanged(bool value) { notifyMutedChange(value); }
 
 private:
     RemoteRealtimeAudioSource(WebCore::RealtimeMediaSourceIdentifier, const WebCore::CaptureDevice&, const WebCore::MediaConstraints*, String&& name, String&& hashSalt, UserMediaCaptureManager&, bool shouldCaptureInGPUProcess);

Modified: trunk/Source/WebKit/WebProcess/cocoa/RemoteRealtimeVideoSource.h (283032 => 283033)


--- trunk/Source/WebKit/WebProcess/cocoa/RemoteRealtimeVideoSource.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/WebProcess/cocoa/RemoteRealtimeVideoSource.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -67,6 +67,7 @@
     void captureFailed() final;
 
     void videoSampleAvailable(WebCore::MediaSample&, WebCore::IntSize);
+    void sourceMutedChanged(bool value) { notifyMutedChange(value); }
 
 private:
     RemoteRealtimeVideoSource(WebCore::RealtimeMediaSourceIdentifier, const WebCore::CaptureDevice&, const WebCore::MediaConstraints*, String&& name, String&& hashSalt, UserMediaCaptureManager&, bool shouldCaptureInGPUProcess);

Modified: trunk/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp (283032 => 283033)


--- trunk/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -137,9 +137,9 @@
 void UserMediaCaptureManager::sourceMutedChanged(RealtimeMediaSourceIdentifier id, bool muted)
 {
     if (auto source = m_audioSources.get(id))
-        source->setMuted(muted);
+        source->sourceMutedChanged(muted);
     else if (auto source = m_videoSources.get(id))
-        source->setMuted(muted);
+        source->sourceMutedChanged(muted);
 }
 
 void UserMediaCaptureManager::sourceSettingsChanged(RealtimeMediaSourceIdentifier id, RealtimeMediaSourceSettings&& settings)

Modified: trunk/Tools/ChangeLog (283032 => 283033)


--- trunk/Tools/ChangeLog	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Tools/ChangeLog	2021-09-24 09:39:18 UTC (rev 283033)
@@ -1,3 +1,23 @@
+2021-09-24  Youenn Fablet  <[email protected]>
+
+        [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+        https://bugs.webkit.org/show_bug.cgi?id=230538
+        <rdar://problem/83355705>
+
+        Reviewed by Eric Carlson.
+
+        Add mock API to mock camera interruption.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setMockCameraIsInterrupted):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::setMockCameraIsInterrupted):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2021-09-23  Andres Gonzalez  <[email protected]>
 
         Remove AXDRTElementIdAttribute from the AX object platform wrapper interface.

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (283032 => 283033)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2021-09-24 09:39:18 UTC (rev 283033)
@@ -383,6 +383,7 @@
     undefined resetMockMediaDevices();
     undefined setMockCameraOrientation(unsigned long orientation);
     boolean isMockRealtimeMediaSourceCenterEnabled();
+    undefined setMockCameraIsInterrupted(boolean isInterrupted);
 
     boolean hasAppBoundSession();
     undefined clearAppBoundSession();

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (283032 => 283033)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -1806,6 +1806,11 @@
     return postSynchronousMessageReturningBoolean("IsMockRealtimeMediaSourceCenterEnabled");
 }
 
+void TestRunner::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    postSynchronousMessage("SetMockCameraIsInterrupted", isInterrupted);
+}
+
 #if ENABLE(GAMEPAD)
 
 void TestRunner::connectMockGamepad(unsigned index)

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (283032 => 283033)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -495,6 +495,7 @@
     void resetMockMediaDevices();
     void setMockCameraOrientation(unsigned);
     bool isMockRealtimeMediaSourceCenterEnabled();
+    void setMockCameraIsInterrupted(bool);
 
     bool hasAppBoundSession();
     void clearAppBoundSession();

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (283032 => 283033)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -3511,6 +3511,11 @@
     return WKPageIsMockRealtimeMediaSourceCenterEnabled(m_mainWebView->page());
 }
 
+void TestController::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    WKPageSetMockCameraIsInterrupted(m_mainWebView->page(), isInterrupted);
+}
+
 struct InAppBrowserPrivacyCallbackContext {
     explicit InAppBrowserPrivacyCallbackContext(TestController& controller)
         : testController(controller)

Modified: trunk/Tools/WebKitTestRunner/TestController.h (283032 => 283033)


--- trunk/Tools/WebKitTestRunner/TestController.h	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2021-09-24 09:39:18 UTC (rev 283033)
@@ -307,6 +307,7 @@
     void resetMockMediaDevices();
     void setMockCameraOrientation(uint64_t);
     bool isMockRealtimeMediaSourceCenterEnabled() const;
+    void setMockCameraIsInterrupted(bool);
     bool hasAppBoundSession();
 
     void injectUserScript(WKStringRef);

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (283032 => 283033)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2021-09-24 09:38:48 UTC (rev 283032)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2021-09-24 09:39:18 UTC (rev 283033)
@@ -956,6 +956,11 @@
     if (WKStringIsEqualToUTF8CString(messageName, "IsMockRealtimeMediaSourceCenterEnabled"))
         return adoptWK(WKBooleanCreate(TestController::singleton().isMockRealtimeMediaSourceCenterEnabled()));
     
+    if (WKStringIsEqualToUTF8CString(messageName, "SetMockCameraIsInterrupted")) {
+        TestController::singleton().setMockCameraIsInterrupted(booleanValue(messageBody));
+        return nullptr;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "HasAppBoundSession"))
         return adoptWK(WKBooleanCreate(TestController::singleton().hasAppBoundSession()));
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to