Title: [212399] trunk
Revision
212399
Author
jer.no...@apple.com
Date
2017-02-15 14:44:25 -0800 (Wed, 15 Feb 2017)

Log Message

Disabled Media Sources should render black/silence
https://bugs.webkit.org/show_bug.cgi?id=168281
Source/WebCore:

Reviewed by Eric Carlson.

Test: webrtc/video-disabled-black.html

Pass the enabled flag setting down from the MediaStreamTrackPrivate to its underlying
source, including RealtimeMediaSource and RealtimeOutgoingAudio/VideoSource. When either
enabled is cleared or muted is set, generate empty (black or silent) media, as opposed to
pausing media or (worse) continuing to send generated media.

* platform/mediastream/MediaStreamTrackPrivate.cpp:
(WebCore::MediaStreamTrackPrivate::setEnabled):
(WebCore::MediaStreamTrackPrivate::sourceEnabledChanged):
* platform/mediastream/MediaStreamTrackPrivate.h:
* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::setEnabled):
* platform/mediastream/RealtimeMediaSource.h:
(WebCore::RealtimeMediaSource::enabled):
* platform/mediastream/mac/AudioTrackPrivateMediaStreamCocoa.h:
* platform/mediastream/mac/MockRealtimeAudioSourceMac.mm:
(WebCore::MockRealtimeAudioSourceMac::render):
* platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp:
(WebCore::RealtimeOutgoingAudioSource::sourceMutedChanged):
(WebCore::RealtimeOutgoingAudioSource::sourceEnabledChanged):
(WebCore::RealtimeOutgoingAudioSource::pullAudioData):
* platform/mediastream/mac/RealtimeOutgoingAudioSource.h:
* platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp:
(WebCore::RealtimeOutgoingVideoSource::sourceMutedChanged):
(WebCore::RealtimeOutgoingVideoSource::sourceEnabledChanged):
(WebCore::RealtimeOutgoingVideoSource::videoSampleAvailable):
* platform/mediastream/mac/RealtimeOutgoingVideoSource.h:
* platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSource::generateFrame):

LayoutTests:

<rdar://problem/30508003>

Reviewed by Eric Carlson.

* webrtc/video-disabled-black-expected.txt: Added.
* webrtc/video-disabled-black.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (212398 => 212399)


--- trunk/LayoutTests/ChangeLog	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/LayoutTests/ChangeLog	2017-02-15 22:44:25 UTC (rev 212399)
@@ -1,3 +1,14 @@
+2017-02-15  Jer Noble  <jer.no...@apple.com>
+
+        Disabled Media Sources should render black/silence
+        https://bugs.webkit.org/show_bug.cgi?id=168281
+        <rdar://problem/30508003>
+
+        Reviewed by Eric Carlson.
+
+        * webrtc/video-disabled-black-expected.txt: Added.
+        * webrtc/video-disabled-black.html: Added.
+
 2017-02-15  Ryan Haddad  <ryanhad...@apple.com>
 
         Remove ElCapitan flag from flaky test media/modern-media-controls/airplay-support/airplay-support.html.

Added: trunk/LayoutTests/webrtc/video-disabled-black-expected.txt (0 => 212399)


--- trunk/LayoutTests/webrtc/video-disabled-black-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webrtc/video-disabled-black-expected.txt	2017-02-15 22:44:25 UTC (rev 212399)
@@ -0,0 +1,4 @@
+
+
+PASS Disabled source exchange
+

Added: trunk/LayoutTests/webrtc/video-disabled-black.html (0 => 212399)


--- trunk/LayoutTests/webrtc/video-disabled-black.html	                        (rev 0)
+++ trunk/LayoutTests/webrtc/video-disabled-black.html	2017-02-15 22:44:25 UTC (rev 212399)
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Testing basic video exchange from offerer to receiver</title>
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <video id="video" autoplay=""></video>
+        <canvas id="canvas" width="640" height="480"></canvas>
+        <script src =""
+        <script>
+if (window.internals)
+    internals.useMockRTCPeerConnectionFactory("TwoRealPeerConnections");
+
+if (window.testRunner)
+    testRunner.setUserMediaPermission(true);
+
+video = document.getElementById("video");
+canvas = document.getElementById("canvas");
+// FIXME: We should use tracks
+
+function testImage()
+{
+    try {
+        canvas.width = video.videoWidth;
+        canvas.height = video.videoHeight;
+        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
+
+        imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
+        assert_true(imageData.data.every( (pixel, index) => {
+            if (index % 4 === 3)
+                return pixel === 255;
+            return pixel === 0;
+        }));
+
+        finishTest();
+    } catch(e) {
+        errorTest(e);
+    }
+}
+
+function testStream(stream)
+{
+    video.srcObject = stream;
+    stream.getTracks()[0].enabled = false;
+    // Video may play with black frames
+    video._onplay_ = setTimeout(() => {
+        testImage();
+    }, 1000);
+}
+
+var finishTest, errorTest;
+promise_test((test) => {
+    return navigator.mediaDevices.getUserMedia({ video: true}).then((stream) => {
+        return new Promise((resolve, reject) => {
+            finishTest = resolve;
+            errorTest = reject;
+            createConnections((firstConnection) => {
+                firstConnection.addStream(stream);
+            }, (secondConnection) => {
+                secondConnection._onaddstream_ = (streamEvent) => { testStream(streamEvent.stream); };
+            });
+        });
+    });
+}, "Disabled source exchange");
+        </script>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (212398 => 212399)


