Skip to content

Commit

Permalink
When stopped, a cloned MediaStreamTrack will stop its base MediaStrea…
Browse files Browse the repository at this point in the history
…mTrack if the source is muted

https://bugs.webkit.org/show_bug.cgi?id=260655
rdar://111534033

Reviewed by Eric Carlson.

When we have two track clones, and the tracks are muted, stopping one of the track will end the other one.
This is due to the fact that when stopping a track, we request the source to end.
We then check each observer to know whether they are stopped, which is true when the track is muted.
We are adding a ended flag in UserMediaCaptureManagerProxy::SourceProxy and we rename preventSourceFromStopping in preventSourceFromEnding to clarify what we are doing.

* LayoutTests/fast/mediastream/stop-clone-when-muted-expected.txt: Added.
* LayoutTests/fast/mediastream/stop-clone-when-muted.html: Added.
* Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp:
(WebCore::MediaStreamTrackPrivate::preventSourceFromEnding):
(WebCore::MediaStreamTrackPrivate::preventSourceFromStopping): Deleted.
* Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h:
* Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::requestToEnd):
* Source/WebCore/platform/mediastream/RealtimeMediaSource.h:
* Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::end):
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::preventSourceFromEnding):
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::preventSourceFromStopping): Deleted.

Canonical link: https://commits.webkit.org/267247@main
  • Loading branch information
youennf committed Aug 24, 2023
1 parent 5033809 commit fc3228e
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

PASS Stopping a muted clone should not mute the track

31 changes: 31 additions & 0 deletions LayoutTests/fast/mediastream/stop-clone-when-muted.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
promise_test(async (test) => {
const stream = await navigator.mediaDevices.getUserMedia({ video:true });
const track = stream.getVideoTracks()[0];
const trackClone = track.clone();

const promise = new Promise(resolve => track.onmute = resolve);
if (window.internals) {
internals.setMediaStreamTrackMuted(track, true);
await promise;
}

const resultPromise = new Promise((resolve, reject) => {
setTimeout(resolve, 500);
track.onended = () => reject("track is ended");
});
trackClone.stop();

return resultPromise;
}, "Stopping a muted clone should not mute the track");
</script>
</head>
<body>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,11 @@ void MediaStreamTrackPrivate::sourceConfigurationChanged()
});
}

bool MediaStreamTrackPrivate::preventSourceFromStopping()
bool MediaStreamTrackPrivate::preventSourceFromEnding()
{
ALWAYS_LOG(LOGIDENTIFIER, m_isEnded);

// Do not allow the source to stop if we are still using it.
// Do not allow the source to end if we are still using it.
return !m_isEnded;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class MediaStreamTrackPrivate final
void sourceMutedChanged() final;
void sourceSettingsChanged() final;
void sourceConfigurationChanged() final;
bool preventSourceFromStopping() final;
bool preventSourceFromEnding() final;
void audioUnitWillStart() final;
void hasStartedProducingData() final;

Expand Down
8 changes: 4 additions & 4 deletions Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,12 +398,12 @@ void RealtimeMediaSource::stop()

void RealtimeMediaSource::requestToEnd(Observer& callingObserver)
{
bool hasObserverPreventingStopping = false;
bool hasObserverPreventingEnding = false;
forEachObserver([&](auto& observer) {
if (observer.preventSourceFromStopping())
hasObserverPreventingStopping = true;
if (observer.preventSourceFromEnding())
hasObserverPreventingEnding = true;
});
if (hasObserverPreventingStopping)
if (hasObserverPreventingEnding)
return;

ALWAYS_LOG_IF(m_logger, LOGIDENTIFIER);
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/platform/mediastream/RealtimeMediaSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class WEBCORE_EXPORT RealtimeMediaSource
virtual void sourceConfigurationChanged() { }

// Observer state queries.
virtual bool preventSourceFromStopping() { return false; }
virtual bool preventSourceFromEnding() { return false; }

virtual void hasStartedProducingData() { }
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class UserMediaCaptureManagerProxy::SourceProxy
void end()
{
m_isStopped = true;
m_isEnded = true;
m_source->requestToEnd(*this);
}

Expand Down Expand Up @@ -280,10 +281,10 @@ class UserMediaCaptureManagerProxy::SourceProxy
return m_rotationSession->rotate(videoFrame, rotation, ImageRotationSessionVT::IsCGImageCompatible::No);
}

bool preventSourceFromStopping()
bool preventSourceFromEnding()
{
// Do not allow the source to stop if we are still using it.
return !m_isStopped;
// Do not allow the source to end if we are still using it.
return !m_isEnded;
}

RealtimeMediaSourceIdentifier m_id;
Expand All @@ -294,6 +295,7 @@ class UserMediaCaptureManagerProxy::SourceProxy
std::unique_ptr<ProducerSharedCARingBuffer> m_ringBuffer;
std::optional<CAAudioStreamDescription> m_description;
bool m_isStopped { false };
bool m_isEnded { false };
std::unique_ptr<ImageRotationSessionVT> m_rotationSession;
bool m_shouldApplyRotation { false };
std::unique_ptr<IPC::Semaphore> m_captureSemaphore;
Expand Down

0 comments on commit fc3228e

Please sign in to comment.