<!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>[208851] 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/208851">208851</a></dd>
<dt>Author</dt> <dd>eric.carlson@apple.com</dd>
<dt>Date</dt> <dd>2016-11-17 10:43:40 -0800 (Thu, 17 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MediaStream][Mac] Use AVCapturePreview object for camera/microphone rendering
https://bugs.webkit.org/show_bug.cgi?id=164837
&lt;rdar://problem/29297727&gt;

Reviewed by Jer Noble.

No new tests, the real capture devices can not be used in layout tests.

* WebCore.xcodeproj/project.pbxproj:

Drive-by fix: clear m_settingMediaStreamSrcObject when the media player is destroyed unless
that happens as a side effect of setting video.srcObject.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::setSrcObject):
(WebCore::HTMLMediaElement::clearMediaPlayer):
* html/HTMLMediaElement.h:

Add support for realtime media source that vend a preview interface, while keeping support
for those that do not (e.g. the mock capture devices).
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::isAvailable):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSampleBuffer):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::prepareVideoSampleBufferFromTrack):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::destroyLayer):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::play):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::pause):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::internalSetVolume):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateTracks):

* platform/mediastream/MediaStreamPrivate.cpp:
(WebCore::MediaStreamPrivate::platformLayer): Deleted, no longer used.
* platform/mediastream/MediaStreamPrivate.h:

Enable/disable the preview when available.
* platform/mediastream/MediaStreamTrackPrivate.cpp:
(WebCore::MediaStreamTrackPrivate::setEnabled):
(WebCore::MediaStreamTrackPrivate::endTrack):
(WebCore::MediaStreamTrackPrivate::preview):
* platform/mediastream/MediaStreamTrackPrivate.h:

* platform/mediastream/RealtimeMediaSource.h:
(WebCore::RealtimeMediaSource::preview):
(WebCore::RealtimeMediaSource::createWeakPtr):
(WebCore::RealtimeMediaSource::platformLayer): Deleted.

Define a realtime media source preview interface.
* platform/mediastream/RealtimeMediaSourcePreview.h: Added.
(WebCore::RealtimeMediaSourcePreview::~RealtimeMediaSourcePreview):
(WebCore::RealtimeMediaSourcePreview::invalidate):
(WebCore::RealtimeMediaSourcePreview::createWeakPtr):
(WebCore::RealtimeMediaSourcePreview::RealtimeMediaSourcePreview):

Implement the preview interface.
* platform/mediastream/mac/AVAudioCaptureSource.h:
* platform/mediastream/mac/AVAudioCaptureSource.mm:
(WebCore::AVAudioSourcePreview::create):
(WebCore::AVAudioSourcePreview::AVAudioSourcePreview):
(WebCore::AVAudioSourcePreview::invalidate):
(WebCore::AVAudioSourcePreview::play):
(WebCore::AVAudioSourcePreview::pause):
(WebCore::AVAudioSourcePreview::setEnabled):
(WebCore::AVAudioSourcePreview::setVolume):
(WebCore::AVAudioSourcePreview::updateState):
(WebCore::AVAudioCaptureSource::createPreview):
* platform/mediastream/mac/AVMediaCaptureSource.h:
(WebCore::AVMediaCaptureSource::createWeakPtr):
* platform/mediastream/mac/AVMediaCaptureSource.mm:
(WebCore::AVMediaCaptureSource::AVMediaCaptureSource):
(WebCore::AVMediaCaptureSource::reset):
(WebCore::AVMediaCaptureSource::preview):
(WebCore::AVMediaCaptureSource::removePreview):
(WebCore::AVMediaSourcePreview::AVMediaSourcePreview):
(WebCore::AVMediaSourcePreview::~AVMediaSourcePreview):
(WebCore::AVMediaSourcePreview::invalidate):
* platform/mediastream/mac/AVVideoCaptureSource.h:
* platform/mediastream/mac/AVVideoCaptureSource.mm:
(WebCore::AVVideoSourcePreview::create):
(WebCore::AVVideoSourcePreview::AVVideoSourcePreview):
(WebCore::AVVideoSourcePreview::invalidate):
(WebCore::AVVideoSourcePreview::play):
(WebCore::AVVideoSourcePreview::pause):
(WebCore::AVVideoSourcePreview::setPaused):
(WebCore::AVVideoSourcePreview::setEnabled):
(WebCore::AVVideoCaptureSource::shutdownCaptureSession):
(WebCore::AVVideoCaptureSource::processNewFrame):
(WebCore::AVVideoCaptureSource::createPreview):
(WebCore::AVVideoCaptureSource::platformLayer): Deleted.