--- trunk/Source/WebCore/ChangeLog	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/ChangeLog	2017-02-15 22:44:25 UTC (rev 212399)
@@ -1,3 +1,41 @@
+2017-02-15  Jer Noble  <jer.no...@apple.com>
+
+        Disabled Media Sources should render black/silence
+        https://bugs.webkit.org/show_bug.cgi?id=168281
+
+        Reviewed by Eric Carlson.
+
+        Test: webrtc/video-disabled-black.html
+
+        Pass the enabled flag setting down from the MediaStreamTrackPrivate to its underlying
+        source, including RealtimeMediaSource and RealtimeOutgoingAudio/VideoSource. When either
+        enabled is cleared or muted is set, generate empty (black or silent) media, as opposed to
+        pausing media or (worse) continuing to send generated media.
+
+        * platform/mediastream/MediaStreamTrackPrivate.cpp:
+        (WebCore::MediaStreamTrackPrivate::setEnabled):
+        (WebCore::MediaStreamTrackPrivate::sourceEnabledChanged):
+        * platform/mediastream/MediaStreamTrackPrivate.h:
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::setEnabled):
+        * platform/mediastream/RealtimeMediaSource.h:
+        (WebCore::RealtimeMediaSource::enabled):
+        * platform/mediastream/mac/AudioTrackPrivateMediaStreamCocoa.h:
+        * platform/mediastream/mac/MockRealtimeAudioSourceMac.mm:
+        (WebCore::MockRealtimeAudioSourceMac::render):
+        * platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp:
+        (WebCore::RealtimeOutgoingAudioSource::sourceMutedChanged):
+        (WebCore::RealtimeOutgoingAudioSource::sourceEnabledChanged):
+        (WebCore::RealtimeOutgoingAudioSource::pullAudioData):
+        * platform/mediastream/mac/RealtimeOutgoingAudioSource.h:
+        * platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp:
+        (WebCore::RealtimeOutgoingVideoSource::sourceMutedChanged):
+        (WebCore::RealtimeOutgoingVideoSource::sourceEnabledChanged):
+        (WebCore::RealtimeOutgoingVideoSource::videoSampleAvailable):
+        * platform/mediastream/mac/RealtimeOutgoingVideoSource.h:
+        * platform/mock/MockRealtimeVideoSource.cpp:
+        (WebCore::MockRealtimeVideoSource::generateFrame):
+
 2017-02-15  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Editing history scripts should not add the contenteditable attribute or override key events

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2017-02-15 22:44:25 UTC (rev 212399)
@@ -100,6 +100,8 @@
     // Always update the enabled state regardless of the track being ended.
     m_isEnabled = enabled;
 
+    m_source->setEnabled(enabled);
+
     for (auto& observer : m_observers)
         observer->trackEnabledChanged(*this);
 }
@@ -186,6 +188,12 @@
         observer->trackMutedChanged(*this);
 }
 
+void MediaStreamTrackPrivate::sourceEnabledChanged()
+{
+    for (auto& observer : m_observers)
+        observer->trackEnabledChanged(*this);
+}
+
 void MediaStreamTrackPrivate::sourceSettingsChanged()
 {
     for (auto& observer : m_observers)

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2017-02-15 22:44:25 UTC (rev 212399)
@@ -98,6 +98,7 @@
     // RealtimeMediaSourceObserver
     void sourceStopped() final;
     void sourceMutedChanged() final;
+    void sourceEnabledChanged() final;
     void sourceSettingsChanged() final;
     bool preventSourceFromStopping() final;
     void videoSampleAvailable(MediaSample&) final;

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2017-02-15 22:44:25 UTC (rev 212399)
@@ -96,6 +96,20 @@
         observer->sourceMutedChanged();
 }
 
