<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[204118] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/204118">204118</a></dd>
<dt>Author</dt> <dd>alex@webkit.org</dd>
<dt>Date</dt> <dd>2016-08-04 02:26:16 -0700 (Thu, 04 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebRTC: OWR: Add support for the muted state in the mediaplayer
https://bugs.webkit.org/show_bug.cgi?id=160502

Modified the load, play and stop methods to handle the new
situation where the mediaSource could be empty, until the remote
side sends the information to create the receiver.

Reviewed by Philippe Normand.

No new tests, we need to upstream the owr endpoint to check this
situation.

* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.cpp:
(WebCore::MediaPlayerPrivateGStreamerOwr::play): Check the muted
state of the tracks if required, we do it using the new
maybeHandleChangeMutedState function.
(WebCore::MediaPlayerPrivateGStreamerOwr::load): Add always the
observer of the track to check when it is unmuted, and we delay
enabling/setting the source until the play or the unmute.
(WebCore::MediaPlayerPrivateGStreamerOwr::internalLoad): Removed,
we now do all in the load method.
(WebCore::MediaPlayerPrivateGStreamerOwr::stop): Remove the
mediasource when disabling. Removed the m_stopped state, it was
there because the internalLoad was called multiple times.
(WebCore::MediaPlayerPrivateGStreamerOwr::trackMutedChanged):
Check the muted state and handle it, we use the new method
maybeHandleChangeMutedState.
(WebCore::MediaPlayerPrivateGStreamerOwr::maybeHandleChangeMutedState):
Check if the track is muted or not, in case it is muted disable
the the renderer and remove its mediasource. If it is not muted
enable the renderer and set the mediasource.
(WebCore::MediaPlayerPrivateGStreamerOwr::createVideoSink): Move
the workaround for the renderer to this method when it is created.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.h:
Removed internalLoad method and the m_stopped attribute used to
call internalLoad multiple times.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerOwrcpp">trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerOwrh">trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (204117 => 204118)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-08-04 07:56:37 UTC (rev 204117)
+++ trunk/Source/WebCore/ChangeLog        2016-08-04 09:26:16 UTC (rev 204118)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2016-08-04  Alejandro G. Castro  &lt;alex@igalia.com&gt;
+
+        WebRTC: OWR: Add support for the muted state in the mediaplayer
+        https://bugs.webkit.org/show_bug.cgi?id=160502
+
+        Modified the load, play and stop methods to handle the new
+        situation where the mediaSource could be empty, until the remote
+        side sends the information to create the receiver.
+
+        Reviewed by Philippe Normand.
+
+        No new tests, we need to upstream the owr endpoint to check this
+        situation.
+
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerOwr::play): Check the muted
+        state of the tracks if required, we do it using the new
+        maybeHandleChangeMutedState function.
+        (WebCore::MediaPlayerPrivateGStreamerOwr::load): Add always the
+        observer of the track to check when it is unmuted, and we delay
+        enabling/setting the source until the play or the unmute.
+        (WebCore::MediaPlayerPrivateGStreamerOwr::internalLoad): Removed,
+        we now do all in the load method.
+        (WebCore::MediaPlayerPrivateGStreamerOwr::stop): Remove the
+        mediasource when disabling. Removed the m_stopped state, it was
+        there because the internalLoad was called multiple times.
+        (WebCore::MediaPlayerPrivateGStreamerOwr::trackMutedChanged):
+        Check the muted state and handle it, we use the new method
+        maybeHandleChangeMutedState.
+        (WebCore::MediaPlayerPrivateGStreamerOwr::maybeHandleChangeMutedState):
+        Check if the track is muted or not, in case it is muted disable
+        the the renderer and remove its mediasource. If it is not muted
+        enable the renderer and set the mediasource.
+        (WebCore::MediaPlayerPrivateGStreamerOwr::createVideoSink): Move
+        the workaround for the renderer to this method when it is created.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.h:
+        Removed internalLoad method and the m_stopped attribute used to
+        call internalLoad multiple times.
+
</ins><span class="cx"> 2016-08-04  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DocumentThreadableLoader should pass the fetch mode to underlying loader code
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerOwrcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.cpp (204117 => 204118)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.cpp        2016-08-04 07:56:37 UTC (rev 204117)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.cpp        2016-08-04 09:26:16 UTC (rev 204118)
</span><span class="lines">@@ -71,7 +71,17 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_paused = false;
</span><del>-    internalLoad();
</del><ins>+
+    GST_DEBUG(&quot;Connecting to live stream, descriptor: %p&quot;, m_streamPrivate.get());
+
+    for (auto track : m_streamPrivate-&gt;tracks()) {
+        if (!track-&gt;enabled()) {
+            GST_DEBUG(&quot;Track %s disabled&quot;, track-&gt;label().ascii().data());
+            continue;
+        }
+
+        maybeHandleChangeMutedState(*track);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateGStreamerOwr::pause()
</span><span class="lines">@@ -132,10 +142,10 @@
</span><span class="cx">     if (!initializeGStreamer())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (!m_videoSink)
</del><ins>+    if (streamPrivate.hasVideo() &amp;&amp; !m_videoSink)
</ins><span class="cx">         createVideoSink();
</span><span class="cx"> 
</span><del>-    if (!m_audioSink)
</del><ins>+    if (streamPrivate.hasAudio() &amp;&amp; !m_audioSink)
</ins><span class="cx">         createGSTAudioSinkBin();
</span><span class="cx"> 
</span><span class="cx">     GST_DEBUG(&quot;Loading MediaStreamPrivate %p&quot;, &amp;streamPrivate);
</span><span class="lines">@@ -151,48 +161,6 @@
</span><span class="cx">     m_player-&gt;networkStateChanged();
</span><span class="cx">     m_player-&gt;readyStateChanged();
</span><span class="cx"> 
</span><del>-    if (!internalLoad())
-        return;
-
-    // If the stream contains video, wait for first video frame before setting
-    // HaveEnoughData.
-    if (!hasVideo())
-        m_readyState = MediaPlayer::HaveEnoughData;
-
-    m_player-&gt;readyStateChanged();
-}
-
-void MediaPlayerPrivateGStreamerOwr::loadingFailed(MediaPlayer::NetworkState error)
-{
-    if (m_networkState != error) {
-        m_networkState = error;
-        m_player-&gt;networkStateChanged();
-    }
-    if (m_readyState != MediaPlayer::HaveNothing) {
-        m_readyState = MediaPlayer::HaveNothing;
-        m_player-&gt;readyStateChanged();
-    }
-}
-
-bool MediaPlayerPrivateGStreamerOwr::didLoadingProgress() const
-{
-    // FIXME: Implement loading progress support.
-    return true;
-}
-
-bool MediaPlayerPrivateGStreamerOwr::internalLoad()
-{
-    if (!m_stopped)
-        return false;
-
-    m_stopped = false;
-    if (!m_streamPrivate || !m_streamPrivate-&gt;active()) {
-        loadingFailed(MediaPlayer::NetworkError);
-        return false;
-    }
-
-    GST_DEBUG(&quot;Connecting to live stream, descriptor: %p&quot;, m_streamPrivate.get());
-
</del><span class="cx">     for (auto track : m_streamPrivate-&gt;tracks()) {
</span><span class="cx">         if (!track-&gt;enabled()) {
</span><span class="cx">             GST_DEBUG(&quot;Track %s disabled&quot;, track-&gt;label().ascii().data());
</span><span class="lines">@@ -199,27 +167,14 @@
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        OwrMediaSource* mediaSource = OWR_MEDIA_SOURCE(reinterpret_cast&lt;RealtimeMediaSourceOwr*&gt;(&amp;track-&gt;source())-&gt;mediaSource());
</del><ins>+        track-&gt;addObserver(*this);
</ins><span class="cx"> 
</span><span class="cx">         switch (track-&gt;type()) {
</span><span class="cx">         case RealtimeMediaSource::Audio:
</span><del>-            if (m_audioTrack &amp;&amp; (m_audioTrack.get() == track))
-                g_object_set(m_audioRenderer.get(), &quot;disabled&quot;, FALSE, nullptr);
-
-            owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_audioRenderer.get()), mediaSource);
</del><span class="cx">             m_audioTrack = track;
</span><del>-            track-&gt;addObserver(*this);
</del><span class="cx">             break;
</span><span class="cx">         case RealtimeMediaSource::Video:
</span><del>-            if (m_videoTrack &amp;&amp; (m_videoTrack.get() == track))
-                g_object_set(m_videoRenderer.get(), &quot;disabled&quot;, FALSE, nullptr);
-
-            // FIXME: Remove hardcoded video dimensions when the rendering performance:
-            // https://webkit.org/b/153826.
-            g_object_set(m_videoRenderer.get(), &quot;width&quot;, 640, &quot;height&quot;, 480, nullptr);
-            owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_videoRenderer.get()), mediaSource);
</del><span class="cx">             m_videoTrack = track;
</span><del>-            track-&gt;addObserver(*this);
</del><span class="cx">             break;
</span><span class="cx">         case RealtimeMediaSource::None:
</span><span class="cx">             GST_WARNING(&quot;Loading a track with None type&quot;);
</span><span class="lines">@@ -228,22 +183,37 @@
</span><span class="cx"> 
</span><span class="cx">     m_readyState = MediaPlayer::HaveEnoughData;
</span><span class="cx">     m_player-&gt;readyStateChanged();
</span><ins>+}
+
+void MediaPlayerPrivateGStreamerOwr::loadingFailed(MediaPlayer::NetworkState error)
+{
+    if (m_networkState != error) {
+        m_networkState = error;
+        m_player-&gt;networkStateChanged();
+    }
+    if (m_readyState != MediaPlayer::HaveNothing) {
+        m_readyState = MediaPlayer::HaveNothing;
+        m_player-&gt;readyStateChanged();
+    }
+}
+
+bool MediaPlayerPrivateGStreamerOwr::didLoadingProgress() const
+{
+    // FIXME: Implement loading progress support.
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateGStreamerOwr::stop()
</span><span class="cx"> {
</span><del>-    if (m_stopped)
-        return;
-
-    m_stopped = true;
</del><span class="cx">     if (m_audioTrack) {
</span><span class="cx">         GST_DEBUG(&quot;Stop: disconnecting audio&quot;);
</span><span class="cx">         g_object_set(m_audioRenderer.get(), &quot;disabled&quot;, TRUE, nullptr);
</span><ins>+        owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_audioRenderer.get()), nullptr);
</ins><span class="cx">     }
</span><span class="cx">     if (m_videoTrack) {
</span><span class="cx">         GST_DEBUG(&quot;Stop: disconnecting video&quot;);
</span><span class="cx">         g_object_set(m_videoRenderer.get(), &quot;disabled&quot;, TRUE, nullptr);
</span><ins>+        owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_videoRenderer.get()), nullptr);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -312,11 +282,42 @@
</span><span class="cx">         g_object_set(m_videoRenderer.get(), &quot;disabled&quot;, TRUE, nullptr);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateGStreamerOwr::trackMutedChanged(MediaStreamTrackPrivate&amp;)
</del><ins>+void MediaPlayerPrivateGStreamerOwr::trackMutedChanged(MediaStreamTrackPrivate&amp; track)
</ins><span class="cx"> {
</span><span class="cx">     GST_DEBUG(&quot;Track muted state changed&quot;);
</span><ins>+
+    maybeHandleChangeMutedState(track);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateGStreamerOwr::maybeHandleChangeMutedState(MediaStreamTrackPrivate&amp; track)
+{
+    auto realTimeMediaSource = reinterpret_cast&lt;RealtimeMediaSourceOwr*&gt;(&amp;track.source());
+    auto mediaSource = OWR_MEDIA_SOURCE(realTimeMediaSource-&gt;mediaSource());
+
+    switch (track.type()) {
+    case RealtimeMediaSource::Audio:
+        if (!realTimeMediaSource-&gt;muted()) {
+            g_object_set(m_audioRenderer.get(), &quot;disabled&quot;, false, nullptr);
+            owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_audioRenderer.get()), mediaSource);
+        } else {
+            g_object_set(m_audioRenderer.get(), &quot;disabled&quot;, true, nullptr);
+            owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_audioRenderer.get()), nullptr);
+        }
+        break;
+    case RealtimeMediaSource::Video:
+        if (!realTimeMediaSource-&gt;muted()) {
+            g_object_set(m_videoRenderer.get(), &quot;disabled&quot;, false, nullptr);
+            owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_videoRenderer.get()), mediaSource);
+        } else {
+            g_object_set(m_videoRenderer.get(), &quot;disabled&quot;, true, nullptr);
+            owr_media_renderer_set_source(OWR_MEDIA_RENDERER(m_videoRenderer.get()), nullptr);
+        }
+        break;
+    case RealtimeMediaSource::None:
+        GST_WARNING(&quot;Trying to change mute state of a track with None type&quot;);
+    }
+}
+
</ins><span class="cx"> void MediaPlayerPrivateGStreamerOwr::trackSettingsChanged(MediaStreamTrackPrivate&amp;)
</span><span class="cx"> {
</span><span class="cx">     GST_DEBUG(&quot;Track settings changed&quot;);
</span><span class="lines">@@ -331,6 +332,11 @@
</span><span class="cx"> {
</span><span class="cx">     GstElement* sink = MediaPlayerPrivateGStreamerBase::createVideoSink();
</span><span class="cx">     m_videoRenderer = adoptGRef(owr_gst_video_renderer_new(sink));
</span><ins>+
+    // FIXME: Remove hardcoded video dimensions when the rendering performance:
+    // https://webkit.org/b/153826.
+    g_object_set(m_videoRenderer.get(), &quot;width&quot;, 640, &quot;height&quot;, 480, nullptr);
+
</ins><span class="cx">     return sink;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerOwrh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.h (204117 => 204118)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.h        2016-08-04 07:56:37 UTC (rev 204117)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerOwr.h        2016-08-04 09:26:16 UTC (rev 204118)
</span><span class="lines">@@ -94,11 +94,10 @@
</span><span class="cx">     static bool initializeGStreamerAndGStreamerDebugging();
</span><span class="cx">     void createGSTAudioSinkBin();
</span><span class="cx">     void loadingFailed(MediaPlayer::NetworkState error);
</span><del>-    bool internalLoad();
</del><span class="cx">     void stop();
</span><ins>+    void maybeHandleChangeMutedState(MediaStreamTrackPrivate&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool m_paused { true };
</span><del>-    bool m_stopped { true };
</del><span class="cx">     RefPtr&lt;MediaStreamTrackPrivate&gt; m_videoTrack;
</span><span class="cx">     RefPtr&lt;MediaStreamTrackPrivate&gt; m_audioTrack;
</span><span class="cx">     GRefPtr&lt;GstElement&gt; m_audioSink;
</span></span></pre>
</div>
</div>

</body>
</html>