* platform/mediastream/mac/MockRealtimeVideoSourceMac.h:
* platform/mediastream/mac/MockRealtimeVideoSourceMac.mm:
(WebCore::MockRealtimeVideoSourceMac::platformLayer): Deleted.
(WebCore::MockRealtimeVideoSourceMac::updatePlatformLayer): Deleted.
* platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSource::applyFrameRate):
(WebCore::MockRealtimeVideoSource::applySize):
(WebCore::MockRealtimeVideoSource::generateFrame):
* platform/mock/MockRealtimeVideoSource.h:
(WebCore::MockRealtimeVideoSource::updatePlatformLayer): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementcpp">trunk/Source/WebCore/html/HTMLMediaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementh">trunk/Source/WebCore/html/HTMLMediaElement.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaStreamAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaStreamAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaStreamPrivatecpp">trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaStreamPrivateh">trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaStreamTrackPrivatecpp">trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaStreamTrackPrivateh">trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceh">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVAudioCaptureSourceh">trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVAudioCaptureSourcemm">trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVMediaCaptureSourceh">trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVMediaCaptureSourcemm">trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourceh">trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourcemm">trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacMockRealtimeVideoSourceMach">trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacMockRealtimeVideoSourceMacmm">trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeVideoSourcecpp">trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeVideoSourceh">trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcePreviewh">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/ChangeLog        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -1,3 +1,109 @@
</span><ins>+2016-11-17  Eric Carlson  &lt;eric.carlson@apple.com&gt;
+
+        [MediaStream][Mac] Use AVCapturePreview object for camera/microphone rendering
+        https://bugs.webkit.org/show_bug.cgi?id=164837
+        &lt;rdar://problem/29297727&gt;
+
+        Reviewed by Jer Noble.
+
+        No new tests, the real capture devices can not be used in layout tests.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        
+        Drive-by fix: clear m_settingMediaStreamSrcObject when the media player is destroyed unless
+        that happens as a side effect of setting video.srcObject.
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::setSrcObject):
+        (WebCore::HTMLMediaElement::clearMediaPlayer):
+        * html/HTMLMediaElement.h:
+
+        Add support for realtime media source that vend a preview interface, while keeping support
+        for those that do not (e.g. the mock capture devices).
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::isAvailable):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSampleBuffer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::prepareVideoSampleBufferFromTrack):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::destroyLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::play):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::pause):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::internalSetVolume):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateTracks):
+
+        * platform/mediastream/MediaStreamPrivate.cpp:
+        (WebCore::MediaStreamPrivate::platformLayer): Deleted, no longer used.
+        * platform/mediastream/MediaStreamPrivate.h:
+
+        Enable/disable the preview when available.
+        * platform/mediastream/MediaStreamTrackPrivate.cpp:
+        (WebCore::MediaStreamTrackPrivate::setEnabled):
+        (WebCore::MediaStreamTrackPrivate::endTrack):
+        (WebCore::MediaStreamTrackPrivate::preview):
+        * platform/mediastream/MediaStreamTrackPrivate.h:
+
+        * platform/mediastream/RealtimeMediaSource.h:
+        (WebCore::RealtimeMediaSource::preview):
+        (WebCore::RealtimeMediaSource::createWeakPtr):
+        (WebCore::RealtimeMediaSource::platformLayer): Deleted.
+
+        Define a realtime media source preview interface.
+        * platform/mediastream/RealtimeMediaSourcePreview.h: Added.
+        (WebCore::RealtimeMediaSourcePreview::~RealtimeMediaSourcePreview):
+        (WebCore::RealtimeMediaSourcePreview::invalidate):
+        (WebCore::RealtimeMediaSourcePreview::createWeakPtr):
+        (WebCore::RealtimeMediaSourcePreview::RealtimeMediaSourcePreview):
+
+        Implement the preview interface.
+        * platform/mediastream/mac/AVAudioCaptureSource.h:
+        * platform/mediastream/mac/AVAudioCaptureSource.mm:
+        (WebCore::AVAudioSourcePreview::create):
+        (WebCore::AVAudioSourcePreview::AVAudioSourcePreview):
+        (WebCore::AVAudioSourcePreview::invalidate):
+        (WebCore::AVAudioSourcePreview::play):
+        (WebCore::AVAudioSourcePreview::pause):
+        (WebCore::AVAudioSourcePreview::setEnabled):
+        (WebCore::AVAudioSourcePreview::setVolume):
+        (WebCore::AVAudioSourcePreview::updateState):
+        (WebCore::AVAudioCaptureSource::createPreview):
+        * platform/mediastream/mac/AVMediaCaptureSource.h:
+        (WebCore::AVMediaCaptureSource::createWeakPtr):
+        * platform/mediastream/mac/AVMediaCaptureSource.mm:
+        (WebCore::AVMediaCaptureSource::AVMediaCaptureSource):
+        (WebCore::AVMediaCaptureSource::reset):
+        (WebCore::AVMediaCaptureSource::preview):
+        (WebCore::AVMediaCaptureSource::removePreview):
+        (WebCore::AVMediaSourcePreview::AVMediaSourcePreview):
+        (WebCore::AVMediaSourcePreview::~AVMediaSourcePreview):
+        (WebCore::AVMediaSourcePreview::invalidate):
+        * platform/mediastream/mac/AVVideoCaptureSource.h:
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        (WebCore::AVVideoSourcePreview::create):
+        (WebCore::AVVideoSourcePreview::AVVideoSourcePreview):
+        (WebCore::AVVideoSourcePreview::invalidate):
+        (WebCore::AVVideoSourcePreview::play):
+        (WebCore::AVVideoSourcePreview::pause):
+        (WebCore::AVVideoSourcePreview::setPaused):
+        (WebCore::AVVideoSourcePreview::setEnabled):
+        (WebCore::AVVideoCaptureSource::shutdownCaptureSession):
+        (WebCore::AVVideoCaptureSource::processNewFrame):
+        (WebCore::AVVideoCaptureSource::createPreview):
+        (WebCore::AVVideoCaptureSource::platformLayer): Deleted.
+
+        * platform/mediastream/mac/MockRealtimeVideoSourceMac.h:
+        * platform/mediastream/mac/MockRealtimeVideoSourceMac.mm:
+        (WebCore::MockRealtimeVideoSourceMac::platformLayer): Deleted.
+        (WebCore::MockRealtimeVideoSourceMac::updatePlatformLayer): Deleted.
+        * platform/mock/MockRealtimeVideoSource.cpp:
+        (WebCore::MockRealtimeVideoSource::applyFrameRate):
+        (WebCore::MockRealtimeVideoSource::applySize):
+        (WebCore::MockRealtimeVideoSource::generateFrame):
+        * platform/mock/MockRealtimeVideoSource.h:
+        (WebCore::MockRealtimeVideoSource::updatePlatformLayer): Deleted.
+
</ins><span class="cx"> 2016-11-17  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, fix build after r208839.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -305,6 +305,7 @@
</span><span class="cx">                 07C59B6917F784BA000FBCBB /* MediaSourceSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C59B6617F784BA000FBCBB /* MediaSourceSettings.h */; };
</span><span class="cx">                 07C59B6E17F794F6000FBCBB /* JSMediaStreamTrackCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C59B6D17F794F6000FBCBB /* JSMediaStreamTrackCustom.cpp */; };
</span><span class="cx">                 07CE77D516712A6A00C55A47 /* InbandTextTrackPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                07D1503B1DDB6965008F7598 /* RealtimeMediaSourcePreview.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 07D637401BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */; };
</span><span class="cx">                 07D637411BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */; };
</span><span class="cx">                 07D6A4EF1BECF2D200174146 /* MockRealtimeMediaSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */; };
</span><span class="lines">@@ -7262,6 +7263,7 @@
</span><span class="cx">                 07C8AD111D073D630087C5CE /* AVFoundationMIMETypeCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AVFoundationMIMETypeCache.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 07C8AD121D073D630087C5CE /* AVFoundationMIMETypeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVFoundationMIMETypeCache.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeMediaSourcePreview.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebAudioSourceProviderAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebAudioSourceProviderAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockRealtimeMediaSource.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15104,6 +15106,7 @@
</span><span class="cx">                 07221B9217CF0AD400848E51 /* mediastream */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */,
</ins><span class="cx">                                 0729B14D17CFCCA0004F1D60 /* mac */,
</span><span class="cx">                                 07D6A4F61BF2307D00174146 /* AudioTrackPrivateMediaStream.h */,
</span><span class="cx">                                 07B7116A1D899E63009F0FFB /* CaptureDevice.h */,
</span><span class="lines">@@ -28149,6 +28152,7 @@
</span><span class="cx">                                 1411DCB1164C39A800D49BC1 /* WidthCache.h in Headers */,
</span><span class="cx">                                 939B02EF0EA2DBC400C54570 /* WidthIterator.h in Headers */,
</span><span class="cx">                                 0F15ED5C1B7EC7C500EDDFEB /* WillChangeData.h in Headers */,
</span><ins>+                                07D1503B1DDB6965008F7598 /* RealtimeMediaSourcePreview.h in Headers */,
</ins><span class="cx">                                 BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */,
</span><span class="cx">                                 7E99AF530B13846468FB01A5 /* WindowFocusAllowedIndicator.h in Headers */,
</span><span class="cx">                                 E1E1BF00115FF6FB006F52CA /* WindowsKeyboardCodes.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -1048,8 +1048,11 @@
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=124896
</span><span class="cx"> 
</span><span class="cx">     m_mediaStreamSrcObject = mediaStream;
</span><del>-    if (mediaStream)
</del><ins>+    if (mediaStream) {
+        m_settingMediaStreamSrcObject = true;
</ins><span class="cx">         setSrc(DOMURL::createPublicURL(context, *mediaStream));
</span><ins>+        m_settingMediaStreamSrcObject = false;
+    }
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -4983,6 +4986,11 @@
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::clearMediaPlayer(%p) - flags = %s&quot;, this, actionName(flags).utf8().data());
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_STREAM)
+    if (!m_settingMediaStreamSrcObject)
+        m_mediaStreamSrcObject = nullptr;
+#endif
+
</ins><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><span class="cx">     detachMediaSource();
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -1023,6 +1023,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx">     RefPtr&lt;MediaStream&gt; m_mediaStreamSrcObject;
</span><ins>+    bool m_settingMediaStreamSrcObject { false };
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaStreamAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -186,11 +186,19 @@
</span><span class="cx">     void setVideoFullscreenFrame(FloatRect) override;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    bool haveVideoLayer() const { return m_sampleBufferDisplayLayer || m_videoPreviewPlayer; }
+
</ins><span class="cx">     MediaPlayer* m_player { nullptr };
</span><span class="cx">     WeakPtrFactory&lt;MediaPlayerPrivateMediaStreamAVFObjC&gt; m_weakPtrFactory;
</span><span class="cx">     RefPtr&lt;MediaStreamPrivate&gt; m_mediaStreamPrivate;
</span><ins>+
+    RefPtr&lt;RealtimeMediaSourcePreview&gt; m_videoPreviewPlayer;
+    RefPtr&lt;MediaStreamTrackPrivate&gt; m_videoTrack;
+
</ins><span class="cx">     RetainPtr&lt;AVSampleBufferDisplayLayer&gt; m_sampleBufferDisplayLayer;
</span><ins>+#if PLATFORM(MAC)
</ins><span class="cx">     RetainPtr&lt;AVSampleBufferRenderSynchronizer&gt; m_synchronizer;
</span><ins>+#endif
</ins><span class="cx">     RetainPtr&lt;CGImageRef&gt; m_pausedImage;
</span><span class="cx">     double m_pausedTime { 0 };
</span><span class="cx">     std::unique_ptr&lt;Clock&gt; m_clock;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaStreamAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -28,9 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><del>-#import &quot;AVAudioCaptureSource.h&quot;
</del><span class="cx"> #import &quot;AVFoundationSPI.h&quot;
</span><del>-#import &quot;AVVideoCaptureSource.h&quot;
</del><span class="cx"> #import &quot;AudioTrackPrivateMediaStream.h&quot;
</span><span class="cx"> #import &quot;Clock.h&quot;
</span><span class="cx"> #import &quot;GraphicsContext.h&quot;
</span><span class="lines">@@ -66,7 +64,6 @@
</span><span class="cx"> MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC(MediaPlayer* player)
</span><span class="cx">     : m_player(player)
</span><span class="cx">     , m_weakPtrFactory(this)
</span><del>-    , m_synchronizer(adoptNS([allocAVSampleBufferRenderSynchronizerInstance() init]))
</del><span class="cx">     , m_clock(Clock::create())
</span><span class="cx"> #if PLATFORM(MAC) &amp;&amp; ENABLE(VIDEO_PRESENTATION_MODE)
</span><span class="cx">     , m_videoFullscreenLayerManager(VideoFullscreenLayerManager::create())
</span><span class="lines">@@ -103,7 +100,15 @@
</span><span class="cx"> 
</span><span class="cx"> bool MediaPlayerPrivateMediaStreamAVFObjC::isAvailable()
</span><span class="cx"> {
</span><del>-    return AVFoundationLibrary() &amp;&amp; isCoreMediaFrameworkAvailable() &amp;&amp; getAVSampleBufferDisplayLayerClass() &amp;&amp; getAVSampleBufferRenderSynchronizerClass();
</del><ins>+    if (!AVFoundationLibrary() || !isCoreMediaFrameworkAvailable() || !getAVSampleBufferDisplayLayerClass())
+        return false;
+
+#if PLATFORM(MAC)
+    if (!getAVSampleBufferRenderSynchronizerClass())
+        return false;
+#endif
+
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::getSupportedTypes(HashSet&lt;String, ASCIICaseInsensitiveHash&gt;&amp; types)
</span><span class="lines">@@ -147,11 +152,17 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSampleBuffer(MediaSample&amp; sample)
</span><span class="cx"> {
</span><del>-    ASSERT([m_sampleBufferDisplayLayer isReadyForMoreMediaData]);
</del><ins>+    if (m_sampleBufferDisplayLayer) {
+        if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
+            m_sampleQueue.append(sample);
+            requestNotificationWhenReadyForMediaData();
+            return;
+        }
</ins><span class="cx"> 
</span><del>-    [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
</del><ins>+        [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
+    }
+
</ins><span class="cx">     m_isFrameDisplayed = true;
</span><del>-
</del><span class="cx">     if (!m_hasEverEnqueuedVideoFrame) {
</span><span class="cx">         m_hasEverEnqueuedVideoFrame = true;
</span><span class="cx">         m_player-&gt;firstVideoFrameAvailable();
</span><span class="lines">@@ -164,12 +175,6 @@
</span><span class="cx">     if (&amp;track != m_mediaStreamPrivate-&gt;activeVideoTrack() || !shouldEnqueueVideoSampleBuffer())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
-        m_sampleQueue.append(sample);
-        requestNotificationWhenReadyForMediaData();
-        return;
-    }
-
</del><span class="cx">     enqueueVideoSampleBuffer(sample);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -192,37 +197,56 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer()
</span><span class="cx"> {
</span><del>-    if (m_sampleBufferDisplayLayer)
</del><ins>+    if (haveVideoLayer())
</ins><span class="cx">         return;
</span><del>-    
-    m_sampleBufferDisplayLayer = adoptNS([allocAVSampleBufferDisplayLayerInstance() init]);
</del><ins>+
+    CALayer *videoLayer = nil;
+    if (m_mediaStreamPrivate-&gt;activeVideoTrack()) {
+        m_videoPreviewPlayer = m_mediaStreamPrivate-&gt;activeVideoTrack()-&gt;preview();
+        if (m_videoPreviewPlayer)
+            videoLayer = m_videoPreviewPlayer-&gt;platformLayer();
+    }
+
+    if (!videoLayer) {
+        m_sampleBufferDisplayLayer = adoptNS([allocAVSampleBufferDisplayLayerInstance() init]);
+        videoLayer = m_sampleBufferDisplayLayer.get();
</ins><span class="cx"> #ifndef NDEBUG
</span><del>-    [m_sampleBufferDisplayLayer setName:@&quot;MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer&quot;];
</del><ins>+        [m_sampleBufferDisplayLayer setName:@&quot;MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer&quot;];
</ins><span class="cx"> #endif
</span><del>-    m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
</del><ins>+        m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
</ins><span class="cx"> 
</span><del>-    [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
</del><ins>+#if PLATFORM(MAC)
+        m_synchronizer = adoptNS([allocAVSampleBufferRenderSynchronizerInstance() init]);
+        [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
+#endif
+    }
</ins><span class="cx"> 
</span><span class="cx">     renderingModeChanged();
</span><span class="cx">     
</span><span class="cx"> #if PLATFORM(MAC) &amp;&amp; ENABLE(VIDEO_PRESENTATION_MODE)
</span><del>-    m_videoFullscreenLayerManager-&gt;setVideoLayer(m_sampleBufferDisplayLayer.get(), snappedIntRect(m_player-&gt;client().mediaPlayerContentBoxRect()).size());
</del><ins>+    m_videoFullscreenLayerManager-&gt;setVideoLayer(videoLayer, snappedIntRect(m_player-&gt;client().mediaPlayerContentBoxRect()).size());
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::destroyLayer()
</span><span class="cx"> {
</span><del>-    if (!m_sampleBufferDisplayLayer)
</del><ins>+    if (!haveVideoLayer())
</ins><span class="cx">         return;
</span><del>-    
-    [m_sampleBufferDisplayLayer stopRequestingMediaData];
-    [m_sampleBufferDisplayLayer flush];
-    CMTime currentTime = CMTimebaseGetTime([m_synchronizer timebase]);
-    [m_synchronizer removeRenderer:m_sampleBufferDisplayLayer.get() atTime:currentTime withCompletionHandler:^(BOOL){
-        // No-op.
-    }];
-    m_sampleBufferDisplayLayer = nullptr;
</del><span class="cx"> 
</span><ins>+    m_videoPreviewPlayer = nullptr;
+
+    if (m_sampleBufferDisplayLayer) {
+        [m_sampleBufferDisplayLayer stopRequestingMediaData];
+        [m_sampleBufferDisplayLayer flush];
+#if PLATFORM(MAC)
+        CMTime currentTime = CMTimebaseGetTime([m_synchronizer timebase]);
+        [m_synchronizer removeRenderer:m_sampleBufferDisplayLayer.get() atTime:currentTime withCompletionHandler:^(BOOL) {
+            // No-op.
+        }];
+        m_sampleBufferDisplayLayer = nullptr;
+#endif
+    }
+
</ins><span class="cx">     renderingModeChanged();
</span><span class="cx">     
</span><span class="cx"> #if PLATFORM(MAC) &amp;&amp; ENABLE(VIDEO_PRESENTATION_MODE)
</span><span class="lines">@@ -282,12 +306,15 @@
</span><span class="cx"> 
</span><span class="cx"> PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
</span><span class="cx"> {
</span><del>-    if (!m_sampleBufferDisplayLayer || m_displayMode == None)
</del><ins>+    if (!haveVideoLayer() || m_displayMode == None)
</ins><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC) &amp;&amp; ENABLE(VIDEO_PRESENTATION_MODE)
</span><span class="cx">     return m_videoFullscreenLayerManager-&gt;videoInlineLayer();
</span><span class="cx"> #else
</span><ins>+    if (m_videoPreviewPlayer)
+        return m_videoPreviewPlayer-&gt;platformLayer();
+
</ins><span class="cx">     return m_sampleBufferDisplayLayer.get();
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="lines">@@ -294,7 +321,7 @@
</span><span class="cx"> 
</span><span class="cx"> MediaPlayerPrivateMediaStreamAVFObjC::DisplayMode MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode() const
</span><span class="cx"> {
</span><del>-    if (m_ended || m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)
</del><ins>+    if (m_ended || m_intrinsicSize.isEmpty() || !metaDataAvailable() || !haveVideoLayer())
</ins><span class="cx">         return None;
</span><span class="cx"> 
</span><span class="cx">     if (m_mediaStreamPrivate-&gt;activeVideoTrack() &amp;&amp; !m_mediaStreamPrivate-&gt;activeVideoTrack()-&gt;enabled())
</span><span class="lines">@@ -344,7 +371,21 @@
</span><span class="cx"> 
</span><span class="cx">     m_clock-&gt;start();
</span><span class="cx">     m_playing = true;
</span><del>-    [m_synchronizer setRate:1];
</del><ins>+
+    if (m_videoPreviewPlayer)
+        m_videoPreviewPlayer-&gt;play();
+#if PLATFORM(MAC)
+    else
+        [m_synchronizer setRate:1];
+#endif
+
+    for (const auto&amp; track : m_audioTrackMap.values()) {
+        if (!track-&gt;enabled() || !track-&gt;streamTrack()-&gt;preview())
+            continue;
+
+        track-&gt;streamTrack()-&gt;preview()-&gt;play();
+    }
+
</ins><span class="cx">     m_haveEverPlayed = true;
</span><span class="cx">     scheduleDeferredTask([this] {
</span><span class="cx">         updateDisplayMode();
</span><span class="lines">@@ -361,7 +402,21 @@
</span><span class="cx"> 
</span><span class="cx">     m_pausedTime = m_clock-&gt;currentTime();
</span><span class="cx">     m_playing = false;
</span><del>-    [m_synchronizer setRate:0];
</del><ins>+
+    if (m_videoPreviewPlayer)
+        m_videoPreviewPlayer-&gt;pause();
+#if PLATFORM(MAC)
+    else
+        [m_synchronizer setRate:0];
+#endif
+
+    for (const auto&amp; track : m_audioTrackMap.values()) {
+        if (!track-&gt;enabled() || !track-&gt;streamTrack()-&gt;preview())
+            continue;
+
+        track-&gt;streamTrack()-&gt;preview()-&gt;pause();
+    }
+
</ins><span class="cx">     updateDisplayMode();
</span><span class="cx">     updatePausedImage();
</span><span class="cx"> }
</span><span class="lines">@@ -379,7 +434,12 @@
</span><span class="cx">     if (!metaDataAvailable())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    // FIXME: Set volume once we actually play audio.
</del><ins>+    for (const auto&amp; track : m_audioTrackMap.values()) {
+        if (!track-&gt;enabled() || !track-&gt;streamTrack()-&gt;preview())
+            continue;
+
+        track-&gt;streamTrack()-&gt;preview()-&gt;setVolume(volume);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::setVolume(float volume)
</span><span class="lines">@@ -627,9 +687,10 @@
</span><span class="cx">     std::function&lt;void(RefPtr&lt;VideoTrackPrivateMediaStream&gt;, int)&gt; enableVideoTrack = [this](auto track, int index)
</span><span class="cx">     {
</span><span class="cx">         track-&gt;setTrackIndex(index);
</span><del>-        track-&gt;setSelected(track-&gt;streamTrack() == m_mediaStreamPrivate-&gt;activeVideoTrack());
</del><ins>+        bool selected = track-&gt;streamTrack() == m_mediaStreamPrivate-&gt;activeVideoTrack();
+        track-&gt;setSelected(selected);
</ins><span class="cx"> 
</span><del>-        if (track-&gt;selected())
</del><ins>+        if (selected)
</ins><span class="cx">             ensureLayer();
</span><span class="cx">     };
</span><span class="cx">     updateTracksOfType(m_videoTrackMap, RealtimeMediaSource::Video, currentTracks, &amp;VideoTrackPrivateMediaStream::create, m_player, &amp;MediaPlayer::removeVideoTrack, &amp;MediaPlayer::addVideoTrack, enableVideoTrack, (MediaStreamTrackPrivate::Observer*) this);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -239,14 +239,6 @@
</span><span class="cx">     return size;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-PlatformLayer* MediaStreamPrivate::platformLayer() const
-{
-    if (!m_activeVideoTrack)
-        return nullptr;
-
-    return m_activeVideoTrack-&gt;source().platformLayer();
-}
-
</del><span class="cx"> void MediaStreamPrivate::paintCurrentFrameInContext(GraphicsContext&amp; context, const FloatRect&amp; rect)
</span><span class="cx"> {
</span><span class="cx">     if (context.paintingDisabled())
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -93,7 +93,6 @@
</span><span class="cx">     void stopProducingData();
</span><span class="cx">     bool isProducingData() const;
</span><span class="cx"> 
</span><del>-    PlatformLayer* platformLayer() const;
</del><span class="cx">     RefPtr&lt;Image&gt; currentFrameImage();
</span><span class="cx">     void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamTrackPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -101,6 +101,9 @@
</span><span class="cx">     // Always update the enabled state regardless of the track being ended.
</span><span class="cx">     m_isEnabled = enabled;
</span><span class="cx"> 
</span><ins>+    if (m_preview)
+        m_preview-&gt;setEnabled(enabled);
+
</ins><span class="cx">     for (auto&amp; observer : m_observers)
</span><span class="cx">         observer-&gt;trackEnabledChanged(*this);
</span><span class="cx"> }
</span><span class="lines">@@ -115,6 +118,7 @@
</span><span class="cx">     // trackEnded method once.
</span><span class="cx">     m_isEnded = true;
</span><span class="cx"> 
</span><ins>+    m_preview = nullptr;
</ins><span class="cx">     m_source-&gt;requestStop(this);
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; observer : m_observers)
</span><span class="lines">@@ -166,6 +170,15 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RealtimeMediaSourcePreview* MediaStreamTrackPrivate::preview()
+{
+    if (m_preview)
+        return m_preview.get();
+
+    m_preview = m_source-&gt;preview();
+    return m_preview.get();
+}
+
</ins><span class="cx"> void MediaStreamTrackPrivate::applyConstraints(const MediaConstraints&amp; constraints, RealtimeMediaSource::SuccessHandler successHandler, RealtimeMediaSource::FailureHandler failureHandler)
</span><span class="cx"> {
</span><span class="cx">     m_source-&gt;applyConstraints(constraints, successHandler, failureHandler);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamTrackPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -96,6 +96,7 @@
</span><span class="cx">     AudioSourceProvider* audioSourceProvider();
</span><span class="cx"> 
</span><span class="cx">     void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;);
</span><ins>+    RealtimeMediaSourcePreview* preview();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     MediaStreamTrackPrivate(Ref&lt;RealtimeMediaSource&gt;&amp;&amp;, String&amp;&amp; id);
</span><span class="lines">@@ -110,6 +111,7 @@
</span><span class="cx">     Vector&lt;Observer*&gt; m_observers;
</span><span class="cx">     Ref&lt;RealtimeMediaSource&gt; m_source;
</span><span class="cx">     RefPtr&lt;MediaConstraints&gt; m_constraints;
</span><ins>+    RefPtr&lt;RealtimeMediaSourcePreview&gt; m_preview;
</ins><span class="cx"> 
</span><span class="cx">     String m_id;
</span><span class="cx">     bool m_isEnabled;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #include &quot;MediaSample.h&quot;
</span><span class="cx"> #include &quot;PlatformLayer.h&quot;
</span><span class="cx"> #include &quot;RealtimeMediaSourceCapabilities.h&quot;
</span><ins>+#include &quot;RealtimeMediaSourcePreview.h&quot;
</ins><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> #include &lt;wtf/WeakPtr.h&gt;
</span><span class="lines">@@ -126,9 +127,9 @@
</span><span class="cx"> 
</span><span class="cx">     virtual AudioSourceProvider* audioSourceProvider() { return nullptr; }
</span><span class="cx"> 
</span><del>-    virtual PlatformLayer* platformLayer() const { return nullptr; }
</del><span class="cx">     virtual RefPtr&lt;Image&gt; currentFrameImage() { return nullptr; }
</span><span class="cx">     virtual void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;) { }
</span><ins>+    virtual RefPtr&lt;RealtimeMediaSourcePreview&gt; preview() { return nullptr; }
</ins><span class="cx"> 
</span><span class="cx">     void setWidth(int);
</span><span class="cx">     void setHeight(int);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcePreviewhfromrev208850trunkSourceWebCoreplatformmediastreammacMockRealtimeVideoSourceMach"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h (from rev 208850, trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h) (0 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h                                (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -0,0 +1,69 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM)
+
+#include &quot;PlatformLayer.h&quot;
+#include &lt;wtf/RetainPtr.h&gt;
+#include &lt;wtf/WeakPtr.h&gt;
+
+namespace WebCore {
+
+class RealtimeMediaSourcePreview : public RefCounted&lt;RealtimeMediaSourcePreview&gt; {
+public:
+    virtual ~RealtimeMediaSourcePreview() { }
+
+    virtual void play() const = 0;
+    virtual void pause() const = 0;
+    virtual void setEnabled(bool) = 0;
+
+    virtual PlatformLayer* platformLayer() const = 0;
+    virtual void setVolume(double) const = 0;
+
+    virtual void invalidate() { m_weakPtrFactory.revokeAll(); }
+
+    WeakPtr&lt;RealtimeMediaSourcePreview&gt; createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
+protected:
+    RealtimeMediaSourcePreview()
+        : m_weakPtrFactory(this)
+    {
+    }
+
+private:
+    WeakPtrFactory&lt;RealtimeMediaSourcePreview&gt; m_weakPtrFactory;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVAudioCaptureSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -67,6 +67,7 @@
</span><span class="cx">     void shutdownCaptureSession() override;
</span><span class="cx">     void updateSettings(RealtimeMediaSourceSettings&amp;) override;
</span><span class="cx">     AudioSourceProvider* audioSourceProvider() override;
</span><ins>+    RefPtr&lt;AVMediaSourcePreview&gt; createPreview() final;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;AVCaptureConnection&gt; m_audioConnection;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVAudioCaptureSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -47,15 +47,31 @@
</span><span class="cx"> typedef AVCaptureDeviceInput AVCaptureDeviceInputType;
</span><span class="cx"> typedef AVCaptureOutput AVCaptureOutputType;
</span><span class="cx"> 
</span><ins>+#if !PLATFORM(IOS)
+typedef AVCaptureAudioPreviewOutput AVCaptureAudioPreviewOutputType;
+#endif
+
</ins><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
</span><span class="cx"> 
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioChannel)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioDataOutput)
</span><ins>+SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioPreviewOutput)
</ins><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureConnection)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureDeviceInput)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureOutput)
</span><span class="cx"> 
</span><ins>+#define AVCaptureAudioPreviewOutput getAVCaptureAudioPreviewOutputClass()
+
+#define AVCaptureAudioChannel getAVCaptureAudioChannelClass()
+#define AVCaptureAudioDataOutput getAVCaptureAudioDataOutputClass()
+#define AVCaptureConnection getAVCaptureConnectionClass()
+#define AVCaptureDevice getAVCaptureDeviceClass()
+#define AVCaptureDeviceFormat getAVCaptureDeviceFormatClass()
+#define AVCaptureDeviceInput getAVCaptureDeviceInputClass()
+#define AVCaptureOutput getAVCaptureOutputClass()
+#define AVFrameRateRange getAVFrameRateRangeClass()
+
</ins><span class="cx"> SOFT_LINK_POINTER(AVFoundation, AVMediaTypeAudio, NSString *)
</span><span class="cx"> 
</span><span class="cx"> #define AVMediaTypeAudio getAVMediaTypeAudio()
</span><span class="lines">@@ -62,6 +78,79 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+#if !PLATFORM(IOS)
+class AVAudioSourcePreview: public AVMediaSourcePreview {
+public:
+    static RefPtr&lt;AVMediaSourcePreview&gt; create(AVCaptureSession *, AVAudioCaptureSource*);
+
+private:
+    AVAudioSourcePreview(AVCaptureSession *, AVAudioCaptureSource*);
+
+    void invalidate() final;
+
+    void play() const final;
+    void pause() const final;
+    void setVolume(double) const final;
+    void setEnabled(bool) final;
+    PlatformLayer* platformLayer() const final { return nullptr; }
+
+    void updateState() const;
+
+    RetainPtr&lt;AVCaptureAudioPreviewOutputType&gt; m_audioPreviewOutput;
+    mutable double m_volume { 1 };
+    mutable bool m_paused { false };
+    mutable bool m_enabled { true };
+};
+
+RefPtr&lt;AVMediaSourcePreview&gt; AVAudioSourcePreview::create(AVCaptureSession *session, AVAudioCaptureSource* parent)
+{
+    return adoptRef(new AVAudioSourcePreview(session, parent));
+}
+
+AVAudioSourcePreview::AVAudioSourcePreview(AVCaptureSession *session, AVAudioCaptureSource* parent)
+    : AVMediaSourcePreview(parent)
+{
+    m_audioPreviewOutput = adoptNS([allocAVCaptureAudioPreviewOutputInstance() init]);
+    setVolume(1);
+    [session addOutput:m_audioPreviewOutput.get()];
+}
+
+void AVAudioSourcePreview::invalidate()
+{
+    m_audioPreviewOutput = nullptr;
+    AVMediaSourcePreview::invalidate();
+}
+
+void AVAudioSourcePreview::play() const
+{
+    m_paused = false;
+    updateState();
+}
+
+void AVAudioSourcePreview::pause() const
+{
+    m_paused = true;
+    updateState();
+}
+
+void AVAudioSourcePreview::setEnabled(bool enabled)
+{
+    m_enabled = enabled;
+    updateState();
+}
+
+void AVAudioSourcePreview::setVolume(double volume) const
+{
+    m_volume = volume;
+    m_audioPreviewOutput.get().volume = volume;
+}
+
+void AVAudioSourcePreview::updateState() const
+{
+    m_audioPreviewOutput.get().volume = (!m_enabled || m_paused) ? 0 : m_volume;
+}
+#endif
+
</ins><span class="cx"> RefPtr&lt;AVMediaCaptureSource&gt; AVAudioCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString&amp; id, const MediaConstraints* constraints, String&amp; invalidConstraint)
</span><span class="cx"> {
</span><span class="cx">     auto source = adoptRef(new AVAudioCaptureSource(device, id));
</span><span class="lines">@@ -213,6 +302,15 @@
</span><span class="cx">     return m_audioSourceProvider.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RefPtr&lt;AVMediaSourcePreview&gt; AVAudioCaptureSource::createPreview()
+{
+#if !PLATFORM(IOS)
+    return AVAudioSourcePreview::create(session(), this);
+#else
+    return nullptr;
+#endif
+}
+    
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVMediaCaptureSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -32,7 +32,6 @@
</span><span class="cx"> #include &quot;RealtimeMediaSource.h&quot;
</span><span class="cx"> #include &quot;Timer.h&quot;
</span><span class="cx"> #include &lt;wtf/Function.h&gt;
</span><del>-#include &lt;wtf/RetainPtr.h&gt;
</del><span class="cx"> 
</span><span class="cx"> OBJC_CLASS AVCaptureAudioDataOutput;
</span><span class="cx"> OBJC_CLASS AVCaptureConnection;
</span><span class="lines">@@ -46,6 +45,21 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class AVMediaCaptureSource;
+
+class AVMediaSourcePreview: public RealtimeMediaSourcePreview {
+public:
+    virtual ~AVMediaSourcePreview();
+
+    void invalidate() override;
+
+protected:
+    AVMediaSourcePreview(AVMediaCaptureSource*);
+
+private:
+    WeakPtr&lt;AVMediaCaptureSource&gt; m_parent;
+};
+
</ins><span class="cx"> class AVMediaCaptureSource : public RealtimeMediaSource {
</span><span class="cx"> public:
</span><span class="cx">     virtual ~AVMediaCaptureSource();
</span><span class="lines">@@ -62,6 +76,10 @@
</span><span class="cx">     void stopProducingData() final;
</span><span class="cx">     bool isProducingData() const final { return m_isRunning; }
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;RealtimeMediaSourcePreview&gt; preview() final;
+    void removePreview(AVMediaSourcePreview*);
+    WeakPtr&lt;AVMediaCaptureSource&gt; createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
</ins><span class="cx"> protected:
</span><span class="cx">     AVMediaCaptureSource(AVCaptureDevice*, const AtomicString&amp;, RealtimeMediaSource::Type);
</span><span class="cx"> 
</span><span class="lines">@@ -81,6 +99,8 @@
</span><span class="cx">     void setVideoSampleBufferDelegate(AVCaptureVideoDataOutput*);
</span><span class="cx">     void setAudioSampleBufferDelegate(AVCaptureAudioDataOutput*);
</span><span class="cx"> 
</span><ins>+    virtual RefPtr&lt;AVMediaSourcePreview&gt; createPreview() = 0;
+
</ins><span class="cx"> private:
</span><span class="cx">     void setupSession();
</span><span class="cx">     void reset() final;
</span><span class="lines">@@ -97,6 +117,8 @@
</span><span class="cx">     RefPtr&lt;RealtimeMediaSourceCapabilities&gt; m_capabilities;
</span><span class="cx">     RetainPtr&lt;AVCaptureSession&gt; m_session;
</span><span class="cx">     RetainPtr&lt;AVCaptureDevice&gt; m_device;
</span><ins>+    Vector&lt;WeakPtr&lt;RealtimeMediaSourcePreview&gt;&gt; m_previews;
+    WeakPtrFactory&lt;AVMediaCaptureSource&gt; m_weakPtrFactory;
</ins><span class="cx">     bool m_isRunning { false};
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVMediaCaptureSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -126,6 +126,7 @@
</span><span class="cx">     : RealtimeMediaSource(id, type, emptyString())
</span><span class="cx">     , m_objcObserver(adoptNS([[WebCoreAVMediaCaptureSourceObserver alloc] initWithCallback:this]))
</span><span class="cx">     , m_device(device)
</span><ins>+    , m_weakPtrFactory(this)
</ins><span class="cx"> {
</span><span class="cx">     setName(device.localizedName);
</span><span class="cx">     setPersistentID(device.uniqueID);
</span><span class="lines">@@ -235,6 +236,13 @@
</span><span class="cx">     m_isRunning = false;
</span><span class="cx">     for (NSString *keyName in sessionKVOProperties())
</span><span class="cx">         [m_session removeObserver:m_objcObserver.get() forKeyPath:keyName];
</span><ins>+
+    for (const auto&amp; preview : m_previews) {
+        if (preview)
+            preview-&gt;invalidate();
+    }
+    m_previews.clear();
+
</ins><span class="cx">     shutdownCaptureSession();
</span><span class="cx">     m_session = nullptr;
</span><span class="cx"> }
</span><span class="lines">@@ -266,6 +274,45 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RefPtr&lt;RealtimeMediaSourcePreview&gt; AVMediaCaptureSource::preview()
+{
+    RefPtr&lt;AVMediaSourcePreview&gt; preview = createPreview();
+    if (!preview)
+        return nullptr;
+
+    m_previews.append(preview-&gt;createWeakPtr());
+    return preview.leakRef();
+}
+
+void AVMediaCaptureSource::removePreview(AVMediaSourcePreview* preview)
+{
+    size_t index;
+    for (index = 0; index &lt; m_previews.size(); ++index) {
+        if (m_previews[index].get() == preview)
+            break;
+    }
+
+    if (index &lt; m_previews.size())
+        m_previews.remove(index);
+}
+
+AVMediaSourcePreview::AVMediaSourcePreview(AVMediaCaptureSource* parent)
+    : m_parent(parent-&gt;createWeakPtr())
+{
+}
+
+AVMediaSourcePreview::~AVMediaSourcePreview()
+{
+    if (m_parent)
+        m_parent-&gt;removePreview(this);
+}
+
+void AVMediaSourcePreview::invalidate()
+{
+    m_parent = nullptr;
+    RealtimeMediaSourcePreview::invalidate();
+}
+
</ins><span class="cx"> NSArray* sessionKVOProperties()
</span><span class="cx"> {
</span><span class="cx">     static NSArray* keys = [@[@&quot;running&quot;] retain];
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> 
</span><span class="cx"> class FloatRect;
</span><span class="cx"> class GraphicsContext;
</span><ins>+class AVVideoSourcePreview;
</ins><span class="cx"> 
</span><span class="cx"> class AVVideoCaptureSource : public AVMediaCaptureSource {
</span><span class="cx"> public:
</span><span class="lines">@@ -77,8 +78,8 @@
</span><span class="cx">     void processNewFrame(RetainPtr&lt;CMSampleBufferRef&gt;);
</span><span class="cx"> 
</span><span class="cx">     void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;) final;
</span><del>-    PlatformLayer* platformLayer() const final;
</del><span class="cx"> 
</span><ins>+    RefPtr&lt;AVMediaSourcePreview&gt; createPreview() final;
</ins><span class="cx">     RetainPtr&lt;CGImageRef&gt; currentFrameCGImage();
</span><span class="cx">     RefPtr&lt;Image&gt; currentFrameImage() final;
</span><span class="cx"> 
</span><span class="lines">@@ -85,8 +86,8 @@
</span><span class="cx">     RetainPtr&lt;NSString&gt; m_pendingPreset;
</span><span class="cx">     RetainPtr&lt;CMSampleBufferRef&gt; m_buffer;
</span><span class="cx">     RetainPtr&lt;CGImageRef&gt; m_lastImage;
</span><ins>+
</ins><span class="cx">     Vector&lt;Float64&gt; m_videoFrameTimeStamps;
</span><del>-    mutable RetainPtr&lt;PlatformLayer&gt; m_videoPreviewLayer;
</del><span class="cx">     Float64 m_frameRate { 0 };
</span><span class="cx">     int32_t m_width { 0 };
</span><span class="cx">     int32_t m_height { 0 };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> #import &quot;NotImplemented.h&quot;
</span><span class="cx"> #import &quot;PlatformLayer.h&quot;
</span><span class="cx"> #import &quot;RealtimeMediaSourceCenter.h&quot;
</span><ins>+#import &quot;RealtimeMediaSourcePreview.h&quot;
</ins><span class="cx"> #import &quot;RealtimeMediaSourceSettings.h&quot;
</span><span class="cx"> #import &lt;AVFoundation/AVFoundation.h&gt;
</span><span class="cx"> #import &lt;objc/runtime.h&gt;
</span><span class="lines">@@ -90,6 +91,90 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class AVVideoSourcePreview: public AVMediaSourcePreview {
+public:
+    static RefPtr&lt;AVMediaSourcePreview&gt; create(AVCaptureSession *, AVCaptureDeviceTypedef *, AVVideoCaptureSource*);
+
+private:
+    AVVideoSourcePreview(AVCaptureSession *, AVCaptureDeviceTypedef *, AVVideoCaptureSource*);
+
+    void invalidate() final;
+
+    void play() const final;
+    void pause() const final;
+    void setVolume(double) const final { };
+    void setEnabled(bool) final;
+    PlatformLayer* platformLayer() const final { return m_previewBackgroundLayer.get(); }
+    
+    void setPaused(bool) const;
+
+    RetainPtr&lt;AVCaptureVideoPreviewLayerType&gt; m_previewLayer;
+    RetainPtr&lt;PlatformLayer&gt; m_previewBackgroundLayer;
+    RetainPtr&lt;AVCaptureDeviceTypedef&gt; m_device;
+};
+
+RefPtr&lt;AVMediaSourcePreview&gt; AVVideoSourcePreview::create(AVCaptureSession *session, AVCaptureDeviceTypedef* device, AVVideoCaptureSource* parent)
+{
+    return adoptRef(new AVVideoSourcePreview(session, device, parent));
+}
+
+AVVideoSourcePreview::AVVideoSourcePreview(AVCaptureSession *session, AVCaptureDeviceTypedef* device, AVVideoCaptureSource* parent)
+    : AVMediaSourcePreview(parent)
+{
+    m_device = device;
+    m_previewLayer = adoptNS([allocAVCaptureVideoPreviewLayerInstance() initWithSession:session]);
+#ifndef NDEBUG
+    m_previewLayer.get().name = @&quot;AVVideoCaptureSource preview layer&quot;;
+#endif
+
+    m_previewLayer.get().contentsGravity = kCAGravityResize;
+    m_previewLayer.get().anchorPoint = CGPointZero;
+#if !PLATFORM(IOS)
+    m_previewLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+#endif
+
+    m_previewBackgroundLayer = adoptNS([[CALayer alloc] init]);
+    m_previewBackgroundLayer.get().name = @&quot;AVVideoSourcePreview parent layer&quot;;
+    m_previewBackgroundLayer.get().contentsGravity = kCAGravityResizeAspect;
+    m_previewBackgroundLayer.get().anchorPoint = CGPointZero;
+    m_previewBackgroundLayer.get().needsDisplayOnBoundsChange = YES;
+#if !PLATFORM(IOS)
+    m_previewBackgroundLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+#endif
+
+    [m_previewBackgroundLayer addSublayer:m_previewLayer.get()];
+}
+
+void AVVideoSourcePreview::invalidate()
+{
+    m_previewLayer = nullptr;
+    m_previewBackgroundLayer = nullptr;
+    m_device = nullptr;
+    AVMediaSourcePreview::invalidate();
+}
+
+void AVVideoSourcePreview::play() const
+{
+    setPaused(false);
+}
+
+void AVVideoSourcePreview::pause() const
+{
+    setPaused(true);
+}
+
+void AVVideoSourcePreview::setPaused(bool paused) const
+{
+    [m_device lockForConfiguration:nil];
+    m_previewLayer.get().connection.enabled = !paused;
+    [m_device unlockForConfiguration];
+}
+
+void AVVideoSourcePreview::setEnabled(bool enabled)
+{
+    m_previewLayer.get().hidden = !enabled;
+}
+
</ins><span class="cx"> const OSType videoCaptureFormat = kCVPixelFormatType_32BGRA;
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;AVMediaCaptureSource&gt; AVVideoCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString&amp; id, const MediaConstraints* constraints, String&amp; invalidConstraint)
</span><span class="lines">@@ -215,7 +300,7 @@
</span><span class="cx"> {
</span><span class="cx">     NSString *preset = bestSessionPresetForVideoDimensions(size.width(), size.height());
</span><span class="cx">     if (!preset || ![session() canSetSessionPreset:preset]) {
</span><del>-        LOG(Media, &quot;AVVideoCaptureSource::applySize%p), unable find or set preset for width: %i, height: %i&quot;, this, size.width(), size.height());
</del><ins>+        LOG(Media, &quot;AVVideoCaptureSource::applySize(%p), unable find or set preset for width: %i, height: %i&quot;, this, size.width(), size.height());
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -318,7 +403,6 @@
</span><span class="cx"> 
</span><span class="cx"> void AVVideoCaptureSource::shutdownCaptureSession()
</span><span class="cx"> {
</span><del>-    m_videoPreviewLayer = nullptr;
</del><span class="cx">     m_buffer = nullptr;
</span><span class="cx">     m_lastImage = nullptr;
</span><span class="cx">     m_videoFrameTimeStamps.clear();
</span><span class="lines">@@ -365,12 +449,14 @@
</span><span class="cx">     ASSERT(newSampleBuffer);
</span><span class="cx"> 
</span><span class="cx">     CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(newSampleBuffer, true);
</span><del>-    for (CFIndex i = 0; i &lt; CFArrayGetCount(attachmentsArray); ++i) {
-        CFMutableDictionaryRef attachments = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachmentsArray, i);
-        CFDictionarySetValue(attachments, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
</del><ins>+    if (attachmentsArray) {
+        for (CFIndex i = 0; i &lt; CFArrayGetCount(attachmentsArray); ++i) {
+            CFMutableDictionaryRef attachments = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachmentsArray, i);
+            CFDictionarySetValue(attachments, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_buffer = newSampleBuffer;
</del><ins>+    m_buffer = adoptCF(newSampleBuffer);
</ins><span class="cx">     m_lastImage = nullptr;
</span><span class="cx"> 
</span><span class="cx">     bool settingsChanged = false;
</span><span class="lines">@@ -450,17 +536,9 @@
</span><span class="cx">     CGContextDrawImage(context.platformContext(), CGRectMake(0, 0, paintRect.width(), paintRect.height()), m_lastImage.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-PlatformLayer* AVVideoCaptureSource::platformLayer() const
</del><ins>+RefPtr&lt;AVMediaSourcePreview&gt; AVVideoCaptureSource::createPreview()
</ins><span class="cx"> {
</span><del>-    if (m_videoPreviewLayer)
-        return m_videoPreviewLayer.get();
-
-    m_videoPreviewLayer = adoptNS([allocAVCaptureVideoPreviewLayerInstance() initWithSession:session()]);
-#ifndef NDEBUG
-    m_videoPreviewLayer.get().name = @&quot;AVVideoCaptureSource preview layer&quot;;
-#endif
-
-    return m_videoPreviewLayer.get();
</del><ins>+    return AVVideoSourcePreview::create(session(), device(), this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> NSString *AVVideoCaptureSource::bestSessionPresetForVideoDimensions(Optional&lt;int&gt; width, Optional&lt;int&gt; height) const
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacMockRealtimeVideoSourceMach"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -54,8 +54,7 @@
</span><span class="cx">     RetainPtr&lt;CMSampleBufferRef&gt; CMSampleBufferFromPixelBuffer(CVPixelBufferRef);
</span><span class="cx">     RetainPtr&lt;CVPixelBufferRef&gt; pixelBufferFromCGImage(CGImageRef) const;
</span><span class="cx"> 
</span><del>-    PlatformLayer* platformLayer() const override;
-    void updatePlatformLayer() const override;
</del><ins>+    PlatformLayer* platformLayer() const;
</ins><span class="cx">     void updateSampleBuffer() override;
</span><span class="cx"> 
</span><span class="cx">     mutable RetainPtr&lt;CGImageRef&gt; m_previewImage;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacMockRealtimeVideoSourceMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -120,49 +120,6 @@
</span><span class="cx">     return adoptCF(pixelBuffer);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-PlatformLayer* MockRealtimeVideoSourceMac::platformLayer() const
-{
-    if (m_previewLayer)
-        return m_previewLayer.get();
-
-    m_previewLayer = adoptNS([[CALayer alloc] init]);
-    m_previewLayer.get().name = @&quot;MockRealtimeVideoSourceMac preview layer&quot;;
-    m_previewLayer.get().contentsGravity = kCAGravityResizeAspect;
-    m_previewLayer.get().anchorPoint = CGPointZero;
-    m_previewLayer.get().needsDisplayOnBoundsChange = YES;
-#if !PLATFORM(IOS)
-    m_previewLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
-#endif
-
-    updatePlatformLayer();
-
-    return m_previewLayer.get();
-}
-
-void MockRealtimeVideoSourceMac::updatePlatformLayer() const
-{
-    if (!m_previewLayer)
-        return;
-
-    [CATransaction begin];
-    [CATransaction setAnimationDuration:0];
-    [CATransaction setDisableActions:YES];
-
-    do {
-        RefPtr&lt;Image&gt; image = imageBuffer()-&gt;copyImage();
-        if (!image)
-            break;
-
-        m_previewImage = image-&gt;nativeImage();
-        if (!m_previewImage)
-            break;
-
-        m_previewLayer.get().contents = (NSObject*)(m_previewImage.get());
-    } while (0);
-
-    [CATransaction commit];
-}
-
</del><span class="cx"> void MockRealtimeVideoSourceMac::updateSampleBuffer()
</span><span class="cx"> {
</span><span class="cx">     auto pixelBuffer = pixelBufferFromCGImage(imageBuffer()-&gt;copyImage()-&gt;nativeImage().get());
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeVideoSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -138,7 +138,6 @@
</span><span class="cx">     if (m_timer.isActive())
</span><span class="cx">         m_timer.startRepeating(std::chrono::milliseconds(lround(1000 / rate)));
</span><span class="cx"> 
</span><del>-    updatePlatformLayer();
</del><span class="cx">     updateSampleBuffer();
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -168,7 +167,6 @@
</span><span class="cx">     m_statsFont.update(nullptr);
</span><span class="cx"> 
</span><span class="cx">     m_imageBuffer = nullptr;
</span><del>-    updatePlatformLayer();
</del><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -339,7 +337,6 @@
</span><span class="cx">     drawAnimation(context);
</span><span class="cx">     drawBoxes(context);
</span><span class="cx"> 
</span><del>-    updatePlatformLayer();
</del><span class="cx">     updateSampleBuffer();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeVideoSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (208850 => 208851)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h        2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h        2016-11-17 18:43:40 UTC (rev 208851)
</span><span class="lines">@@ -53,7 +53,6 @@
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     MockRealtimeVideoSource(const String&amp;);
</span><del>-    virtual void updatePlatformLayer() const { }
</del><span class="cx">     virtual void updateSampleBuffer() { }
</span><span class="cx"> 
</span><span class="cx">     ImageBuffer* imageBuffer() const;
</span><span class="lines">@@ -77,7 +76,6 @@
</span><span class="cx">     bool applyFacingMode(RealtimeMediaSourceSettings::VideoFacingMode) override { return true; }
</span><span class="cx">     bool applyAspectRatio(double) override { return true; }
</span><span class="cx"> 
</span><del>-    PlatformLayer* platformLayer() const override { return nullptr; }
</del><span class="cx">     RefPtr&lt;Image&gt; currentFrameImage() override;
</span><span class="cx">     void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;) override;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>