+void RealtimeMediaSource::setEnabled(bool enabled)
+{
+    if (m_stopped || m_enabled == enabled)
+        return;
+
+    m_enabled = enabled;
+
+    if (m_stopped)
+        return;
+
+    for (auto& observer : m_observers)
+        observer->sourceEnabledChanged();
+}
+
 void RealtimeMediaSource::settingsDidChange()
 {
     ASSERT(isMainThread());

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2017-02-15 22:44:25 UTC (rev 212399)
@@ -69,6 +69,7 @@
         // Source state changes.
         virtual void sourceStopped() = 0;
         virtual void sourceMutedChanged() = 0;
+        virtual void sourceEnabledChanged() = 0;
         virtual void sourceSettingsChanged() = 0;
 
         // Observer state queries.
@@ -117,6 +118,9 @@
     virtual bool muted() const { return m_muted; }
     virtual void setMuted(bool);
 
+    virtual bool enabled() const { return m_enabled; }
+    virtual void setEnabled(bool);
+
     virtual bool readonly() const;
     virtual void setReadonly(bool readonly) { m_readonly = readonly; }
 
@@ -190,6 +194,7 @@
     virtual void applySizeAndFrameRate(std::optional<int> width, std::optional<int> height, std::optional<double>);
 
     bool m_muted { false };
+    bool m_enabled { true };
 
 private:
     WeakPtr<RealtimeMediaSource> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }

Modified: trunk/Source/WebCore/platform/mediastream/mac/AudioTrackPrivateMediaStreamCocoa.h (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/mac/AudioTrackPrivateMediaStreamCocoa.h	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/mac/AudioTrackPrivateMediaStreamCocoa.h	2017-02-15 22:44:25 UTC (rev 212399)
@@ -64,6 +64,7 @@
     // RealtimeMediaSource::Observer
     void sourceStopped() final;
     void sourceMutedChanged()  final { }
+    void sourceEnabledChanged() final { }
     void sourceSettingsChanged() final { }
     bool preventSourceFromStopping() final { return false; }
     void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;

Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm	2017-02-15 22:44:25 UTC (rev 212399)
@@ -149,6 +149,9 @@
 
 void MockRealtimeAudioSourceMac::render(double delta)
 {
+    if (m_muted || !m_enabled)
+        return;
+
     static double theta;
     static const double frequencies[] = { 1500., 500. };
     static const double tau = 2 * M_PI;

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp	2017-02-15 22:44:25 UTC (rev 212399)
@@ -53,9 +53,16 @@
 
 void RealtimeOutgoingAudioSource::sourceMutedChanged()
 {
-    m_isMuted = m_audioSource->muted();
+    m_muted = m_audioSource->muted();
+    m_sampleConverter->setMuted(m_muted || !m_enabled);
 }
 
+void RealtimeOutgoingAudioSource::sourceEnabledChanged()
+{
+    m_enabled = m_audioSource->enabled();
+    m_sampleConverter->setMuted(m_muted || !m_enabled);
+}
+
 void RealtimeOutgoingAudioSource::audioSamplesAvailable(const MediaTime& time, const PlatformAudioData& audioData, const AudioStreamDescription& streamDescription, size_t sampleCount)
 {
     if (m_inputStreamDescription != streamDescription) {
@@ -86,8 +93,6 @@
 
     m_sampleConverter->pullAvalaibleSamplesAsChunks(bufferList, LibWebRTCAudioFormat::chunkSampleCount, m_startFrame, [this] {
         m_startFrame += LibWebRTCAudioFormat::chunkSampleCount;
-        if (m_isMuted)
-            return;
         for (auto sink : m_sinks)
             sink->OnData(m_audioBuffer.data(), LibWebRTCAudioFormat::sampleSize, LibWebRTCAudioFormat::sampleRate, m_inputStreamDescription.numberOfChannels(), LibWebRTCAudioFormat::chunkSampleCount);
     });

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.h (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.h	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.h	2017-02-15 22:44:25 UTC (rev 212399)
@@ -65,6 +65,7 @@
     // RealtimeMediaSource::Observer API
     void sourceStopped() final { }
     void sourceMutedChanged() final;
+    void sourceEnabledChanged() final;
     void sourceSettingsChanged() final { }
     bool preventSourceFromStopping() final { return false; }
     void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
@@ -79,7 +80,8 @@
 
     Vector<uint16_t> m_audioBuffer;
     uint64_t m_startFrame { 0 };
-    bool m_isMuted { false };
+    bool m_muted { false };
+    bool m_enabled { true };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp	2017-02-15 22:44:25 UTC (rev 212399)
@@ -44,6 +44,16 @@
     m_videoSource->addObserver(*this);
 }
 
+void RealtimeOutgoingVideoSource::sourceMutedChanged()
+{
+    m_muted = m_videoSource->muted();
+}
+
+void RealtimeOutgoingVideoSource::sourceEnabledChanged()
+{
+    m_enabled = m_videoSource->enabled();
+}
+
 bool RealtimeOutgoingVideoSource::GetStats(Stats*)
 {
     return false;
@@ -66,13 +76,7 @@
     if (!m_sinks.size())
         return;
 
-    ASSERT(sample.platformSample().type == PlatformSample::CMSampleBufferType);
-    auto pixelBuffer = static_cast<CVPixelBufferRef>(CMSampleBufferGetImageBuffer(sample.platformSample().sample.cmSampleBuffer));
-    auto pixelFormatType = CVPixelBufferGetPixelFormatType(pixelBuffer);
 
-    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
-    uint8_t* src = "" 0));
-
     // FIXME: Shouldn't we use RealtimeMediaSource::size()
     const auto& settings = m_videoSource->settings();
 
@@ -79,19 +83,30 @@
     // FIXME: We should not need to allocate one buffer per frame.
     auto dest = webrtc::I420Buffer::Create(settings.width(), settings.height());
 
-    if (pixelFormatType == kCVPixelFormatType_420YpCbCr8Planar) {
-        // We probably can memcpy the data directly
-        webrtc::ConvertToI420(webrtc::kI420, src, 0, 0, settings.width(), settings.height(), 0, webrtc::kVideoRotation_0, dest);
-    } else if (pixelFormatType == kCVPixelFormatType_32BGRA)
-        webrtc::ConvertToI420(webrtc::kARGB, src, 0, 0, settings.width(), settings.height(), 0, webrtc::kVideoRotation_0, dest);
-    else {
-        // FIXME: Mock source conversion works with kBGRA while regular camera works with kARGB
-        ASSERT(pixelFormatType == kCVPixelFormatType_32ARGB);
-        webrtc::ConvertToI420(webrtc::kBGRA, src, 0, 0, settings.width(), settings.height(), 0, webrtc::kVideoRotation_0, dest);
+    if (!m_muted && m_enabled) {
+        ASSERT(sample.platformSample().type == PlatformSample::CMSampleBufferType);
+        auto pixelBuffer = static_cast<CVPixelBufferRef>(CMSampleBufferGetImageBuffer(sample.platformSample().sample.cmSampleBuffer));
+        auto pixelFormatType = CVPixelBufferGetPixelFormatType(pixelBuffer);
+
+        CVPixelBufferLockBaseAddress(pixelBuffer, 0);
+        uint8_t* src = "" 0));
+
+        if (pixelFormatType == kCVPixelFormatType_420YpCbCr8Planar) {
+            // We probably can memcpy the data directly
+            webrtc::ConvertToI420(webrtc::kI420, src, 0, 0, settings.width(), settings.height(), 0, webrtc::kVideoRotation_0, dest);
+        } else if (pixelFormatType == kCVPixelFormatType_32BGRA)
+            webrtc::ConvertToI420(webrtc::kARGB, src, 0, 0, settings.width(), settings.height(), 0, webrtc::kVideoRotation_0, dest);
+        else {
+            // FIXME: Mock source conversion works with kBGRA while regular camera works with kARGB
+            ASSERT(pixelFormatType == kCVPixelFormatType_32ARGB);
+            webrtc::ConvertToI420(webrtc::kBGRA, src, 0, 0, settings.width(), settings.height(), 0, webrtc::kVideoRotation_0, dest);
+        }
+
+        CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
+    } else {
+        dest->SetToBlack();
     }
 
-    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
-
     webrtc::VideoFrame frame(dest, 0, 0,  webrtc::kVideoRotation_0);
     for (auto* sink : m_sinks)
         sink->OnFrame(frame);

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.h (212398 => 212399)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.h	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.h	2017-02-15 22:44:25 UTC (rev 212399)
@@ -68,12 +68,15 @@
     // RealtimeMediaSource::Observer API
     bool preventSourceFromStopping() final { return false; }
     void sourceStopped() final { }
-    void sourceMutedChanged() final { }
+    void sourceMutedChanged() final;
+    void sourceEnabledChanged() final;
     void sourceSettingsChanged() final { }
     void videoSampleAvailable(MediaSample&) final;
 
     Vector<rtc::VideoSinkInterface<webrtc::VideoFrame>*> m_sinks;
     Ref<RealtimeMediaSource> m_videoSource;
+    bool m_enabled { true };
+    bool m_muted { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (212398 => 212399)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2017-02-15 22:43:59 UTC (rev 212398)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2017-02-15 22:44:25 UTC (rev 212399)
@@ -333,9 +333,11 @@
     FloatRect frameRect(FloatPoint(), size);
     context.fillRect(FloatRect(FloatPoint(), size), Color::black);
 
-    drawText(context);
-    drawAnimation(context);
-    drawBoxes(context);
+    if (!m_muted && m_enabled) {
+        drawText(context);
+        drawAnimation(context);
+        drawBoxes(context);
+    }
 
     updateSampleBuffer();
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to