<!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>[191721] 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/191721">191721</a></dd>
<dt>Author</dt> <dd>eric.carlson@apple.com</dd>
<dt>Date</dt> <dd>2015-10-28 22:30:40 -0700 (Wed, 28 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MediaStream] Play MediaStream through media element and rendered to canvas
https://bugs.webkit.org/show_bug.cgi?id=150449

Reviewed by Jer Noble.

* Modules/mediastream/MediaStream.cpp:
(WebCore::MediaStream::create): Don't die a recursive death.
(WebCore::MediaStream::MediaStream): setClient -&gt; addObserver. Set private stream's public stream pointer.
(WebCore::MediaStream::~MediaStream): setClient -&gt; addObserver. Clear private stream's public stream pointer.
(WebCore::MediaStream::didAddTrack): Short circuit calling internalAddTrack when the track is unknown.
(WebCore::MediaStream::didRemoveTrack): ASSERT that the track is known.
* Modules/mediastream/MediaStream.h:

* Modules/mediastream/MediaStreamTrack.cpp:
(WebCore::MediaStreamTrack::trackProducingDataChanged): New.
(WebCore::MediaStreamTrack::trackEnabledChanged): New.
* Modules/mediastream/MediaStreamTrack.h:

* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::didRemoveRemoteStream): Use the new MediaStreamPrivate::publicStream() method.

* Modules/webaudio/MediaStreamAudioSource.cpp:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaStreamcpp">trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaStreamh">trunk/Source/WebCore/Modules/mediastream/MediaStream.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaStreamTrackcpp">trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaStreamTrackh">trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCPeerConnectioncpp">trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioMediaStreamAudioSourcecpp">trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioMediaStreamAudioSourceh">trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioMediaStreamAudioSourceNodecpp">trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayercpp">trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp</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="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp</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="#trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm">trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.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="#trunkSourceWebCoreplatformmediastreammacWebAudioSourceProviderAVFObjCh">trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacWebAudioSourceProviderAVFObjCmm">trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamopenwebrtcRealtimeMediaSourceOwrh">trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceOwr.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp">trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaStreamPrivateAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaStreamPrivateAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/ChangeLog        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -1,3 +1,191 @@
</span><ins>+2015-10-28  Eric Carlson  &lt;eric.carlson@apple.com&gt;
+
+        [MediaStream] Play MediaStream through media element and rendered to canvas
+        https://bugs.webkit.org/show_bug.cgi?id=150449
+
+        Reviewed by Jer Noble.
+
+        * Modules/mediastream/MediaStream.cpp:
+        (WebCore::MediaStream::create): Don't die a recursive death.
+        (WebCore::MediaStream::MediaStream): setClient -&gt; addObserver. Set private stream's public stream pointer.
+        (WebCore::MediaStream::~MediaStream): setClient -&gt; addObserver. Clear private stream's public stream pointer.
+        (WebCore::MediaStream::didAddTrack): Short circuit calling internalAddTrack when the track is unknown.
+        (WebCore::MediaStream::didRemoveTrack): ASSERT that the track is known.
+        * Modules/mediastream/MediaStream.h:
+
+        * Modules/mediastream/MediaStreamTrack.cpp:
+        (WebCore::MediaStreamTrack::trackProducingDataChanged): New.
+        (WebCore::MediaStreamTrack::trackEnabledChanged): New.
+        * Modules/mediastream/MediaStreamTrack.h:
+
+        * Modules/mediastream/RTCPeerConnection.cpp:
+        (WebCore::RTCPeerConnection::didRemoveRemoteStream): Use the new MediaStreamPrivate::publicStream() method.
+
+        * Modules/webaudio/MediaStreamAudioSource.cpp:
+]        (WebCore::MediaStreamAudioSource::capabilities): capabilities isn't const.
+        * Modules/webaudio/MediaStreamAudioSource.h:
+
+        * Modules/webaudio/MediaStreamAudioSourceNode.cpp:
+        (WebCore::MediaStreamAudioSourceNode::setFormat): Reformat to make it use early return.
+
+        * WebCore.xcodeproj/project.pbxproj: Remove MediaStreamPrivateAVFObjC.mm/h, they are no longer necessary.
+
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::buildMediaEnginesVector): Register MediaPlayerPrivateMediaStreamAVFObjC engine.
+
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC): Cleanup, add logging.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC): Add
+          logging, remove private stream observer.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::registerMediaEngine): Cleanup.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::isAvailable): Ditto.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::getSupportedTypes): Return an empty vector.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::load): Use the MediaStreamPrivate passed instead
+          of creating a new private stream. 
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::cancelLoad): Pause output.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::prepareToPlay): Add logging.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer): m_previewLayer -&gt; m_videoBackgroundLayer.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setPausedImageVisible): New, show/hide the preview layer and configure
+          the background layer so we show a still image even though the capture device continues to run. Start/stop clock.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::play): Don't need to start the source, that happens in in load. Just
+          set flags and hide the paused image.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::pause): Don't stop the source, it may be shared by more than one 
+          stream/track. Just set the playing flag and show the paused image.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::paused): Fix.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::internalSetVolume): New, called by setMuted and setVolume.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVolume): New.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setMuted): Don't mute the source, it doesn't do what you think.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::hasVideo): Pass-through to stream.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::hasAudio): Ditto.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentMediaTime): Return clock time.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentReadyState): New.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::activeStatusChanged): Update readyState.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateIntrinsicSize): Update intrinsic size, create layers if necessary.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::createPreviewLayers): Create preview layers.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::characteristicsChanged): Update for changed characteristics.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::seekable): 'seekable' must return an empty TimeRanges object.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::paintCurrentFrameInContext): New.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask):
+        (WebCore::mimeTypeCache): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformMedia): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::playInternal): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::pauseInternal): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::sizeChanged): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::maxMediaTimeSeekable): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::minMediaTimeSeekable): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::createImageFromSampleBuffer): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::supportsAcceleratedRendering): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::movieLoadType): Deleted.
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::extraMemoryCost): Deleted.
+
+        Delete MediaStreamPrivateAVFObjC.mm/.h as they aren't necessary. 
+        * platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.h: Removed.
+        * platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.mm: Removed.
+
+        * platform/mediastream/MediaStreamPrivate.cpp:
+        (WebCore::MediaStreamPrivate::MediaStreamPrivate): Add track observer!
+        (WebCore::MediaStreamPrivate::addObserver): New.
+        (WebCore::MediaStreamPrivate::removeObserver): New.
+        (WebCore::MediaStreamPrivate::updateActiveState): Remember the first active video track.
+        (WebCore::MediaStreamPrivate::addTrack): Notify observers.
+        (WebCore::MediaStreamPrivate::removeTrack): Ditto.
+        (WebCore::MediaStreamPrivate::startProducingData): Pass-through to tracks.
+        (WebCore::MediaStreamPrivate::stopProducingData): Ditto.
+        (WebCore::MediaStreamPrivate::isProducingData): Ditto.
+        (WebCore::MediaStreamPrivate::hasVideo): Ditto.
+        (WebCore::MediaStreamPrivate::hasAudio): Ditto.
+        (WebCore::MediaStreamPrivate::platformLayer): Ditto.
+        (WebCore::MediaStreamPrivate::paintCurrentFrameInContext): Either pass-through to first active video
+          track, or paint the context black.
+        (WebCore::MediaStreamPrivate::currentFrameImage): Pass-through to first active video track.
+        (WebCore::MediaStreamPrivate::characteristicsChanged): Inform observers.
+        (WebCore::MediaStreamPrivate::trackMutedChanged):
+        (WebCore::MediaStreamPrivate::trackStatesChanged):
+        (WebCore::MediaStreamPrivate::trackEnabledChanged):
+        (WebCore::MediaStreamPrivate::trackProducingDataChanged):
+        (WebCore::MediaStreamPrivate::scheduleDeferredTask): New, call a function asynchronously on
+          the main thread.
+        * platform/mediastream/MediaStreamPrivate.h:
+
+        * platform/mediastream/MediaStreamTrackPrivate.cpp:
+        (WebCore::MediaStreamTrackPrivate::endTrack):
+        (WebCore::MediaStreamTrackPrivate::sourceProducingDataChanged): New, inform observers.
+        (WebCore::MediaStreamTrackPrivate::sourceEnabledChanged): Ditto.
+        * platform/mediastream/MediaStreamTrackPrivate.h:
+
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::isProducingDataDidChange): New, inform observers.
+        (WebCore::RealtimeMediaSource::setEnabled): Ditto.
+        (WebCore::RealtimeMediaSource::stop): Call reset();
+        * platform/mediastream/RealtimeMediaSource.h: Don't declare &quot;capabilities&quot; as const so 
+          capabilities can be created and initialized lazily.
+
+        * platform/mediastream/mac/AVAudioCaptureSource.h:
+        * platform/mediastream/mac/AVAudioCaptureSource.mm:
+        (WebCore::AVAudioCaptureSource::initializeCapabilities): New.
+        (WebCore::AVAudioCaptureSource::addObserver): Hold the lock while calling observers so the list
+          can't be mutated.
+        (WebCore::AVAudioCaptureSource::setupCaptureSession): Log and fail if the session won't add the
+          input or output.
+        (WebCore::AVAudioCaptureSource::shutdownCaptureSession): Cleanup.
+        (WebCore::AVAudioCaptureSource::captureOutputDidOutputSampleBufferFromConnection): Don't block
+          if it isn't possible to acquire the lock. Hold the lock while calling observers.
+        (WebCore::AVAudioCaptureSource::capabilities): Deleted.
+
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::refreshCaptureDeviceList): Don't include devices that can't be used.
+        (WebCore::AVCaptureDeviceManager::bestSourcesForTypeAndConstraints):  Use AVCaptureDeviceManager::sourceWithUID
+          so constraints are considered.
+        (WebCore::AVCaptureDeviceManager::sourceWithUID): Don't consider disabled devices. Always
+          create a new capture device so each track starts out with a unique source.
+        * platform/mediastream/mac/AVMediaCaptureSource.h:
+
+        * platform/mediastream/mac/AVMediaCaptureSource.mm:
+        (WebCore::globaAudioCaptureSerialQueue):
+        (WebCore::AVMediaCaptureSource::AVMediaCaptureSource):
+        (WebCore::AVMediaCaptureSource::~AVMediaCaptureSource): Remove KVO observers.
+        (WebCore::AVMediaCaptureSource::startProducingData): m_isRunning is changed in captureSessionIsRunningDidChange.
+        (WebCore::AVMediaCaptureSource::stopProducingData): Ditto.
+        (WebCore::AVMediaCaptureSource::capabilities): New.
+        (WebCore::AVMediaCaptureSource::setupSession): Add KVObservers for the properties we care about.
+        (WebCore::AVMediaCaptureSource::reset): New, cleanup.
+        (WebCore::AVMediaCaptureSource::captureSessionIsRunningDidChange): Dispatch to the main thread 
+          to set m_isRunning, call isProducingDataDidChange so observers can find out.
+        (WebCore::sessionKVOProperties):
+        (-[WebCoreAVMediaCaptureSourceObserver disconnect]):
+        (-[WebCoreAVMediaCaptureSourceObserver captureOutput:didOutputSampleBuffer:fromConnection:]):
+        (-[WebCoreAVMediaCaptureSourceObserver observeValueForKeyPath:ofObject:change:context:]): Respond
+          to running changes.
+        (WebCore::AVMediaCaptureSource::captureSessionStoppedRunning): Deleted.
+        (-[WebCoreAVMediaCaptureSourceObserver captureSessionStoppedRunning:]): Deleted.
+
+        * platform/mediastream/mac/AVVideoCaptureSource.h:
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        (WebCore::AVVideoCaptureSource::initializeCapabilities): Partial implementation.
+        (WebCore::AVVideoCaptureSource::setupCaptureSession):  Log and fail if the session won't add the
+          input or output.
+        (WebCore::AVVideoCaptureSource::shutdownCaptureSession): Cleanup.
+        (WebCore::AVVideoCaptureSource::updateFramerate): Renamed from calculateFramerate.
+        (WebCore::AVVideoCaptureSource::currentFrameImage): Return an Image.
+        (WebCore::AVVideoCaptureSource::platformLayer): New.
+        (WebCore::AVVideoCaptureSource::capabilities): Deleted.
+        (WebCore::AVVideoCaptureSource::calculateFramerate): Deleted.
+
+        * platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h:
+        * platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm:
+        (WebCore::WebAudioSourceProviderAVFObjC::~WebAudioSourceProviderAVFObjC): AudioConverterRef is
+          not a CF/ObjC object so we can't use a RetainPtr&lt;&gt; for it.
+        (WebCore::WebAudioSourceProviderAVFObjC::provideInput): Ditto.
+        (WebCore::WebAudioSourceProviderAVFObjC::prepare): Ditto.
+        (WebCore::WebAudioSourceProviderAVFObjC::unprepare): Ditto.
+        (WebCore::WebAudioSourceProviderAVFObjC::process): Fix typo in logging.
+
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockSource::capabilities): Update for capabilities change.
+
+        * platform/mediastream/openwebrtc/RealtimeMediaSourceOwr.h: Update for capabilities change.
+
</ins><span class="cx"> 2015-10-28  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Regression(r191673): [WIN][EFL][GTK] layout tests using data URLs time out
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -40,6 +40,36 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+static Vector&lt;MediaStream*&gt;&amp; mediaStreams()
+{
+    static NeverDestroyed&lt;Vector&lt;MediaStream*&gt;&gt; streams;
+    return streams;
+}
+
+static void registerMediaStream(MediaStream* stream)
+{
+    mediaStreams().append(stream);
+}
+
+static void unRegisterMediaStream(MediaStream* stream)
+{
+    Vector&lt;MediaStream*&gt;&amp; allStreams = mediaStreams();
+    size_t pos = allStreams.find(stream);
+    if (pos != notFound)
+        allStreams.remove(pos);
+}
+
+MediaStream* MediaStream::lookUp(const MediaStreamPrivate&amp; privateStream)
+{
+    Vector&lt;MediaStream*&gt;&amp; allStreams = mediaStreams();
+    for (auto&amp; stream : allStreams) {
+        if (stream-&gt;m_private == &amp;privateStream)
+            return stream;
+    }
+
+    return nullptr;
+}
+
</ins><span class="cx"> static URLRegistry* s_registry;
</span><span class="cx"> 
</span><span class="cx"> void MediaStream::setRegistry(URLRegistry&amp; registry)
</span><span class="lines">@@ -58,7 +88,7 @@
</span><span class="cx"> 
</span><span class="cx"> Ref&lt;MediaStream&gt; MediaStream::create(ScriptExecutionContext&amp; context)
</span><span class="cx"> {
</span><del>-    return MediaStream::create(context);
</del><ins>+    return MediaStream::create(context, MediaStreamPrivate::create(Vector&lt;RefPtr&lt;MediaStreamTrackPrivate&gt;&gt;()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Ref&lt;MediaStream&gt; MediaStream::create(ScriptExecutionContext&amp; context, MediaStream* stream)
</span><span class="lines">@@ -95,7 +125,8 @@
</span><span class="cx"> 
</span><span class="cx">     m_private = MediaStreamPrivate::create(trackPrivates);
</span><span class="cx">     m_isActive = m_private-&gt;active();
</span><del>-    m_private-&gt;setClient(this);
</del><ins>+    m_private-&gt;addObserver(*this);
+    registerMediaStream(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MediaStream::MediaStream(ScriptExecutionContext&amp; context, RefPtr&lt;MediaStreamPrivate&gt;&amp;&amp; streamPrivate)
</span><span class="lines">@@ -105,7 +136,8 @@
</span><span class="cx">     , m_activityEventTimer(*this, &amp;MediaStream::activityEventTimerFired)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_private);
</span><del>-    m_private-&gt;setClient(this);
</del><ins>+    m_private-&gt;addObserver(*this);
+    registerMediaStream(this);
</ins><span class="cx"> 
</span><span class="cx">     for (auto&amp; trackPrivate : m_private-&gt;tracks()) {
</span><span class="cx">         RefPtr&lt;MediaStreamTrack&gt; track = MediaStreamTrack::create(context, *trackPrivate);
</span><span class="lines">@@ -116,7 +148,10 @@
</span><span class="cx"> 
</span><span class="cx"> MediaStream::~MediaStream()
</span><span class="cx"> {
</span><del>-    m_private-&gt;setClient(nullptr);
</del><ins>+    unRegisterMediaStream(this);
+    m_private-&gt;removeObserver(*this);
+    for (auto&amp; track : m_trackSet.values())
+        track-&gt;removeObserver(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;MediaStream&gt; MediaStream::clone()
</span><span class="lines">@@ -199,12 +234,14 @@
</span><span class="cx">     if (!context)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    internalAddTrack(MediaStreamTrack::create(*context, trackPrivate), StreamModifier::Platform);
</del><ins>+    if (!getTrackById(trackPrivate.id()))
+        internalAddTrack(MediaStreamTrack::create(*context, trackPrivate), StreamModifier::Platform);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaStream::didRemoveTrack(MediaStreamTrackPrivate&amp; trackPrivate)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;MediaStreamTrack&gt; track = getTrackById(trackPrivate.id());
</span><ins>+    ASSERT(track);
</ins><span class="cx">     internalRemoveTrack(WTF::move(track), StreamModifier::Platform);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -254,6 +291,7 @@
</span><span class="cx">     events.swap(m_scheduledActivityEvents);
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; event : events) {
</span><ins>+        // FIXME: This can't be right, the event type is set from m_isActive in scheduleActiveStateChange! - https://webkit.org/b/150635
</ins><span class="cx">         m_isActive = event-&gt;type() == eventNames().activeEvent;
</span><span class="cx">         dispatchEvent(event.release());
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaStream.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class MediaStream final : public URLRegistrable, public ScriptWrappable, public MediaStreamPrivateClient, public EventTargetWithInlineData, public ContextDestructionObserver, public MediaStreamTrack::Observer {
</del><ins>+class MediaStream final : public URLRegistrable, public ScriptWrappable, public EventTargetWithInlineData, public ContextDestructionObserver, public MediaStreamTrack::Observer, public MediaStreamPrivate::Observer, public RefCounted&lt;MediaStream&gt; {
</ins><span class="cx"> public:
</span><span class="cx">     class Observer {
</span><span class="cx">     public:
</span><span class="lines">@@ -55,6 +55,8 @@
</span><span class="cx">     static void setRegistry(URLRegistry&amp;);
</span><span class="cx">     static MediaStream* lookUp(const URL&amp;);
</span><span class="cx"> 
</span><ins>+    static MediaStream* lookUp(const MediaStreamPrivate&amp;);
+
</ins><span class="cx">     static Ref&lt;MediaStream&gt; create(ScriptExecutionContext&amp;);
</span><span class="cx">     static Ref&lt;MediaStream&gt; create(ScriptExecutionContext&amp;, MediaStream*);
</span><span class="cx">     static Ref&lt;MediaStream&gt; create(ScriptExecutionContext&amp;, const MediaStreamTrackVector&amp;);
</span><span class="lines">@@ -81,8 +83,8 @@
</span><span class="cx">     virtual EventTargetInterface eventTargetInterface() const final { return MediaStreamEventTargetInterfaceType; }
</span><span class="cx">     virtual ScriptExecutionContext* scriptExecutionContext() const final { return ContextDestructionObserver::scriptExecutionContext(); }
</span><span class="cx"> 
</span><del>-    using RefCounted&lt;MediaStreamPrivateClient&gt;::ref;
-    using RefCounted&lt;MediaStreamPrivateClient&gt;::deref;
</del><ins>+    using RefCounted&lt;MediaStream&gt;::ref;
+    using RefCounted&lt;MediaStream&gt;::deref;
</ins><span class="cx"> 
</span><span class="cx">     // URLRegistrable
</span><span class="cx">     virtual URLRegistry&amp; registry() const override;
</span><span class="lines">@@ -107,7 +109,7 @@
</span><span class="cx">     // MediaStreamTrack::Observer
</span><span class="cx">     virtual void trackDidEnd() override final;
</span><span class="cx"> 
</span><del>-    // MediaStreamPrivateClient
</del><ins>+    // MediaStreamPrivate::Observer
</ins><span class="cx">     virtual void activeStatusChanged() override final;
</span><span class="cx">     virtual void didAddTrack(MediaStreamTrackPrivate&amp;) override final;
</span><span class="cx">     virtual void didRemoveTrack(MediaStreamTrackPrivate&amp;) override final;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaStreamTrackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -213,6 +213,16 @@
</span><span class="cx">     configureTrackRendering();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaStreamTrack::trackProducingDataChanged(MediaStreamTrackPrivate&amp;)
+{
+    configureTrackRendering();
+}
+
+void MediaStreamTrack::trackEnabledChanged(MediaStreamTrackPrivate&amp;)
+{
+    configureTrackRendering();
+}
+
</ins><span class="cx"> void MediaStreamTrack::configureTrackRendering()
</span><span class="cx"> {
</span><span class="cx">     // 4.3.1
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaStreamTrackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -118,6 +118,8 @@
</span><span class="cx">     void trackEnded(MediaStreamTrackPrivate&amp;) override;
</span><span class="cx">     void trackMutedChanged(MediaStreamTrackPrivate&amp;) override;
</span><span class="cx">     void trackStatesChanged(MediaStreamTrackPrivate&amp;) override;
</span><ins>+    void trackProducingDataChanged(MediaStreamTrackPrivate&amp;) override;
+    void trackEnabledChanged(MediaStreamTrackPrivate&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;Observer*&gt; m_observers;
</span><span class="cx">     Ref&lt;MediaStreamTrackPrivate&gt; m_private;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCPeerConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -649,14 +649,12 @@
</span><span class="cx"> void RTCPeerConnection::didRemoveRemoteStream(MediaStreamPrivate* privateStream)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(scriptExecutionContext()-&gt;isContextThread());
</span><del>-    ASSERT(privateStream-&gt;client());
</del><span class="cx"> 
</span><del>-    // FIXME: this class shouldn't know that the private stream client is a MediaStream!
-    RefPtr&lt;MediaStream&gt; stream = static_cast&lt;MediaStream*&gt;(privateStream-&gt;client());
-
</del><span class="cx">     if (m_signalingState == SignalingStateClosed)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;MediaStream&gt; stream = MediaStream::lookUp(*privateStream);
+    ASSERT(stream);
</ins><span class="cx">     size_t pos = m_remoteStreams.find(stream);
</span><span class="cx">     ASSERT(pos != notFound);
</span><span class="cx">     m_remoteStreams.remove(pos);
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioMediaStreamAudioSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;RealtimeMediaSourceCapabilities&gt; MediaStreamAudioSource::capabilities() const
</del><ins>+RefPtr&lt;RealtimeMediaSourceCapabilities&gt; MediaStreamAudioSource::capabilities()
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: implement this.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=122430
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioMediaStreamAudioSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSource.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> 
</span><span class="cx">     ~MediaStreamAudioSource() { }
</span><span class="cx"> 
</span><del>-    RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() const override;
</del><ins>+    RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() override;
</ins><span class="cx">     const RealtimeMediaSourceStates&amp; states() override;
</span><span class="cx">     
</span><span class="cx">     const String&amp; deviceId() const { return m_deviceId; }
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioMediaStreamAudioSourceNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -69,37 +69,38 @@
</span><span class="cx"> void MediaStreamAudioSourceNode::setFormat(size_t numberOfChannels, float sourceSampleRate)
</span><span class="cx"> {
</span><span class="cx">     float sampleRate = this-&gt;sampleRate();
</span><del>-    if (numberOfChannels != m_sourceNumberOfChannels || sourceSampleRate != sampleRate) {
-        // The sample-rate must be equal to the context's sample-rate.
-        if (!numberOfChannels || numberOfChannels &gt; AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate) {
-            // process() will generate silence for these uninitialized values.
-            LOG(Media, &quot;MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change&quot;, static_cast&lt;unsigned&gt;(numberOfChannels), sourceSampleRate);
-            m_sourceNumberOfChannels = 0;
-            return;
-        }
</del><ins>+    if (numberOfChannels == m_sourceNumberOfChannels &amp;&amp; sourceSampleRate == sampleRate)
+        return;
</ins><span class="cx"> 
</span><del>-        // Synchronize with process().
-        std::lock_guard&lt;Lock&gt; lock(m_processMutex);
</del><ins>+    // The sample-rate must be equal to the context's sample-rate.
+    if (!numberOfChannels || numberOfChannels &gt; AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate) {
+        // process() will generate silence for these uninitialized values.
+        LOG(Media, &quot;MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change&quot;, static_cast&lt;unsigned&gt;(numberOfChannels), sourceSampleRate);
+        m_sourceNumberOfChannels = 0;
+        return;
+    }
</ins><span class="cx"> 
</span><del>-        m_sourceNumberOfChannels = numberOfChannels;
-        m_sourceSampleRate = sourceSampleRate;
</del><ins>+    // Synchronize with process().
+    std::lock_guard&lt;Lock&gt; lock(m_processMutex);
</ins><span class="cx"> 
</span><del>-        if (sourceSampleRate == sampleRate)
-            m_multiChannelResampler = nullptr;
-        else {
-            double scaleFactor = sourceSampleRate / sampleRate;
-            m_multiChannelResampler = std::make_unique&lt;MultiChannelResampler&gt;(scaleFactor, numberOfChannels);
-        }
</del><ins>+    m_sourceNumberOfChannels = numberOfChannels;
+    m_sourceSampleRate = sourceSampleRate;
</ins><span class="cx"> 
</span><del>-        m_sourceNumberOfChannels = numberOfChannels;
</del><ins>+    if (sourceSampleRate == sampleRate)
+        m_multiChannelResampler = nullptr;
+    else {
+        double scaleFactor = sourceSampleRate / sampleRate;
+        m_multiChannelResampler = std::make_unique&lt;MultiChannelResampler&gt;(scaleFactor, numberOfChannels);
+    }
</ins><span class="cx"> 
</span><del>-        {
-            // The context must be locked when changing the number of output channels.
-            AudioContext::AutoLocker contextLocker(*context());
</del><ins>+    m_sourceNumberOfChannels = numberOfChannels;
</ins><span class="cx"> 
</span><del>-            // Do any necesssary re-configuration to the output's number of channels.
-            output(0)-&gt;setNumberOfChannels(numberOfChannels);
-        }
</del><ins>+    {
+        // The context must be locked when changing the number of output channels.
+        AudioContext::AutoLocker contextLocker(*context());
+
+        // Do any necesssary re-configuration to the output's number of channels.
+        output(0)-&gt;setNumberOfChannels(numberOfChannels);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -654,8 +654,6 @@
</span><span class="cx">                 14FFE31E0AE1963300136BF5 /* HTMLFrameElementBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14FFE31C0AE1963300136BF5 /* HTMLFrameElementBase.cpp */; };
</span><span class="cx">                 150524F41B712FF600696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 150524F01B712FF000696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.h */; };
</span><span class="cx">                 150524F51B712FF900696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 150524F11B712FF000696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.mm */; };
</span><del>-                150524F61B712FFC00696AA9 /* MediaStreamPrivateAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 150524F21B712FF000696AA9 /* MediaStreamPrivateAVFObjC.h */; };
-                150524F71B712FFF00696AA9 /* MediaStreamPrivateAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 150524F31B712FF000696AA9 /* MediaStreamPrivateAVFObjC.mm */; };
</del><span class="cx">                 15145B901B3A1CE000662BF7 /* MediaDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15145B8F1B3A1B3E00662BF7 /* MediaDeviceInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 15739BBA1B42012A00D258C1 /* JSMediaDevices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 15739BB81B42012200D258C1 /* JSMediaDevices.cpp */; };
</span><span class="cx">                 15739BBB1B42012D00D258C1 /* JSMediaDevices.h in Headers */ = {isa = PBXBuildFile; fileRef = 15739BB91B42012200D258C1 /* JSMediaDevices.h */; };
</span><span class="lines">@@ -7931,8 +7929,6 @@
</span><span class="cx">                 14FFE31C0AE1963300136BF5 /* HTMLFrameElementBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLFrameElementBase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 150524F01B712FF000696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlayerPrivateMediaStreamAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 150524F11B712FF000696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaPlayerPrivateMediaStreamAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                150524F21B712FF000696AA9 /* MediaStreamPrivateAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamPrivateAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
-                150524F31B712FF000696AA9 /* MediaStreamPrivateAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaStreamPrivateAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 15145B8F1B3A1B3E00662BF7 /* MediaDeviceInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaDeviceInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 15145B911B3A1D4C00662BF7 /* MediaDeviceInfo.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaDeviceInfo.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 15739BB81B42012200D258C1 /* JSMediaDevices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaDevices.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -22750,8 +22746,6 @@
</span><span class="cx">                                 150524F11B712FF000696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.mm */,
</span><span class="cx">                                 CDC8B5A5180474F70016E685 /* MediaSourcePrivateAVFObjC.h */,
</span><span class="cx">                                 CDC8B5A4180474F70016E685 /* MediaSourcePrivateAVFObjC.mm */,
</span><del>-                                150524F21B712FF000696AA9 /* MediaStreamPrivateAVFObjC.h */,
-                                150524F31B712FF000696AA9 /* MediaStreamPrivateAVFObjC.mm */,
</del><span class="cx">                                 7A29F57118C69514004D0F81 /* OutOfBandTextTrackPrivateAVF.h */,
</span><span class="cx">                                 CDC8B5A918047FF10016E685 /* SourceBufferPrivateAVFObjC.h */,
</span><span class="cx">                                 CDC8B5A818047FF10016E685 /* SourceBufferPrivateAVFObjC.mm */,
</span><span class="lines">@@ -26617,7 +26611,6 @@
</span><span class="cx">                                 078E093917D16B2C00420AA1 /* MediaStreamCreationClient.h in Headers */,
</span><span class="cx">                                 078E091617D14D1C00420AA1 /* MediaStreamEvent.h in Headers */,
</span><span class="cx">                                 078E093717D16B2C00420AA1 /* MediaStreamPrivate.h in Headers */,
</span><del>-                                150524F61B712FFC00696AA9 /* MediaStreamPrivateAVFObjC.h in Headers */,
</del><span class="cx">                                 078E091717D14D1C00420AA1 /* MediaStreamRegistry.h in Headers */,
</span><span class="cx">                                 078E091817D14D1C00420AA1 /* MediaStreamTrack.h in Headers */,
</span><span class="cx">                                 078E091917D14D1C00420AA1 /* MediaStreamTrackEvent.h in Headers */,
</span><span class="lines">@@ -30298,7 +30291,6 @@
</span><span class="cx">                                 0705851517FB0EEA005F2BCB /* MediaStreamCapabilities.cpp in Sources */,
</span><span class="cx">                                 078E090017D14CEE00420AA1 /* MediaStreamEvent.cpp in Sources */,
</span><span class="cx">                                 0711589117DF6F6600EDFE2B /* MediaStreamPrivate.cpp in Sources */,
</span><del>-                                150524F71B712FFF00696AA9 /* MediaStreamPrivateAVFObjC.mm in Sources */,
</del><span class="cx">                                 078E090117D14CEE00420AA1 /* MediaStreamRegistry.cpp in Sources */,
</span><span class="cx">                                 078E090217D14CEE00420AA1 /* MediaStreamTrack.cpp in Sources */,
</span><span class="cx">                                 078E090317D14CEE00420AA1 /* MediaStreamTrackEvent.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -72,6 +72,10 @@
</span><span class="cx"> #include &quot;MediaPlayerPrivateMediaSourceAVFObjC.h&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
+#include &quot;MediaPlayerPrivateMediaStreamAVFObjC.h&quot;
+#endif
+
</ins><span class="cx"> #endif // PLATFORM(COCOA)
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(WIN) &amp;&amp; USE(AVFOUNDATION) &amp;&amp; !USE(GSTREAMER)
</span><span class="lines">@@ -190,6 +194,10 @@
</span><span class="cx">         MediaPlayerPrivateMediaSourceAVFObjC::registerMediaEngine(addMediaEngine);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_STREAM)
+        MediaPlayerPrivateMediaStreamAVFObjC::registerMediaEngine(addMediaEngine);
+#endif
+
</ins><span class="cx"> #if PLATFORM(WIN)
</span><span class="cx">         MediaPlayerPrivateAVFoundationCF::registerMediaEngine(addMediaEngine);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaStreamAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -29,24 +29,22 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;MediaPlayerPrivate.h&quot;
</span><del>-#include &quot;MediaStreamPrivateAVFObjC.h&quot;
-#include &quot;SourceBufferPrivateClient.h&quot;
</del><ins>+#include &quot;MediaStreamPrivate.h&quot;
</ins><span class="cx"> #include &lt;wtf/MediaTime.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="cx"> 
</span><del>-OBJC_CLASS AVAsset;
-OBJC_CLASS AVCaptureVideoPreviewLayer;
</del><span class="cx"> OBJC_CLASS AVSampleBufferAudioRenderer;
</span><del>-OBJC_CLASS AVSampleBufferDisplayLayer;
-OBJC_CLASS AVSampleBufferRenderSynchronizer;
</del><span class="cx"> OBJC_CLASS AVStreamSession;
</span><ins>+typedef struct opaqueCMSampleBuffer *CMSampleBufferRef;
</ins><span class="cx"> 
</span><del>-typedef struct OpaqueCMTimebase* CMTimebaseRef;
-
</del><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class MediaPlayerPrivateMediaStreamAVFObjC : public MediaPlayerPrivateInterface {
</del><ins>+class AVVideoCaptureSource;
+class Clock;
+class MediaSourcePrivateClient;
+
+class MediaPlayerPrivateMediaStreamAVFObjC : public MediaPlayerPrivateInterface, public MediaStreamPrivate::Observer {
</ins><span class="cx"> public:
</span><span class="cx">     explicit MediaPlayerPrivateMediaStreamAVFObjC(MediaPlayer*);
</span><span class="cx">     virtual ~MediaPlayerPrivateMediaStreamAVFObjC();
</span><span class="lines">@@ -58,116 +56,109 @@
</span><span class="cx">     static void getSupportedTypes(HashSet&lt;String&gt;&amp; types);
</span><span class="cx">     static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&amp;);
</span><span class="cx"> 
</span><del>-    void addDisplayLayer(AVSampleBufferDisplayLayer*);
-    void removeDisplayLayer(AVSampleBufferDisplayLayer*);
-
-    void addAudioRenderer(AVSampleBufferAudioRenderer*);
-    void removeAudioRenderer(AVSampleBufferAudioRenderer*);
-
</del><span class="cx">     MediaPlayer::NetworkState networkState() const override;
</span><ins>+    void setNetworkState(MediaPlayer::NetworkState);
</ins><span class="cx">     MediaPlayer::ReadyState readyState() const override;
</span><span class="cx">     void setReadyState(MediaPlayer::ReadyState);
</span><span class="cx"> 
</span><del>-    void sizeChanged();
-    void characteristicsChanged();
-
</del><span class="cx">     WeakPtr&lt;MediaPlayerPrivateMediaStreamAVFObjC&gt; createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-        // MediaPlayerPrivateInterface
-        // FIXME(146853): Implement necessary conformations to standard in HTMLMediaElement for MediaStream 
-    void load(const String&amp;) override { };
</del><ins>+    // MediaPlayerPrivateInterface
+
+    // FIXME(146853): Implement necessary conformations to standard in HTMLMediaElement for MediaStream
+
+    void load(const String&amp;) override;
</ins><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><del>-    void load(const String&amp;, MediaSourcePrivateClient*) override { };
</del><ins>+    void load(const String&amp;, MediaSourcePrivateClient*) override;
</ins><span class="cx"> #endif
</span><del>-#if ENABLE(MEDIA_STREAM)
</del><span class="cx">     void load(MediaStreamPrivate&amp;) override;
</span><del>-#endif
</del><span class="cx">     void cancelLoad() override;
</span><span class="cx"> 
</span><span class="cx">     void prepareToPlay() override;
</span><del>-    PlatformMedia platformMedia() const override;
</del><span class="cx">     PlatformLayer* platformLayer() const override;
</span><span class="cx"> 
</span><span class="cx">     bool supportsFullscreen() const override { return true; }
</span><span class="cx"> 
</span><span class="cx">     void play() override;
</span><del>-    void playInternal();
-
</del><span class="cx">     void pause() override;
</span><del>-    void pauseInternal();
-
</del><span class="cx">     bool paused() const override;
</span><span class="cx"> 
</span><span class="cx">     void setVolume(float) override;
</span><del>-    bool supportsMuting() const override { return true; }
</del><ins>+    void internalSetVolume(float, bool);
</ins><span class="cx">     void setMuted(bool) override;
</span><ins>+    bool supportsMuting() const override { return true; }
</ins><span class="cx"> 
</span><del>-    bool supportsScanning() const override;
</del><ins>+    bool supportsScanning() const override { return false; }
</ins><span class="cx"> 
</span><del>-    FloatSize naturalSize() const override;
</del><ins>+    FloatSize naturalSize() const override { return m_intrinsicSize; }
</ins><span class="cx"> 
</span><span class="cx">     bool hasVideo() const override;
</span><span class="cx">     bool hasAudio() const override;
</span><span class="cx"> 
</span><del>-    void setVisible(bool) override;
</del><ins>+    void setVisible(bool) override { /* No-op */ }
</ins><span class="cx"> 
</span><span class="cx">     MediaTime durationMediaTime() const override;
</span><span class="cx">     MediaTime currentMediaTime() const override;
</span><span class="cx"> 
</span><del>-    void seekWithTolerance(const MediaTime&amp;, const MediaTime&amp;, const MediaTime&amp;) override { };
-    bool seeking() const override;
-    void setRateDouble(double) override;
</del><ins>+    bool seeking() const override { return false; }
</ins><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;PlatformTimeRanges&gt; seekable() const override;
</span><del>-    MediaTime maxMediaTimeSeekable() const override;
-    MediaTime minMediaTimeSeekable() const override;
</del><span class="cx">     std::unique_ptr&lt;PlatformTimeRanges&gt; buffered() const override;
</span><span class="cx"> 
</span><del>-    bool didLoadingProgress() const override;
</del><ins>+    bool didLoadingProgress() const override { return m_playing; }
</ins><span class="cx"> 
</span><del>-    void setSize(const IntSize&amp;) override;
</del><ins>+    void setSize(const IntSize&amp;) override { /* No-op */ }
</ins><span class="cx"> 
</span><span class="cx">     void paint(GraphicsContext&amp;, const FloatRect&amp;) override;
</span><span class="cx">     void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;) override;
</span><ins>+    bool metaDataAvailable() const { return m_mediaStreamPrivate &amp;&amp; m_readyState &gt;= MediaPlayer::HaveMetadata; }
</ins><span class="cx"> 
</span><del>-    bool supportsAcceleratedRendering() const override;
</del><ins>+    bool supportsAcceleratedRendering() const override { return true; }
</ins><span class="cx"> 
</span><del>-    MediaPlayer::MovieLoadType movieLoadType() const override;
</del><ins>+    bool hasSingleSecurityOrigin() const override { return true; }
</ins><span class="cx"> 
</span><del>-    void prepareForRendering() override;
</del><ins>+    MediaPlayer::MovieLoadType movieLoadType() const override { return MediaPlayer::LiveStream; }
</ins><span class="cx"> 
</span><span class="cx">     String engineDescription() const override;
</span><span class="cx"> 
</span><del>-    String languageOfPrimaryAudioTrack() const override;
</del><ins>+    size_t extraMemoryCost() const override { return 0; }
</ins><span class="cx"> 
</span><del>-    size_t extraMemoryCost() const override;
-
</del><span class="cx">     bool shouldBePlaying() const;
</span><span class="cx"> 
</span><del>-    RetainPtr&lt;CGImageRef&gt; createImageFromSampleBuffer(CMSampleBufferRef);
</del><ins>+    MediaPlayer::ReadyState currentReadyState();
</ins><span class="cx"> 
</span><del>-    friend class MediaStreamPrivateAVFObjC;
</del><ins>+    enum RenderingModeStatus {
+        RenderingModeUnchanged,
+        RenderingModeChanged,
+    };
+    RenderingModeStatus updateIntrinsicSize(const FloatSize&amp;);
</ins><span class="cx"> 
</span><del>-    MediaPlayer* m_player;
</del><ins>+    void createPreviewLayers();
+
+    void setPausedImageVisible(bool);
+
+    void scheduleDeferredTask(std::function&lt;void()&gt;);
+
+    // MediaStreamPrivate::Observer
+    void activeStatusChanged() override;
+    void characteristicsChanged() override;
+
+    MediaPlayer* m_player { nullptr };
</ins><span class="cx">     WeakPtrFactory&lt;MediaPlayerPrivateMediaStreamAVFObjC&gt; m_weakPtrFactory;
</span><del>-    RefPtr&lt;MediaStreamPrivateAVFObjC&gt; m_MediaStreamPrivate;
-    RetainPtr&lt;AVAsset&gt; m_asset;
-    RetainPtr&lt;AVCaptureVideoPreviewLayer&gt; m_previewLayer;
-    RetainPtr&lt;AVSampleBufferDisplayLayer&gt; m_sampleBufferDisplayLayer;
-    Vector&lt;RetainPtr&lt;AVSampleBufferAudioRenderer&gt;&gt; m_sampleBufferAudioRenderers;
-    RetainPtr&lt;CGImageRef&gt; m_lastImage;
-    RetainPtr&lt;id&gt; m_timeJumpedObserver;
-    RetainPtr&lt;id&gt; m_durationObserver;
-    RetainPtr&lt;AVStreamSession&gt; m_streamSession;
-    MediaPlayer::NetworkState m_networkState;
-    MediaPlayer::ReadyState m_readyState;
-    MediaTime m_lastSeekTime;
-    double m_rate;
-    bool m_playing;
-    bool m_seeking;
-    bool m_seekCompleted;
-    mutable bool m_loadingProgressed;
</del><ins>+    RefPtr&lt;MediaStreamPrivate&gt; m_mediaStreamPrivate;
+    mutable RetainPtr&lt;CALayer&gt; m_previewLayer;
+    mutable RetainPtr&lt;PlatformLayer&gt; m_videoBackgroundLayer;
+    RetainPtr&lt;CGImageRef&gt; m_pausedImage;
+    std::unique_ptr&lt;Clock&gt; m_clock;
+    MediaPlayer::NetworkState m_networkState { MediaPlayer::Empty };
+    MediaPlayer::ReadyState m_readyState { MediaPlayer::HaveNothing };
+    FloatSize m_intrinsicSize;
+    float m_volume { 1 };
+    bool m_playing { false };
+    bool m_muted { false };
+    bool m_waitingForNewFrame {false };
+    bool m_haveEverPlayed { false };
</ins><span class="cx"> };
</span><span class="cx">     
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaStreamAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -28,18 +28,14 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><ins>+#import &quot;AVAudioCaptureSource.h&quot;
</ins><span class="cx"> #import &quot;AVVideoCaptureSource.h&quot;
</span><del>-#import &quot;FileSystem.h&quot;
</del><ins>+#import &quot;Clock.h&quot;
+#import &quot;GraphicsContext.h&quot;
</ins><span class="cx"> #import &quot;Logging.h&quot;
</span><span class="cx"> #import &quot;MediaStreamPrivate.h&quot;
</span><del>-#import &quot;MediaStreamPrivateAVFObjC.h&quot;
-#import &quot;MediaTimeAVFoundation.h&quot;
-#import &quot;PlatformClockCM.h&quot;
-#import &quot;WebCoreSystemInterface.h&quot;
-#import &lt;AVFoundation/AVAsset.h&gt;
-#import &lt;AVFoundation/AVCaptureVideoPreviewLayer.h&gt;
-#import &lt;AVFoundation/AVTime.h&gt;
</del><span class="cx"> #import &lt;QuartzCore/CALayer.h&gt;
</span><ins>+#import &lt;QuartzCore/CATransaction.h&gt;
</ins><span class="cx"> #import &lt;objc_runtime.h&gt;
</span><span class="cx"> #import &lt;wtf/MainThread.h&gt;
</span><span class="cx"> #import &lt;wtf/NeverDestroyed.h&gt;
</span><span class="lines">@@ -50,18 +46,6 @@
</span><span class="cx"> 
</span><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
</span><span class="cx"> 
</span><del>-SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVAsset)
-SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVCaptureVideoPreviewLayer)
-SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVURLAsset)
-SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVStreamSession);
-
-#pragma mark -
-#pragma mark AVStreamSession
-
-@interface AVStreamSession : NSObject
-- (instancetype)initWithStorageDirectoryAtURL:(NSURL *)storageDirectory;
-@end
-
</del><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> #pragma mark -
</span><span class="lines">@@ -70,19 +54,16 @@
</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_networkState(MediaPlayer::Idle)
-    , m_readyState(MediaPlayer::HaveNothing)
-    , m_rate(1)
-    , m_playing(0)
-    , m_seeking(false)
-    , m_seekCompleted(true)
-    , m_loadingProgressed(false)
</del><ins>+    , m_clock(Clock::create())
</ins><span class="cx"> {
</span><del>-
</del><ins>+    LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC(%p)&quot;, this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC()
</span><span class="cx"> {
</span><ins>+    LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC(%p)&quot;, this);
+    if (m_mediaStreamPrivate)
+        m_mediaStreamPrivate-&gt;removeObserver(*this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #pragma mark -
</span><span class="lines">@@ -97,31 +78,15 @@
</span><span class="cx"> 
</span><span class="cx"> bool MediaPlayerPrivateMediaStreamAVFObjC::isAvailable()
</span><span class="cx"> {
</span><del>-    return AVFoundationLibrary()
-        &amp;&amp; isCoreMediaFrameworkAvailable();
</del><ins>+    return AVFoundationLibrary() &amp;&amp; isCoreMediaFrameworkAvailable();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static const HashSet&lt;String&gt;&amp; mimeTypeCache()
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::getSupportedTypes(HashSet&lt;String&gt;&amp; types)
</ins><span class="cx"> {
</span><span class="cx">     static NeverDestroyed&lt;HashSet&lt;String&gt;&gt; cache;
</span><del>-    static bool typeListInitialized = false;
-
-    if (typeListInitialized)
-        return cache;
-    typeListInitialized = true;
-
-    NSArray *types = [getAVURLAssetClass() audiovisualMIMETypes];
-    for (NSString *mimeType in types)
-        cache.get().add(mimeType);
-
-    return cache;
</del><ins>+    types = cache;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::getSupportedTypes(HashSet&lt;String&gt;&amp; types)
-{
-    types = mimeTypeCache();
-}
-
</del><span class="cx"> MediaPlayer::SupportsType MediaPlayerPrivateMediaStreamAVFObjC::supportsType(const MediaEngineSupportParameters&amp; parameters)
</span><span class="cx"> {
</span><span class="cx">     if (parameters.isMediaStream)
</span><span class="lines">@@ -133,148 +98,176 @@
</span><span class="cx"> #pragma mark -
</span><span class="cx"> #pragma mark MediaPlayerPrivateInterface Overrides
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::load(const String&amp;)
+{
+    // This media engine only supports MediaStream URLs.
+    scheduleDeferredTask([this] {
+        setNetworkState(MediaPlayer::FormatError);
+    });
+}
+
+#if ENABLE(MEDIA_SOURCE)
+void MediaPlayerPrivateMediaStreamAVFObjC::load(const String&amp;, MediaSourcePrivateClient*)
+{
+    // This media engine only supports MediaStream URLs.
+    scheduleDeferredTask([this] {
+        setNetworkState(MediaPlayer::FormatError);
+    });
+}
+#endif
+
</ins><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::load(MediaStreamPrivate&amp; stream)
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::load(%p)&quot;, this);
</span><span class="cx"> 
</span><del>-    m_MediaStreamPrivate = MediaStreamPrivateAVFObjC::create(*this, stream);
-    for (auto track : stream.tracks()) {
-        m_MediaStreamPrivate-&gt;addTrack(WTF::move(track));
-        if (!track-&gt;ended()) {
-            track-&gt;source()-&gt;startProducingData();
-            track-&gt;setEnabled(true);
-        }
-    }
</del><ins>+    m_mediaStreamPrivate = &amp;stream;
+    m_mediaStreamPrivate-&gt;addObserver(*this);
+    m_mediaStreamPrivate-&gt;startProducingData();
+
</ins><span class="cx">     m_previewLayer = nullptr;
</span><del>-    for (auto&amp; track : m_MediaStreamPrivate-&gt;tracks()) {
-        if (track-&gt;type() == RealtimeMediaSource::Type::Video)
-            m_previewLayer = static_cast&lt;AVVideoCaptureSource*&gt;(track-&gt;source())-&gt;previewLayer();
-    }
-    m_player-&gt;client().mediaPlayerRenderingModeChanged(m_player);
</del><ins>+
+    scheduleDeferredTask([this] {
+        setNetworkState(MediaPlayer::Idle);
+        if (m_readyState &lt; MediaPlayer::ReadyState::HaveMetadata)
+            this-&gt;setReadyState(MediaPlayer::ReadyState::HaveMetadata);
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::cancelLoad()
</span><span class="cx"> {
</span><ins>+    LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::cancelLoad(%p)&quot;, this);
+    pause();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::prepareToPlay()
</span><span class="cx"> {
</span><ins>+    LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::prepareToPlay(%p)&quot;, this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-PlatformMedia MediaPlayerPrivateMediaStreamAVFObjC::platformMedia() const
</del><ins>+PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
</ins><span class="cx"> {
</span><del>-    PlatformMedia pm;
-    pm.type = PlatformMedia::AVFoundationAssetType;
-    pm.media.avfAsset = m_asset.get();
-    return pm;
</del><ins>+    if (!m_videoBackgroundLayer)
+        return nullptr;
+
+    return m_videoBackgroundLayer.get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::setPausedImageVisible(bool visible)
</ins><span class="cx"> {
</span><del>-    if (!m_previewLayer)
-        return nullptr;
-    return static_cast&lt;PlatformLayer*&gt;(m_previewLayer);
</del><ins>+    if (!metaDataAvailable() || !m_videoBackgroundLayer)
+        return;
+
+    if (visible == m_previewLayer.get().hidden)
+        return;
+
+    [CATransaction begin];
+    [CATransaction setAnimationDuration:0];
+    [CATransaction setDisableActions:YES];
+
+    do {
+        if (visible) {
+            m_clock-&gt;stop();
+
+            RefPtr&lt;Image&gt; image = m_mediaStreamPrivate-&gt;currentFrameImage();
+            if (!image)
+                break;
+
+            m_pausedImage = image-&gt;getCGImageRef();
+            if (!m_pausedImage)
+                break;
+
+            m_videoBackgroundLayer.get().contents = (id)m_pausedImage.get();
+            m_previewLayer.get().hidden = true;
+            m_waitingForNewFrame = false;
+        } else {
+            if (!m_mediaStreamPrivate-&gt;isProducingData()) {
+                m_waitingForNewFrame = true;
+                break;
+            }
+
+            m_clock-&gt;start();
+            m_waitingForNewFrame = false;
+            m_previewLayer.get().hidden = false;
+            m_videoBackgroundLayer.get().contents = nil;
+            m_pausedImage = nullptr;
+        }
+    } while (0);
+
+    [CATransaction commit];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::play()
</span><span class="cx"> {
</span><del>-    auto weakThis = createWeakPtr();
-    callOnMainThread([weakThis] {
-        if (!weakThis)
-            return;
-        weakThis.get()-&gt;playInternal();
-    });
-}
</del><ins>+    LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::play(%p)&quot;, this);
</ins><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::playInternal()
-{
</del><ins>+    if (!metaDataAvailable())
+        return;
+
</ins><span class="cx">     m_playing = true;
</span><del>-
-    for (auto&amp; track : m_MediaStreamPrivate-&gt;tracks())
-        track-&gt;source()-&gt;startProducingData();
</del><ins>+    m_haveEverPlayed = true;
+    setPausedImageVisible(false);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::pause()
</span><span class="cx"> {
</span><del>-    auto weakThis = createWeakPtr();
-    callOnMainThread([weakThis] {
-        if (!weakThis)
-            return;
-        weakThis.get()-&gt;pauseInternal();
-    });
-}
</del><ins>+    LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::pause(%p)&quot;, this);
</ins><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::pauseInternal()
-{
</del><ins>+    if (!metaDataAvailable())
+        return;
+
+    setPausedImageVisible(true);
</ins><span class="cx">     m_playing = false;
</span><del>-
-    for (auto&amp; track : m_MediaStreamPrivate-&gt;tracks())
-        track-&gt;source()-&gt;stopProducingData();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool MediaPlayerPrivateMediaStreamAVFObjC::paused() const
</span><span class="cx"> {
</span><del>-    // Shouldn't be able to pause streams
-    return false;
</del><ins>+    return !m_playing;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::setVolume(float)
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::internalSetVolume(float volume, bool internal)
</ins><span class="cx"> {
</span><ins>+    if (!internal)
+        m_volume = volume;
+
+    if (!metaDataAvailable())
+        return;
+
+    // FIXME: Set volume once we actually play audio.
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool MediaPlayerPrivateMediaStreamAVFObjC::supportsScanning() const
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::setVolume(float volume)
</ins><span class="cx"> {
</span><del>-    return true;
</del><ins>+    internalSetVolume(volume, false);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::setMuted(bool muted)
</span><span class="cx"> {
</span><del>-    for (auto&amp; track : m_MediaStreamPrivate-&gt;tracks()) {
-        if (track-&gt;type() == RealtimeMediaSource::Type::Audio)
-            track-&gt;source()-&gt;setMuted(muted);
-    }
-}
</del><ins>+    LOG(Media, &quot;MediaPlayerPrivateMediaStreamAVFObjC::setMuted(%p)&quot;, this);
</ins><span class="cx"> 
</span><del>-FloatSize MediaPlayerPrivateMediaStreamAVFObjC::naturalSize() const
-{
-    FloatSize floatSize(0, 0);
-    for (auto&amp; track : m_MediaStreamPrivate-&gt;tracks()) {
-        if (track-&gt;type() == RealtimeMediaSource::Type::Video) {
-            AVVideoCaptureSource* source = (AVVideoCaptureSource*)track-&gt;source();
-            if (!source-&gt;stopped() &amp;&amp; track-&gt;enabled()) {
-                if (source-&gt;width() &gt; floatSize.width())
-                    floatSize.setWidth(source-&gt;width());
-                if (source-&gt;height() &gt; floatSize.height())
-                    floatSize.setHeight(source-&gt;height());
-            }
-        }
-    }
-    return floatSize;
</del><ins>+    if (muted == m_muted)
+        return;
+
+    m_muted = muted;
+    
+    internalSetVolume(muted ? 0 : m_volume, true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool MediaPlayerPrivateMediaStreamAVFObjC::hasVideo() const
</span><span class="cx"> {
</span><del>-    for (auto&amp; track : m_MediaStreamPrivate-&gt;tracks()) {
-        if (track-&gt;type() == RealtimeMediaSource::Type::Video)
-            return true;
-    }
-    return false;
</del><ins>+    if (!metaDataAvailable())
+        return false;
+    
+    return m_mediaStreamPrivate-&gt;hasVideo();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool MediaPlayerPrivateMediaStreamAVFObjC::hasAudio() const
</span><span class="cx"> {
</span><del>-    for (auto&amp; track : m_MediaStreamPrivate-&gt;tracks()) {
-        if (track-&gt;type() == RealtimeMediaSource::Type::Audio)
-            return true;
-    }
-    return false;
</del><ins>+    if (!metaDataAvailable())
+        return false;
+    
+    return m_mediaStreamPrivate-&gt;hasAudio();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::setVisible(bool)
-{
-    // No-op.
-}
-
</del><span class="cx"> MediaTime MediaPlayerPrivateMediaStreamAVFObjC::durationMediaTime() const
</span><span class="cx"> {
</span><span class="cx">     return MediaTime::positiveInfiniteTime();
</span><span class="lines">@@ -282,21 +275,9 @@
</span><span class="cx"> 
</span><span class="cx"> MediaTime MediaPlayerPrivateMediaStreamAVFObjC::currentMediaTime() const
</span><span class="cx"> {
</span><del>-    // FIXME(147125): Must implement this later
-    return MediaTime::zeroTime();
</del><ins>+    return MediaTime::createWithDouble(m_clock-&gt;currentTime());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool MediaPlayerPrivateMediaStreamAVFObjC::seeking() const
-{
-    // MediaStream is unseekable
-    return false;
-}
-
-void MediaPlayerPrivateMediaStreamAVFObjC::setRateDouble(double)
-{
-    // MediaStream is unseekable; therefore, cannot set rate
-}
-
</del><span class="cx"> MediaPlayer::NetworkState MediaPlayerPrivateMediaStreamAVFObjC::networkState() const
</span><span class="cx"> {
</span><span class="cx">     return m_networkState;
</span><span class="lines">@@ -307,60 +288,107 @@
</span><span class="cx">     return m_readyState;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::sizeChanged()
</del><ins>+MediaPlayer::ReadyState MediaPlayerPrivateMediaStreamAVFObjC::currentReadyState()
</ins><span class="cx"> {
</span><del>-    m_player-&gt;sizeChanged();
</del><ins>+    if (m_mediaStreamPrivate) {
+        if (m_mediaStreamPrivate-&gt;active())
+            return MediaPlayer::ReadyState::HaveEnoughData;
+
+        return MediaPlayer::ReadyState::HaveCurrentData;
+    }
+
+    return MediaPlayer::ReadyState::HaveNothing;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;PlatformTimeRanges&gt; MediaPlayerPrivateMediaStreamAVFObjC::seekable() const
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::activeStatusChanged()
</ins><span class="cx"> {
</span><del>-    return std::make_unique&lt;PlatformTimeRanges&gt;(minMediaTimeSeekable(), maxMediaTimeSeekable());
</del><ins>+    MediaPlayer::ReadyState newReadyState = currentReadyState();
+
+    scheduleDeferredTask([this, newReadyState] {
+        if (newReadyState != m_readyState)
+            setReadyState(newReadyState);
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MediaTime MediaPlayerPrivateMediaStreamAVFObjC::maxMediaTimeSeekable() const
</del><ins>+MediaPlayerPrivateMediaStreamAVFObjC::RenderingModeStatus MediaPlayerPrivateMediaStreamAVFObjC::updateIntrinsicSize(const FloatSize&amp; size)
</ins><span class="cx"> {
</span><del>-    return durationMediaTime();
</del><ins>+    if (size == m_intrinsicSize)
+        return RenderingModeUnchanged;
+
+    m_intrinsicSize = size;
+
+    if (m_videoBackgroundLayer || !m_player || !m_player-&gt;client().mediaPlayerRenderingCanBeAccelerated(m_player))
+        return RenderingModeUnchanged;
+
+    if (!m_mediaStreamPrivate || !m_mediaStreamPrivate-&gt;platformLayer())
+        return RenderingModeUnchanged;
+
+    createPreviewLayers();
+
+    return RenderingModeChanged;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MediaTime MediaPlayerPrivateMediaStreamAVFObjC::minMediaTimeSeekable() const
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::createPreviewLayers()
</ins><span class="cx"> {
</span><del>-    return startTime();
</del><ins>+    if (m_videoBackgroundLayer)
+        return;
+
+    m_videoBackgroundLayer = adoptNS([[CALayer alloc] init]);
+#ifndef NDEBUG
+    m_videoBackgroundLayer.get().name = @&quot;MediaPlayerPrivateMediaStreamAVFObjC preview background layer&quot;;
+#endif
+
+    m_previewLayer = m_mediaStreamPrivate-&gt;platformLayer();
+    m_previewLayer.get().contentsGravity = kCAGravityResize;
+    m_previewLayer.get().anchorPoint = CGPointZero;
+#if !PLATFORM(IOS)
+    m_previewLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+#endif
+    if (!m_playing)
+        m_previewLayer.get().hidden = true;
+
+    [m_videoBackgroundLayer addSublayer:m_previewLayer.get()];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;PlatformTimeRanges&gt; MediaPlayerPrivateMediaStreamAVFObjC::buffered() const
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::characteristicsChanged()
</ins><span class="cx"> {
</span><del>-    return std::make_unique&lt;PlatformTimeRanges&gt;();
-}
</del><ins>+    RenderingModeStatus status = RenderingModeUnchanged;
+    bool sizeChanged = false;
</ins><span class="cx"> 
</span><del>-bool MediaPlayerPrivateMediaStreamAVFObjC::didLoadingProgress() const
-{
-    bool loadingProgressed = m_loadingProgressed;
-    m_loadingProgressed = false;
-    return loadingProgressed;
</del><ins>+    FloatSize intrinsicSize = m_mediaStreamPrivate-&gt;intrinsicSize();
+    if (intrinsicSize.height() != m_intrinsicSize.height() || intrinsicSize.width() != m_intrinsicSize.width()) {
+        status = updateIntrinsicSize(intrinsicSize);
+        sizeChanged = true;
+    }
+
+    if (m_waitingForNewFrame &amp;&amp; m_mediaStreamPrivate-&gt;isProducingData())
+        setPausedImageVisible(false);
+
+    MediaPlayer::ReadyState newReadyState = currentReadyState();
+    scheduleDeferredTask([this, sizeChanged, newReadyState, status] {
+        if (newReadyState != m_readyState)
+            setReadyState(newReadyState);
+
+        if (!m_player)
+            return;
+
+        m_player-&gt;characteristicChanged();
+        if (sizeChanged) {
+            m_player-&gt;sizeChanged();
+            if (status == RenderingModeChanged)
+                m_player-&gt;client().mediaPlayerRenderingModeChanged(m_player);
+        }
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::setSize(const IntSize&amp;)
</del><ins>+std::unique_ptr&lt;PlatformTimeRanges&gt; MediaPlayerPrivateMediaStreamAVFObjC::seekable() const
</ins><span class="cx"> {
</span><del>-    // No-op.
</del><ins>+    return std::make_unique&lt;PlatformTimeRanges&gt;();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RetainPtr&lt;CGImageRef&gt; MediaPlayerPrivateMediaStreamAVFObjC::createImageFromSampleBuffer(CMSampleBufferRef sampleBuffer)
</del><ins>+std::unique_ptr&lt;PlatformTimeRanges&gt; MediaPlayerPrivateMediaStreamAVFObjC::buffered() const
</ins><span class="cx"> {
</span><del>-    CVPixelBufferRef imageBuffer = static_cast&lt;CVPixelBufferRef&gt;(CMSampleBufferGetImageBuffer(sampleBuffer));
-    CVPixelBufferLockBaseAddress(imageBuffer, 0);
-    
-    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
-    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
-    size_t width = CVPixelBufferGetWidth(imageBuffer);
-    size_t height = CVPixelBufferGetHeight(imageBuffer);
-    
-    RetainPtr&lt;CGColorSpaceRef&gt; colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
-    RetainPtr&lt;CGDataProviderRef&gt; provider = adoptCF(CGDataProviderCreateWithData(NULL, baseAddress, bytesPerRow * height, NULL));
-    RetainPtr&lt;CGImageRef&gt; quartzImage = adoptCF(CGImageCreate(width, height, 8, 32, bytesPerRow, colorSpace.get(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, provider.get(), NULL, true, kCGRenderingIntentDefault));
-    
-    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
-    
-    return quartzImage;
</del><ins>+    return std::make_unique&lt;PlatformTimeRanges&gt;();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::paint(GraphicsContext&amp; context, const FloatRect&amp; rect)
</span><span class="lines">@@ -368,43 +396,29 @@
</span><span class="cx">     paintCurrentFrameInContext(context, rect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;)
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::paintCurrentFrameInContext(GraphicsContext&amp; context, const FloatRect&amp; rect)
</ins><span class="cx"> {
</span><del>-    // FIXME(125157): Implement painting.
-}
</del><ins>+    if (!metaDataAvailable() || context.paintingDisabled() || !m_haveEverPlayed)
+        return;
</ins><span class="cx"> 
</span><del>-bool MediaPlayerPrivateMediaStreamAVFObjC::supportsAcceleratedRendering() const
-{
-    return true;
</del><ins>+    if (m_playing)
+        m_mediaStreamPrivate-&gt;paintCurrentFrameInContext(context, rect);
+    else if (m_pausedImage) {
+        GraphicsContextStateSaver stateSaver(context);
+        context.translate(rect.x(), rect.y() + rect.height());
+        context.scale(FloatSize(1, -1));
+        context.setImageInterpolationQuality(InterpolationLow);
+        IntRect paintRect(IntPoint(0, 0), IntSize(rect.width(), rect.height()));
+        CGContextDrawImage(context.platformContext(), CGRectMake(0, 0, paintRect.width(), paintRect.height()), m_pausedImage.get());
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MediaPlayer::MovieLoadType MediaPlayerPrivateMediaStreamAVFObjC::movieLoadType() const
-{
-    return MediaPlayer::LiveStream;
-}
-
-void MediaPlayerPrivateMediaStreamAVFObjC::prepareForRendering()
-{
-    // No-op.
-}
-
</del><span class="cx"> String MediaPlayerPrivateMediaStreamAVFObjC::engineDescription() const
</span><span class="cx"> {
</span><span class="cx">     static NeverDestroyed&lt;String&gt; description(ASCIILiteral(&quot;AVFoundation MediaStream Engine&quot;));
</span><span class="cx">     return description;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String MediaPlayerPrivateMediaStreamAVFObjC::languageOfPrimaryAudioTrack() const
-{
-    // FIXME(125158): implement languageOfPrimaryAudioTrack()
-    return emptyString();
-}
-
-size_t MediaPlayerPrivateMediaStreamAVFObjC::extraMemoryCost() const
-{
-    return 0;
-}
-
</del><span class="cx"> bool MediaPlayerPrivateMediaStreamAVFObjC::shouldBePlaying() const
</span><span class="cx"> {
</span><span class="cx">     return m_playing &amp;&amp; m_readyState &gt;= MediaPlayer::HaveFutureData;
</span><span class="lines">@@ -420,6 +434,27 @@
</span><span class="cx">     m_player-&gt;readyStateChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::setNetworkState(MediaPlayer::NetworkState networkState)
+{
+    if (m_networkState == networkState)
+        return;
+
+    m_networkState = networkState;
+    m_player-&gt;networkStateChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask(std::function&lt;void()&gt; function)
+{
+    ASSERT(function);
+    auto weakThis = createWeakPtr();
+    callOnMainThread([weakThis, function] {
+        if (!weakThis)
+            return;
+
+        function();
+    });
+}
+
+}
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaStreamPrivateAVFObjCh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -1,87 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' 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 APPLE INC. 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.
- */
-
-#ifndef MediaStreamPrivateAVFObjC_h
-#define MediaStreamPrivateAVFObjC_h
-
-#if ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
-
-#include &quot;MediaPlayer.h&quot;
-#include &quot;MediaStreamPrivate.h&quot;
-#include &lt;wtf/Deque.h&gt;
-#include &lt;wtf/HashMap.h&gt;
-#include &lt;wtf/MediaTime.h&gt;
-#include &lt;wtf/RefPtr.h&gt;
-#include &lt;wtf/RetainPtr.h&gt;
-#include &lt;wtf/Vector.h&gt;
-
-OBJC_CLASS AVAsset;
-OBJC_CLASS AVStreamDataParser;
-OBJC_CLASS NSError;
-OBJC_CLASS NSObject;
-typedef struct opaqueCMSampleBuffer *CMSampleBufferRef;
-
-namespace WebCore {
-
-class CDMSession;
-class MediaPlayerPrivateMediaStreamAVFObjC;
-class MediaStreamPrivate;
-class MediaStreamPrivateClient;
-class PlatformTimeRanges;
-class TimeRanges;
-
-class MediaStreamPrivateAVFObjC final : public MediaStreamPrivate {
-public:
-    static RefPtr&lt;MediaStreamPrivateAVFObjC&gt; create(MediaPlayerPrivateMediaStreamAVFObjC&amp;, MediaStreamPrivate&amp;);
-    virtual ~MediaStreamPrivateAVFObjC();
-
-    MediaPlayerPrivateMediaStreamAVFObjC* player() const { return m_player; }
-
-    virtual MediaStreamPrivateClient* client() const { return m_client.get(); }
-    virtual void setClient(MediaStreamPrivateClient* client) { m_client = client; }
-
-    MediaTime duration();
-    std::unique_ptr&lt;PlatformTimeRanges&gt; buffered();
-
-    bool hasAudio() const;
-    bool hasVideo() const;
-
-    void setReadyState(MediaPlayer::ReadyState);
-    FloatSize naturalSize() const;
-
-    MediaPlayer::ReadyState readyState() const;
-
-private:
-    MediaStreamPrivateAVFObjC(MediaPlayerPrivateMediaStreamAVFObjC&amp;, MediaStreamPrivate&amp;);
-
-    MediaPlayerPrivateMediaStreamAVFObjC* m_player;
-    RefPtr&lt;MediaStreamPrivateClient&gt; m_client;
-};
-    
-}
-
-#endif // ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaStreamPrivateAVFObjCmm"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.mm (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.mm        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaStreamPrivateAVFObjC.mm        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -1,98 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' 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 APPLE INC. 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.
- */
-
-#include &quot;config.h&quot;
-#include &quot;MediaStreamPrivateAVFObjC.h&quot;
-
-#if ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
-
-#import &quot;ContentType.h&quot;
-#import &quot;ExceptionCodePlaceholder.h&quot;
-#import &quot;MediaPlayerPrivateMediaStreamAVFObjC.h&quot;
-#import &quot;MediaStreamPrivate.h&quot;
-#import &quot;SoftLinking.h&quot;
-#import &quot;SourceBufferPrivateAVFObjC.h&quot;
-#import &lt;objc/runtime.h&gt;
-#import &lt;wtf/text/AtomicString.h&gt;
-#import &lt;wtf/text/StringBuilder.h&gt;
-
-namespace WebCore {
-
-#pragma mark -
-#pragma mark MediaStreamPrivateAVFObjC
-
-RefPtr&lt;MediaStreamPrivateAVFObjC&gt; MediaStreamPrivateAVFObjC::create(MediaPlayerPrivateMediaStreamAVFObjC&amp; parent, MediaStreamPrivate&amp; stream)
-{
-    return adoptRef(new MediaStreamPrivateAVFObjC(parent, stream));
-}
-
-MediaStreamPrivateAVFObjC::MediaStreamPrivateAVFObjC(MediaPlayerPrivateMediaStreamAVFObjC&amp; parent, MediaStreamPrivate&amp; stream)
-    : MediaStreamPrivate(*stream.client())
-    , m_player(&amp;parent)
-{
-}
-
-MediaStreamPrivateAVFObjC::~MediaStreamPrivateAVFObjC()
-{
-}
-
-MediaTime MediaStreamPrivateAVFObjC::duration()
-{
-    return MediaTime::positiveInfiniteTime();
-}
-
-std::unique_ptr&lt;PlatformTimeRanges&gt; MediaStreamPrivateAVFObjC::buffered()
-{
-    return std::unique_ptr&lt;PlatformTimeRanges&gt;();
-}
-
-MediaPlayer::ReadyState MediaStreamPrivateAVFObjC::readyState() const
-{
-    return m_player-&gt;readyState();
-}
-
-void MediaStreamPrivateAVFObjC::setReadyState(MediaPlayer::ReadyState readyState)
-{
-    m_player-&gt;setReadyState(readyState);
-}
-
-bool MediaStreamPrivateAVFObjC::hasAudio() const
-{
-    return m_player-&gt;hasAudio();
-}
-
-bool MediaStreamPrivateAVFObjC::hasVideo() const
-{
-    return m_player-&gt;hasVideo();
-}
-
-FloatSize MediaStreamPrivateAVFObjC::naturalSize() const
-{
-    return m_player-&gt;naturalSize();
-}
-    
-}
-
-#endif // ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -2,6 +2,7 @@
</span><span class="cx">  * Copyright (C) 2011, 2015 Ericsson AB. All rights reserved.
</span><span class="cx">  * Copyright (C) 2013 Google Inc. All rights reserved.
</span><span class="cx">  * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
</span><ins>+ * Copyright (C) 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions are
</span><span class="lines">@@ -31,12 +32,14 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;config.h&quot;
</span><ins>+#include &quot;MediaStreamPrivate.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><del>-#include &quot;MediaStreamPrivate.h&quot;
-
</del><ins>+#include &quot;GraphicsContext.h&quot;
+#include &quot;IntRect.h&quot;
</ins><span class="cx"> #include &quot;UUID.h&quot;
</span><ins>+#include &lt;wtf/MainThread.h&gt;
</ins><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -62,27 +65,37 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MediaStreamPrivate::MediaStreamPrivate(const String&amp; id, const MediaStreamTrackPrivateVector&amp; tracks)
</span><del>-    : m_id(id)
</del><ins>+    : m_weakPtrFactory(this)
+    , m_id(id)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_id.isEmpty());
</span><span class="cx"> 
</span><del>-    for (auto&amp; track : tracks)
</del><ins>+    for (auto&amp; track : tracks) {
+        track-&gt;addObserver(*this);
</ins><span class="cx">         m_trackSet.add(track-&gt;id(), track);
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     updateActiveState(NotifyClientOption::DontNotify);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MediaStreamPrivate::MediaStreamPrivate(MediaStreamPrivateClient&amp; client)
-    : m_client(&amp;client)
</del><ins>+MediaStreamPrivate::~MediaStreamPrivate()
</ins><span class="cx"> {
</span><ins>+    for (auto&amp; track : m_trackSet.values())
+        track-&gt;removeObserver(*this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MediaStreamPrivate::~MediaStreamPrivate()
</del><ins>+void MediaStreamPrivate::addObserver(MediaStreamPrivate::Observer&amp; observer)
</ins><span class="cx"> {
</span><del>-    m_client = nullptr;
-    m_isActive = false;
</del><ins>+    m_observers.append(&amp;observer);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaStreamPrivate::removeObserver(MediaStreamPrivate::Observer&amp; observer)
+{
+    size_t pos = m_observers.find(&amp;observer);
+    if (pos != notFound)
+        m_observers.remove(pos);
+}
+
</ins><span class="cx"> MediaStreamTrackPrivateVector MediaStreamPrivate::tracks() const
</span><span class="cx"> {
</span><span class="cx">     MediaStreamTrackPrivateVector tracks;
</span><span class="lines">@@ -94,21 +107,29 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaStreamPrivate::updateActiveState(NotifyClientOption notifyClientOption)
</span><span class="cx"> {
</span><del>-    // A stream is active if it has at least one un-ended track.
</del><span class="cx">     bool newActiveState = false;
</span><ins>+    m_activeVideoTrack = nullptr;
</ins><span class="cx">     for (auto&amp; track : m_trackSet.values()) {
</span><ins>+
</ins><span class="cx">         if (!track-&gt;ended()) {
</span><span class="cx">             newActiveState = true;
</span><del>-            break;
</del><ins>+            if (track-&gt;source()-&gt;type() == RealtimeMediaSource::Type::Video) {
+                m_activeVideoTrack = track.get();
+                break;
+            }
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // A stream is active if it has at least one un-ended track.
</ins><span class="cx">     if (newActiveState == m_isActive)
</span><span class="cx">         return;
</span><ins>+
</ins><span class="cx">     m_isActive = newActiveState;
</span><span class="cx"> 
</span><del>-    if (m_client &amp;&amp; notifyClientOption == NotifyClientOption::Notify)
-        m_client-&gt;activeStatusChanged();
</del><ins>+    if (notifyClientOption == NotifyClientOption::Notify) {
+        for (auto&amp; observer : m_observers)
+            observer-&gt;activeStatusChanged();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaStreamPrivate::addTrack(RefPtr&lt;MediaStreamTrackPrivate&gt;&amp;&amp; track, NotifyClientOption notifyClientOption)
</span><span class="lines">@@ -119,8 +140,10 @@
</span><span class="cx">     track-&gt;addObserver(*this);
</span><span class="cx">     m_trackSet.add(track-&gt;id(), track);
</span><span class="cx"> 
</span><del>-    if (m_client &amp;&amp; notifyClientOption == NotifyClientOption::Notify)
-        m_client-&gt;didAddTrack(*track.get());
</del><ins>+    if (notifyClientOption == NotifyClientOption::Notify) {
+        for (auto&amp; observer : m_observers)
+            observer-&gt;didAddTrack(*track.get());
+    }
</ins><span class="cx"> 
</span><span class="cx">     updateActiveState(notifyClientOption);
</span><span class="cx"> }
</span><span class="lines">@@ -132,12 +155,142 @@
</span><span class="cx"> 
</span><span class="cx">     track.removeObserver(*this);
</span><span class="cx"> 
</span><del>-    if (m_client &amp;&amp; notifyClientOption == NotifyClientOption::Notify)
-        m_client-&gt;didRemoveTrack(track);
</del><ins>+    if (notifyClientOption == NotifyClientOption::Notify) {
+        for (auto&amp; observer : m_observers)
+            observer-&gt;didRemoveTrack(track);
+    }
</ins><span class="cx"> 
</span><span class="cx">     updateActiveState(NotifyClientOption::Notify);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaStreamPrivate::startProducingData()
+{
+    for (auto&amp; track : m_trackSet.values())
+        track-&gt;startProducingData();
+}
+
+void MediaStreamPrivate::stopProducingData()
+{
+    for (auto&amp; track : m_trackSet.values())
+        track-&gt;stopProducingData();
+}
+
+bool MediaStreamPrivate::isProducingData() const
+{
+    for (auto&amp; track : m_trackSet.values()) {
+        if (track-&gt;isProducingData())
+            return true;
+    }
+    return false;
+}
+
+bool MediaStreamPrivate::hasVideo()
+{
+    for (auto&amp; track : m_trackSet.values()) {
+        if (track-&gt;type() == RealtimeMediaSource::Type::Video &amp;&amp; track-&gt;enabled())
+            return true;
+    }
+    return false;
+}
+
+bool MediaStreamPrivate::hasAudio()
+{
+    for (auto&amp; track : m_trackSet.values()) {
+        if (track-&gt;type() == RealtimeMediaSource::Type::Audio &amp;&amp; track-&gt;enabled())
+            return true;
+    }
+    return false;
+}
+
+FloatSize MediaStreamPrivate::intrinsicSize() const
+{
+    FloatSize size;
+
+    if (m_activeVideoTrack) {
+        const RealtimeMediaSourceStates&amp; states = m_activeVideoTrack-&gt;source()-&gt;states();
+        size.setWidth(states.width());
+        size.setHeight(states.height());
+    }
+
+    return size;
+}
+
+PlatformLayer* MediaStreamPrivate::platformLayer() const
+{
+    if (!m_activeVideoTrack)
+        return nullptr;
+
+    return m_activeVideoTrack-&gt;source()-&gt;platformLayer();
+}
+
+void MediaStreamPrivate::paintCurrentFrameInContext(GraphicsContext&amp; context, const FloatRect&amp; rect)
+{
+    if (context.paintingDisabled())
+        return;
+
+    if (active() &amp;&amp; m_activeVideoTrack)
+        m_activeVideoTrack-&gt;source()-&gt;paintCurrentFrameInContext(context, rect);
+    else {
+        GraphicsContextStateSaver stateSaver(context);
+        context.translate(rect.x(), rect.y() + rect.height());
+        context.scale(FloatSize(1, -1));
+        IntRect paintRect(IntPoint(0, 0), IntSize(rect.width(), rect.height()));
+        context.fillRect(paintRect, Color::black, ColorSpaceDeviceRGB);
+    }
+}
+
+RefPtr&lt;Image&gt; MediaStreamPrivate::currentFrameImage()
+{
+    if (!active() &amp;&amp; !m_activeVideoTrack)
+        return nullptr;
+
+    return m_activeVideoTrack-&gt;source()-&gt;currentFrameImage();
+}
+
+void MediaStreamPrivate::characteristicsChanged()
+{
+    for (auto&amp; observer : m_observers)
+        observer-&gt;characteristicsChanged();
+}
+
+void MediaStreamPrivate::trackMutedChanged(MediaStreamTrackPrivate&amp;)
+{
+    scheduleDeferredTask([this] {
+        characteristicsChanged();
+    });
+}
+
+void MediaStreamPrivate::trackStatesChanged(MediaStreamTrackPrivate&amp;)
+{
+    characteristicsChanged();
+}
+
+void MediaStreamPrivate::trackEnabledChanged(MediaStreamTrackPrivate&amp;)
+{
+    scheduleDeferredTask([this] {
+        characteristicsChanged();
+    });
+}
+
+void MediaStreamPrivate::trackProducingDataChanged(MediaStreamTrackPrivate&amp;)
+{
+    scheduleDeferredTask([this] {
+        characteristicsChanged();
+    });
+}
+
+void MediaStreamPrivate::scheduleDeferredTask(std::function&lt;void()&gt; function)
+{
+    ASSERT(function);
+    auto weakThis = createWeakPtr();
+    callOnMainThread([weakThis, function] {
+        if (!weakThis)
+            return;
+
+        function();
+    });
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -2,6 +2,7 @@
</span><span class="cx">  * Copyright (C) 2011, 2015 Ericsson AB. All rights reserved.
</span><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><span class="cx">  * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
</span><ins>+ * Copyright (C) 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -35,28 +36,32 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><ins>+#include &quot;FloatSize.h&quot;
</ins><span class="cx"> #include &quot;MediaStreamTrack.h&quot;
</span><span class="cx"> #include &quot;MediaStreamTrackPrivate.h&quot;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><ins>+#include &lt;wtf/MediaTime.h&gt;
</ins><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><ins>+#include &lt;wtf/WeakPtr.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class MediaStreamTrackPrivate;
</del><ins>+class MediaStream;
</ins><span class="cx"> 
</span><del>-class MediaStreamPrivateClient : public RefCounted&lt;MediaStreamPrivateClient&gt; {
</del><ins>+class MediaStreamPrivate : public MediaStreamTrackPrivate::Observer, public RefCounted&lt;MediaStreamPrivate&gt; {
</ins><span class="cx"> public:
</span><del>-    virtual ~MediaStreamPrivateClient() { }
</del><ins>+    class Observer {
+    public:
+        virtual ~Observer() { }
</ins><span class="cx"> 
</span><del>-    virtual void activeStatusChanged() = 0;
-    virtual void didAddTrack(MediaStreamTrackPrivate&amp;) = 0;
-    virtual void didRemoveTrack(MediaStreamTrackPrivate&amp;) = 0;
-};
</del><ins>+        virtual void characteristicsChanged() { }
+        virtual void activeStatusChanged() { }
+        virtual void didAddTrack(MediaStreamTrackPrivate&amp;) { }
+        virtual void didRemoveTrack(MediaStreamTrackPrivate&amp;) { }
+    };
</ins><span class="cx"> 
</span><del>-class MediaStreamPrivate : public MediaStreamTrackPrivate::Observer, public RefCounted&lt;MediaStreamPrivate&gt; {
-public:
</del><span class="cx">     static RefPtr&lt;MediaStreamPrivate&gt; create(const Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt;&amp; audioSources, const Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt;&amp; videoSources);
</span><span class="cx">     static RefPtr&lt;MediaStreamPrivate&gt; create(const MediaStreamTrackPrivateVector&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -64,8 +69,8 @@
</span><span class="cx"> 
</span><span class="cx">     enum class NotifyClientOption { Notify, DontNotify };
</span><span class="cx"> 
</span><del>-    MediaStreamPrivateClient* client() const { return m_client; }
-    void setClient(MediaStreamPrivateClient* client) { m_client = client; }
</del><ins>+    void addObserver(Observer&amp;);
+    void removeObserver(Observer&amp;);
</ins><span class="cx"> 
</span><span class="cx">     String id() const { return m_id; }
</span><span class="cx"> 
</span><span class="lines">@@ -77,21 +82,40 @@
</span><span class="cx">     void addTrack(RefPtr&lt;MediaStreamTrackPrivate&gt;&amp;&amp;, NotifyClientOption = NotifyClientOption::Notify);
</span><span class="cx">     void removeTrack(MediaStreamTrackPrivate&amp;, NotifyClientOption = NotifyClientOption::Notify);
</span><span class="cx"> 
</span><del>-protected:
-    explicit MediaStreamPrivate(MediaStreamPrivateClient&amp;);
</del><ins>+    void startProducingData();
+    void stopProducingData();
+    bool isProducingData() const;
</ins><span class="cx"> 
</span><ins>+    PlatformLayer* platformLayer() const;
+    RefPtr&lt;Image&gt; currentFrameImage();
+    void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;);
+
+    bool hasVideo();
+    bool hasAudio();
+
+    FloatSize intrinsicSize() const;
+
+    WeakPtr&lt;MediaStreamPrivate&gt; createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
</ins><span class="cx"> private:
</span><span class="cx">     MediaStreamPrivate(const String&amp;, const MediaStreamTrackPrivateVector&amp;);
</span><span class="cx"> 
</span><span class="cx">     void trackEnded(MediaStreamTrackPrivate&amp;) override { }
</span><del>-    void trackMutedChanged(MediaStreamTrackPrivate&amp;) override { }
-    void trackStatesChanged(MediaStreamTrackPrivate&amp;) override { }
</del><ins>+    void trackMutedChanged(MediaStreamTrackPrivate&amp;) override;
+    void trackStatesChanged(MediaStreamTrackPrivate&amp;) override;
+    void trackProducingDataChanged(MediaStreamTrackPrivate&amp;) override;
+    void trackEnabledChanged(MediaStreamTrackPrivate&amp;) override;
</ins><span class="cx"> 
</span><del>-    MediaStreamPrivateClient* m_client { nullptr };
</del><ins>+    void characteristicsChanged();
+
+    void scheduleDeferredTask(std::function&lt;void()&gt;);
+
+    WeakPtrFactory&lt;MediaStreamPrivate&gt; m_weakPtrFactory;
+    Vector&lt;Observer*&gt; m_observers;
</ins><span class="cx">     String m_id;
</span><ins>+    MediaStreamTrackPrivate* m_activeVideoTrack { nullptr };
+    HashMap&lt;String, RefPtr&lt;MediaStreamTrackPrivate&gt;&gt; m_trackSet;
</ins><span class="cx">     bool m_isActive { false };
</span><del>-
-    HashMap&lt;String, RefPtr&lt;MediaStreamTrackPrivate&gt;&gt; m_trackSet;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> typedef Vector&lt;RefPtr&lt;MediaStreamPrivate&gt;&gt; MediaStreamPrivateVector;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamTrackPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -178,6 +178,18 @@
</span><span class="cx">         observer-&gt;trackStatesChanged(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaStreamTrackPrivate::sourceProducingDataChanged()
+{
+    for (auto&amp; observer : m_observers)
+        observer-&gt;trackProducingDataChanged(*this);
+}
+
+void MediaStreamTrackPrivate::sourceEnabledChanged()
+{
+    for (auto&amp; observer : m_observers)
+        observer-&gt;trackEnabledChanged(*this);
+}
+
</ins><span class="cx"> bool MediaStreamTrackPrivate::preventSourceFromStopping()
</span><span class="cx"> {
</span><span class="cx">     return !m_isEnded;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaStreamTrackPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -48,6 +48,8 @@
</span><span class="cx">         virtual void trackEnded(MediaStreamTrackPrivate&amp;) = 0;
</span><span class="cx">         virtual void trackMutedChanged(MediaStreamTrackPrivate&amp;) = 0;
</span><span class="cx">         virtual void trackStatesChanged(MediaStreamTrackPrivate&amp;) = 0;
</span><ins>+        virtual void trackProducingDataChanged(MediaStreamTrackPrivate&amp;) = 0;
+        virtual void trackEnabledChanged(MediaStreamTrackPrivate&amp;) = 0;
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     static RefPtr&lt;MediaStreamTrackPrivate&gt; create(RefPtr&lt;RealtimeMediaSource&gt;&amp;&amp;);
</span><span class="lines">@@ -62,6 +64,7 @@
</span><span class="cx"> 
</span><span class="cx">     void startProducingData() { m_source-&gt;startProducingData(); }
</span><span class="cx">     void stopProducingData() { m_source-&gt;stopProducingData(); }
</span><ins>+    bool isProducingData() { return m_source-&gt;isProducingData(); }
</ins><span class="cx"> 
</span><span class="cx">     bool muted() const;
</span><span class="cx">     void setMuted(bool muted) const { m_source-&gt;setMuted(muted); }
</span><span class="lines">@@ -98,7 +101,9 @@
</span><span class="cx">     void sourceStopped() override final;
</span><span class="cx">     void sourceMutedChanged() override final;
</span><span class="cx">     void sourceStatesChanged() override final;
</span><ins>+    void sourceProducingDataChanged() override final;
</ins><span class="cx">     bool preventSourceFromStopping() override final;
</span><ins>+    void sourceEnabledChanged() override final;
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;Observer*&gt; m_observers;
</span><span class="cx">     RefPtr&lt;RealtimeMediaSource&gt; m_source;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -101,6 +101,22 @@
</span><span class="cx">         observer-&gt;sourceStatesChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RealtimeMediaSource::isProducingDataDidChange()
+{
+    for (auto&amp; observer : m_observers)
+        observer-&gt;sourceProducingDataChanged();
+}
+
+void RealtimeMediaSource::setEnabled(bool enabled)
+{
+    if (m_enabled == enabled)
+        return;
+
+    m_enabled = enabled;
+    for (auto&amp; observer : m_observers)
+        observer-&gt;sourceEnabledChanged();
+}
+
</ins><span class="cx"> bool RealtimeMediaSource::readonly() const
</span><span class="cx"> {
</span><span class="cx">     return m_readonly;
</span><span class="lines">@@ -119,6 +135,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     stopProducingData();
</span><ins>+    reset();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RealtimeMediaSource::requestStop(Observer* callingObserver)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -37,7 +37,9 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AudioSourceProvider.h&quot;
</span><ins>+#include &quot;Image.h&quot;
</ins><span class="cx"> #include &quot;MediaConstraints.h&quot;
</span><ins>+#include &quot;PlatformLayer.h&quot;
</ins><span class="cx"> #include &quot;RealtimeMediaSourceCapabilities.h&quot;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -45,6 +47,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class FloatRect;
+class GraphicsContext;
</ins><span class="cx"> class MediaConstraints;
</span><span class="cx"> class MediaStreamPrivate;
</span><span class="cx"> class RealtimeMediaSourceStates;
</span><span class="lines">@@ -59,6 +63,8 @@
</span><span class="cx">         virtual void sourceStopped() = 0;
</span><span class="cx">         virtual void sourceMutedChanged() = 0;
</span><span class="cx">         virtual void sourceStatesChanged() = 0;
</span><ins>+        virtual void sourceProducingDataChanged() = 0;
+        virtual void sourceEnabledChanged() = 0;
</ins><span class="cx"> 
</span><span class="cx">         // Observer state queries.
</span><span class="cx">         virtual bool preventSourceFromStopping() = 0;
</span><span class="lines">@@ -66,8 +72,6 @@
</span><span class="cx"> 
</span><span class="cx">     virtual ~RealtimeMediaSource() { }
</span><span class="cx"> 
</span><del>-    bool isAudioStreamSource() const { return type() == Audio; }
-
</del><span class="cx">     const String&amp; id() const { return m_id; }
</span><span class="cx"> 
</span><span class="cx">     const String&amp; persistentID() const { return m_persistentID; }
</span><span class="lines">@@ -82,7 +86,7 @@
</span><span class="cx">     virtual unsigned fitnessScore() const { return m_fitnessScore; }
</span><span class="cx">     virtual void setFitnessScore(const unsigned fitnessScore) { m_fitnessScore = fitnessScore; }
</span><span class="cx"> 
</span><del>-    virtual RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() const = 0;
</del><ins>+    virtual RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() = 0;
</ins><span class="cx">     virtual const RealtimeMediaSourceStates&amp; states() = 0;
</span><span class="cx">     void statesDidChanged();
</span><span class="cx">     
</span><span class="lines">@@ -97,19 +101,28 @@
</span><span class="cx">     virtual bool remote() const { return m_remote; }
</span><span class="cx">     virtual void setRemote(bool remote) { m_remote = remote; }
</span><span class="cx"> 
</span><ins>+    virtual void setEnabled(bool);
+    virtual bool enabled() const { return m_enabled; }
+
</ins><span class="cx">     void addObserver(Observer*);
</span><span class="cx">     void removeObserver(Observer*);
</span><span class="cx"> 
</span><span class="cx">     virtual void startProducingData() { }
</span><span class="cx">     virtual void stopProducingData() { }
</span><ins>+    virtual bool isProducingData() const { return false; }
+    virtual void isProducingDataDidChange();
</ins><span class="cx"> 
</span><span class="cx">     void stop(Observer* callingObserver = nullptr);
</span><span class="cx">     void requestStop(Observer* callingObserver = nullptr);
</span><span class="cx"> 
</span><del>-    void reset();
</del><ins>+    virtual void reset();
</ins><span class="cx"> 
</span><span class="cx">     virtual AudioSourceProvider* audioSourceProvider() { return nullptr; }
</span><del>-    
</del><ins>+
+    virtual PlatformLayer* platformLayer() const { return nullptr; }
+    virtual RefPtr&lt;Image&gt; currentFrameImage() { return nullptr; }
+    virtual void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;) { }
+
</ins><span class="cx"> protected:
</span><span class="cx">     RealtimeMediaSource(const String&amp; id, Type, const String&amp; name);
</span><span class="cx"> 
</span><span class="lines">@@ -124,6 +137,7 @@
</span><span class="cx">     bool m_muted;
</span><span class="cx">     bool m_readonly;
</span><span class="cx">     bool m_remote;
</span><ins>+    bool m_enabled { true };
</ins><span class="cx">     
</span><span class="cx">     unsigned m_fitnessScore;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVAudioCaptureSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -58,10 +58,12 @@
</span><span class="cx">     AVAudioCaptureSource(AVCaptureDevice*, const AtomicString&amp;, PassRefPtr&lt;MediaConstraints&gt;);
</span><span class="cx">     virtual ~AVAudioCaptureSource();
</span><span class="cx">     
</span><del>-    RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() const override;
</del><ins>+    void initializeCapabilities(RealtimeMediaSourceCapabilities&amp;) override;
+
</ins><span class="cx">     void captureOutputDidOutputSampleBufferFromConnection(AVCaptureOutput*, CMSampleBufferRef, AVCaptureConnection*) override;
</span><span class="cx">     
</span><span class="cx">     void setupCaptureSession() override;
</span><ins>+    void shutdownCaptureSession() override;
</ins><span class="cx">     void updateStates() override;
</span><span class="cx">     AudioSourceProvider* audioSourceProvider() override;
</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 (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -40,14 +40,16 @@
</span><span class="cx"> 
</span><span class="cx"> #import &quot;CoreMediaSoftLink.h&quot;
</span><span class="cx"> 
</span><ins>+typedef AVCaptureAudioChannel AVCaptureAudioChannelType;
+typedef AVCaptureAudioDataOutput AVCaptureAudioDataOutputType;
</ins><span class="cx"> typedef AVCaptureConnection AVCaptureConnectionType;
</span><span class="cx"> typedef AVCaptureDevice AVCaptureDeviceType;
</span><span class="cx"> typedef AVCaptureDeviceInput AVCaptureDeviceInputType;
</span><span class="cx"> typedef AVCaptureOutput AVCaptureOutputType;
</span><del>-typedef AVCaptureAudioDataOutput AVCaptureAudioDataOutputType;
</del><span class="cx"> 
</span><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
</span><span class="cx"> 
</span><ins>+SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioChannel)
</ins><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioDataOutput)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureConnection)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice)
</span><span class="lines">@@ -77,10 +79,10 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;RealtimeMediaSourceCapabilities&gt; AVAudioCaptureSource::capabilities() const
</del><ins>+void AVAudioCaptureSource::initializeCapabilities(RealtimeMediaSourceCapabilities&amp;capabilities)
</ins><span class="cx"> {
</span><del>-    notImplemented();
-    return nullptr;
</del><ins>+    // FIXME: finish this implementation - https://webkit.org/b/122430
+    capabilities.addSourceType(RealtimeMediaSourceStates::Microphone);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AVAudioCaptureSource::updateStates()
</span><span class="lines">@@ -90,11 +92,8 @@
</span><span class="cx"> 
</span><span class="cx"> void AVAudioCaptureSource::addObserver(AVAudioCaptureSource::Observer* observer)
</span><span class="cx"> {
</span><del>-    {
-        LockHolder lock(m_lock);
-        m_observers.append(observer);
-    }
-
</del><ins>+    LockHolder lock(m_lock);
+    m_observers.append(observer);
</ins><span class="cx">     if (m_inputDescription-&gt;mSampleRate)
</span><span class="cx">         observer-&gt;prepare(m_inputDescription.get());
</span><span class="cx"> }
</span><span class="lines">@@ -110,18 +109,42 @@
</span><span class="cx"> void AVAudioCaptureSource::setupCaptureSession()
</span><span class="cx"> {
</span><span class="cx">     RetainPtr&lt;AVCaptureDeviceInputType&gt; audioIn = adoptNS([allocAVCaptureDeviceInputInstance() initWithDevice:device() error:nil]);
</span><del>-    ASSERT([session() canAddInput:audioIn.get()]);
-    if ([session() canAddInput:audioIn.get()])
-        [session() addInput:audioIn.get()];
-    
</del><ins>+
+    if (![session() canAddInput:audioIn.get()]) {
+        LOG(Media, &quot;AVVideoCaptureSource::setupCaptureSession(%p), unable to add audio input device&quot;, this);
+        return;
+    }
+    [session() addInput:audioIn.get()];
+
</ins><span class="cx">     RetainPtr&lt;AVCaptureAudioDataOutputType&gt; audioOutput = adoptNS([allocAVCaptureAudioDataOutputInstance() init]);
</span><span class="cx">     setAudioSampleBufferDelegate(audioOutput.get());
</span><del>-    ASSERT([session() canAddOutput:audioOutput.get()]);
-    if ([session() canAddOutput:audioOutput.get()])
-        [session() addOutput:audioOutput.get()];
-    m_audioConnection = adoptNS([audioOutput.get() connectionWithMediaType:AVMediaTypeAudio]);
</del><ins>+
+    if (![session() canAddOutput:audioOutput.get()]) {
+        LOG(Media, &quot;AVVideoCaptureSource::setupCaptureSession(%p), unable to add audio sample buffer output delegate&quot;, this);
+        return;
+    }
+    [session() addOutput:audioOutput.get()];
+    m_audioConnection = [audioOutput.get() connectionWithMediaType:AVMediaTypeAudio];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void AVAudioCaptureSource::shutdownCaptureSession()
+{
+    {
+        LockHolder lock(m_lock);
+
+        m_audioConnection = nullptr;
+        m_inputDescription = std::make_unique&lt;AudioStreamBasicDescription&gt;();
+
+        for (auto&amp; observer : m_observers)
+            observer-&gt;unprepare();
+        m_observers.shrink(0);
+    }
+
+    // Don't hold the lock when destroying the audio provider, it will call back into this object
+    // to remove itself as an observer.
+    m_audioSourceProvider = nullptr;
+}
+
</ins><span class="cx"> static bool operator==(const AudioStreamBasicDescription&amp; a, const AudioStreamBasicDescription&amp; b)
</span><span class="cx"> {
</span><span class="cx">     return a.mSampleRate == b.mSampleRate
</span><span class="lines">@@ -141,27 +164,30 @@
</span><span class="cx"> 
</span><span class="cx"> void AVAudioCaptureSource::captureOutputDidOutputSampleBufferFromConnection(AVCaptureOutputType*, CMSampleBufferRef sampleBuffer, AVCaptureConnectionType*)
</span><span class="cx"> {
</span><del>-    Vector&lt;Observer*&gt; observers;
-    {
-        LockHolder lock(m_lock);
-        if (m_observers.isEmpty())
-            return;
</del><ins>+    if (!enabled())
+        return;
</ins><span class="cx"> 
</span><del>-        copyToVector(m_observers, observers);
-    }
-
</del><span class="cx">     CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
</span><span class="cx">     if (!formatDescription)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    std::unique_lock&lt;Lock&gt; lock(m_lock, std::try_to_lock);
+    if (!lock.owns_lock()) {
+        // Failed to acquire the lock, just return instead of blocking.
+        return;
+    }
+
+    if (m_observers.isEmpty())
+        return;
+
</ins><span class="cx">     const AudioStreamBasicDescription* streamDescription = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription);
</span><span class="cx">     if (*m_inputDescription != *streamDescription) {
</span><span class="cx">         m_inputDescription = std::make_unique&lt;AudioStreamBasicDescription&gt;(*streamDescription);
</span><del>-        for (auto&amp; observer : observers)
</del><ins>+        for (auto&amp; observer : m_observers)
</ins><span class="cx">             observer-&gt;prepare(m_inputDescription.get());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    for (auto&amp; observer : observers)
</del><ins>+    for (auto&amp; observer : m_observers)
</ins><span class="cx">         observer-&gt;process(formatDescription, sampleBuffer);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -103,10 +103,7 @@
</span><span class="cx">     String m_groupID;
</span><span class="cx"> 
</span><span class="cx">     String m_audioSourceId;
</span><del>-    RefPtr&lt;AVMediaCaptureSource&gt; m_audioAVMediaCaptureSource;
-
</del><span class="cx">     String m_videoSourceId;
</span><del>-    RefPtr&lt;AVMediaCaptureSource&gt; m_videoAVMediaCaptureSource;
</del><span class="cx"> 
</span><span class="cx">     bool m_enabled;
</span><span class="cx"> };
</span><span class="lines">@@ -146,7 +143,15 @@
</span><span class="cx">     
</span><span class="cx">     for (AVCaptureDeviceType *device in [AVCaptureDevice devices]) {
</span><span class="cx">         CaptureDevice source;
</span><del>-        
</del><ins>+
+        if (![device isConnected])
+            continue;
+
+#if !PLATFORM(IOS)
+        if ([device isSuspended] || [device isInUseByAnotherApplication])
+            continue;
+#endif
+
</ins><span class="cx">         if (!captureDeviceFromDeviceID(device.uniqueID, source)) {
</span><span class="cx">             // An AVCaptureDevice has a unique ID, but we can't use it for the source ID because:
</span><span class="cx">             // 1. if it provides both audio and video we will need to create two sources for it
</span><span class="lines">@@ -388,24 +393,20 @@
</span><span class="cx">         if (!captureDevice.m_enabled)
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        // FIXME: consider the constraints when choosing among multiple devices. For now just select the first available
-        // device of the appropriate type.
</del><span class="cx">         if (type == RealtimeMediaSource::Audio &amp;&amp; !captureDevice.m_audioSourceId.isEmpty()) {
</span><del>-            if (!captureDevice.m_audioAVMediaCaptureSource) {
-                AVCaptureDeviceType *device = [AVCaptureDevice deviceWithUniqueID:captureDevice.m_captureDeviceID];
-                ASSERT(device);
-                captureDevice.m_audioAVMediaCaptureSource = AVAudioCaptureSource::create(device, captureDevice.m_audioSourceId, constraints);
-            }
-            bestSourcesList.append(captureDevice.m_audioAVMediaCaptureSource);
</del><ins>+            RefPtr&lt;RealtimeMediaSource&gt; captureSource = AVCaptureDeviceManager::sourceWithUID(captureDevice.m_captureDeviceID, RealtimeMediaSource::Audio, constraints.get());
+            if (!captureSource)
+                continue;
+
+            bestSourcesList.append(captureSource.leakRef());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (type == RealtimeMediaSource::Video &amp;&amp; !captureDevice.m_videoSourceId.isEmpty()) {
</span><del>-            if (!captureDevice.m_videoAVMediaCaptureSource) {
-                AVCaptureDeviceType *device = [AVCaptureDevice deviceWithUniqueID:captureDevice.m_captureDeviceID];
-                ASSERT(device);
-                captureDevice.m_videoAVMediaCaptureSource = AVVideoCaptureSource::create(device, captureDevice.m_videoSourceId, constraints);
-            }
-            bestSourcesList.append(captureDevice.m_videoAVMediaCaptureSource);
</del><ins>+            RefPtr&lt;RealtimeMediaSource&gt; captureSource = AVCaptureDeviceManager::sourceWithUID(captureDevice.m_captureDeviceID, RealtimeMediaSource::Video, constraints.get());
+            if (!captureSource)
+                continue;
+
+            bestSourcesList.append(captureSource.leakRef());
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     std::sort(bestSourcesList.begin(), bestSourcesList.end(), sortBasedOffFitnessScore);
</span><span class="lines">@@ -416,41 +417,41 @@
</span><span class="cx"> {
</span><span class="cx">     if (!isAvailable())
</span><span class="cx">         return 0;
</span><del>-    
</del><ins>+
</ins><span class="cx">     Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
</span><del>-    for (auto captureDevice : devices) {
-        if (!captureDevice.m_enabled)
</del><ins>+    for (auto&amp; captureDevice : devices) {
+        if (captureDevice.m_captureDeviceID != deviceUID || !captureDevice.m_enabled)
</ins><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        if (captureDevice.m_captureDeviceID != deviceUID)
</del><ins>+        if (type == RealtimeMediaSource::Audio &amp;&amp; captureDevice.m_audioSourceId.isEmpty())
</ins><span class="cx">             continue;
</span><ins>+        if (type == RealtimeMediaSource::Video &amp;&amp; captureDevice.m_videoSourceId.isEmpty())
+            continue;
</ins><span class="cx"> 
</span><ins>+        AVCaptureDeviceType *device = [AVCaptureDevice deviceWithUniqueID:captureDevice.m_captureDeviceID];
+        ASSERT(device);
+
+        RefPtr&lt;AVMediaCaptureSource&gt; captureSource;
+        if (type == RealtimeMediaSource::Audio)
+            captureSource = AVAudioCaptureSource::create(device, captureDevice.m_audioSourceId, constraints);
+        else
+            captureSource = AVVideoCaptureSource::create(device, captureDevice.m_videoSourceId, constraints);
+
</ins><span class="cx">         if (constraints) {
</span><span class="cx">             String invalidConstraints;
</span><span class="cx">             AVCaptureSessionType *session = nil;
</span><span class="cx"> 
</span><del>-            if (type == RealtimeMediaSource::Video &amp;&amp; captureDevice.m_videoAVMediaCaptureSource)
-                captureDevice.m_videoAVMediaCaptureSource-&gt;session();
-            else if (type == RealtimeMediaSource::Audio &amp;&amp; captureDevice.m_audioAVMediaCaptureSource)
-                captureDevice.m_audioAVMediaCaptureSource-&gt;session();
</del><ins>+            if (type == RealtimeMediaSource::Video)
+                session = captureSource-&gt;session();
+            else if (type == RealtimeMediaSource::Audio)
+                session = captureSource-&gt;session();
</ins><span class="cx">             AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(session, type, constraints, invalidConstraints);
</span><span class="cx"> 
</span><span class="cx">             if (!invalidConstraints.isEmpty())
</span><span class="cx">                 continue;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        AVCaptureDeviceType *device = [AVCaptureDevice deviceWithUniqueID:captureDevice.m_captureDeviceID];
-        ASSERT(device);
-        if (type == RealtimeMediaSource::Audio &amp;&amp; !captureDevice.m_audioSourceId.isEmpty()) {
-            if (!captureDevice.m_audioAVMediaCaptureSource)
-                captureDevice.m_audioAVMediaCaptureSource = AVAudioCaptureSource::create(device, captureDevice.m_audioSourceId, constraints);
-            return captureDevice.m_audioAVMediaCaptureSource;
-        }
-        if (type == RealtimeMediaSource::Video &amp;&amp; !captureDevice.m_videoSourceId.isEmpty()) {
-            if (!captureDevice.m_videoAVMediaCaptureSource)
-                captureDevice.m_videoAVMediaCaptureSource = AVVideoCaptureSource::create(device, captureDevice.m_videoSourceId, constraints);
-            return captureDevice.m_videoAVMediaCaptureSource;
-        }
</del><ins>+        return captureSource.leakRef();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     return nullptr;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVMediaCaptureSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -52,45 +52,52 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void captureOutputDidOutputSampleBufferFromConnection(AVCaptureOutput*, CMSampleBufferRef, AVCaptureConnection*) = 0;
</span><span class="cx"> 
</span><del>-    virtual void captureSessionStoppedRunning();
</del><ins>+    virtual void captureSessionIsRunningDidChange(bool);
</ins><span class="cx">     
</span><span class="cx">     AVCaptureSession *session() const { return m_session.get(); }
</span><span class="cx"> 
</span><ins>+    const RealtimeMediaSourceStates&amp; states() override;
+
</ins><span class="cx">     void startProducingData() override;
</span><span class="cx">     void stopProducingData() override;
</span><ins>+    bool isProducingData() const override { return m_isRunning; }
</ins><span class="cx"> 
</span><ins>+    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, PassRefPtr&lt;MediaConstraints&gt;);
</span><span class="cx"> 
</span><del>-    const RealtimeMediaSourceStates&amp; states() override;
</del><span class="cx">     AudioSourceProvider* audioSourceProvider() override;
</span><span class="cx"> 
</span><span class="cx">     virtual void setupCaptureSession() = 0;
</span><ins>+    virtual void shutdownCaptureSession() = 0;
</ins><span class="cx">     virtual void updateStates() = 0;
</span><ins>+    virtual void initializeCapabilities(RealtimeMediaSourceCapabilities&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     AVCaptureDevice *device() const { return m_device.get(); }
</span><ins>+
</ins><span class="cx">     RealtimeMediaSourceStates* currentStates() { return &amp;m_currentStates; }
</span><span class="cx">     MediaConstraints* constraints() { return m_constraints.get(); }
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() override;
+
</ins><span class="cx">     void setVideoSampleBufferDelegate(AVCaptureVideoDataOutput*);
</span><span class="cx">     void setAudioSampleBufferDelegate(AVCaptureAudioDataOutput*);
</span><span class="cx"> 
</span><span class="cx">     void scheduleDeferredTask(std::function&lt;void ()&gt;);
</span><span class="cx"> 
</span><del>-    void statesDidChanged() { }
-    
</del><span class="cx"> private:
</span><span class="cx">     void setupSession();
</span><del>-    WeakPtr&lt;AVMediaCaptureSource&gt; createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
</del><ins>+    void reset() override;
</ins><span class="cx"> 
</span><span class="cx">     WeakPtrFactory&lt;AVMediaCaptureSource&gt; m_weakPtrFactory;
</span><span class="cx">     RetainPtr&lt;WebCoreAVMediaCaptureSourceObserver&gt; m_objcObserver;
</span><span class="cx">     RefPtr&lt;MediaConstraints&gt; m_constraints;
</span><ins>+    RefPtr&lt;RealtimeMediaSourceCapabilities&gt; m_capabilities;
</ins><span class="cx">     RealtimeMediaSourceStates m_currentStates;
</span><span class="cx">     RetainPtr&lt;AVCaptureSession&gt; m_session;
</span><span class="cx">     RetainPtr&lt;AVCaptureDevice&gt; m_device;
</span><del>-    
-    bool m_isRunning;
</del><ins>+    bool m_isRunning { false};
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVMediaCaptureSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -94,12 +94,14 @@
</span><span class="cx"> 
</span><span class="cx"> -(id)initWithCallback:(AVMediaCaptureSource*)callback;
</span><span class="cx"> -(void)disconnect;
</span><del>--(void)captureSessionStoppedRunning:(NSNotification *)notification;
</del><span class="cx"> -(void)captureOutput:(AVCaptureOutputType *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnectionType *)connection;
</span><ins>+-(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context;
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+static NSArray* sessionKVOProperties();
+
</ins><span class="cx"> static dispatch_queue_t globaAudioCaptureSerialQueue()
</span><span class="cx"> {
</span><span class="cx">     static dispatch_queue_t globalQueue;
</span><span class="lines">@@ -127,7 +129,6 @@
</span><span class="cx">     , m_objcObserver(adoptNS([[WebCoreAVMediaCaptureSourceObserver alloc] initWithCallback:this]))
</span><span class="cx">     , m_constraints(constraints)
</span><span class="cx">     , m_device(device)
</span><del>-    , m_isRunning(false)
</del><span class="cx"> {
</span><span class="cx">     setName(device.localizedName);
</span><span class="cx">     setPersistentID(device.uniqueID);
</span><span class="lines">@@ -136,9 +137,13 @@
</span><span class="cx"> 
</span><span class="cx"> AVMediaCaptureSource::~AVMediaCaptureSource()
</span><span class="cx"> {
</span><del>-    [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()];
</del><span class="cx">     [m_objcObserver disconnect];
</span><del>-    [m_session.get() stopRunning];
</del><ins>+
+    if (m_session) {
+        for (NSString *keyName in sessionKVOProperties())
+            [m_session.get() removeObserver:m_objcObserver.get() forKeyPath:keyName];
+        [m_session.get() stopRunning];
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AVMediaCaptureSource::startProducingData()
</span><span class="lines">@@ -150,8 +155,6 @@
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     [m_session.get() startRunning];
</span><del>-
-    m_isRunning = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AVMediaCaptureSource::stopProducingData()
</span><span class="lines">@@ -160,8 +163,6 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     [m_session.get() stopRunning];
</span><del>-
-    m_isRunning = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const RealtimeMediaSourceStates&amp; AVMediaCaptureSource::states()
</span><span class="lines">@@ -170,23 +171,49 @@
</span><span class="cx">     return m_currentStates;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RefPtr&lt;RealtimeMediaSourceCapabilities&gt; AVMediaCaptureSource::capabilities()
+{
+    if (!m_capabilities) {
+        m_capabilities = RealtimeMediaSourceCapabilities::create();
+        m_capabilities-&gt;setSourceId(m_currentStates.sourceId());
+        initializeCapabilities(*m_capabilities.get());
+    }
+    return m_capabilities;
+}
+
</ins><span class="cx"> void AVMediaCaptureSource::setupSession()
</span><span class="cx"> {
</span><span class="cx">     if (m_session)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     m_session = adoptNS([allocAVCaptureSessionInstance() init]);
</span><del>-    
-    [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(captureSessionStoppedRunning:) name:AVCaptureSessionDidStopRunningNotification object:nil];
-    
</del><ins>+    for (NSString *keyName in sessionKVOProperties())
+        [m_session.get() addObserver:m_objcObserver.get() forKeyPath:keyName options:NSKeyValueObservingOptionNew context:(void *)nil];
+
</ins><span class="cx">     setupCaptureSession();
</span><span class="cx"> }
</span><del>- 
-void AVMediaCaptureSource::captureSessionStoppedRunning()
</del><ins>+
+void AVMediaCaptureSource::reset()
</ins><span class="cx"> {
</span><del>-    stopProducingData();
</del><ins>+    RealtimeMediaSource::reset();
+    m_isRunning = false;
+    for (NSString *keyName in sessionKVOProperties())
+        [m_session.get() removeObserver:m_objcObserver.get() forKeyPath:keyName];
+    shutdownCaptureSession();
+    m_session = nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void AVMediaCaptureSource::captureSessionIsRunningDidChange(bool state)
+{
+    scheduleDeferredTask([this, state] {
+        if (state == m_isRunning)
+            return;
+
+        m_isRunning = state;
+        isProducingDataDidChange();
+    });
+}
+
</ins><span class="cx"> void AVMediaCaptureSource::setVideoSampleBufferDelegate(AVCaptureVideoDataOutputType* videoOutput)
</span><span class="cx"> {
</span><span class="cx">     [videoOutput setSampleBufferDelegate:m_objcObserver.get() queue:globaVideoCaptureSerialQueue()];
</span><span class="lines">@@ -216,6 +243,12 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+NSArray* sessionKVOProperties()
+{
+    static NSArray* keys = [@[@&quot;running&quot;] retain];
+    return keys;
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> @implementation WebCoreAVMediaCaptureSourceObserver
</span><span class="lines">@@ -225,6 +258,7 @@
</span><span class="cx">     self = [super init];
</span><span class="cx">     if (!self)
</span><span class="cx">         return nil;
</span><ins>+
</ins><span class="cx">     m_callback = callback;
</span><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="lines">@@ -235,25 +269,37 @@
</span><span class="cx">     m_callback = 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)captureSessionStoppedRunning:(NSNotification *)notification
</del><ins>+- (void)captureOutput:(AVCaptureOutputType *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnectionType *)connection
</ins><span class="cx"> {
</span><del>-    UNUSED_PARAM(notification);
-
</del><span class="cx">     if (!m_callback)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (m_callback)
-            m_callback-&gt;captureSessionStoppedRunning();
-    });
</del><ins>+    m_callback-&gt;captureOutputDidOutputSampleBufferFromConnection(captureOutput, sampleBuffer, connection);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)captureOutput:(AVCaptureOutputType *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnectionType *)connection
</del><ins>+-(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
</ins><span class="cx"> {
</span><ins>+    UNUSED_PARAM(object);
+    UNUSED_PARAM(context);
+
</ins><span class="cx">     if (!m_callback)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_callback-&gt;captureOutputDidOutputSampleBufferFromConnection(captureOutput, sampleBuffer, connection);
</del><ins>+    id newValue = [change valueForKey:NSKeyValueChangeNewKey];
+
+#if !LOG_DISABLED
+    bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
+
+    if (willChange)
+        LOG(Media, &quot;WebCoreAVMediaCaptureSourceObserver::observeValueForKeyPath(%p) - will change, keyPath = %s&quot;, self, [keyPath UTF8String]);
+    else {
+        RetainPtr&lt;NSString&gt; valueString = adoptNS([[NSString alloc] initWithFormat:@&quot;%@&quot;, newValue]);
+        LOG(Media, &quot;WebCoreAVMediaCaptureSourceObserver::observeValueForKeyPath(%p) - did change, keyPath = %s, value = %s&quot;, self, [keyPath UTF8String], [valueString.get() UTF8String]);
+    }
+#endif
+
+    if ([keyPath isEqualToString:@&quot;running&quot;])
+        m_callback-&gt;captureSessionIsRunningDidChange([newValue boolValue]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AVMediaCaptureSource.h&quot;
</span><span class="cx"> 
</span><del>-OBJC_CLASS AVCaptureVideoPreviewLayer;
</del><ins>+OBJC_CLASS CALayer;
</ins><span class="cx"> 
</span><span class="cx"> typedef struct CGImage *CGImageRef;
</span><span class="cx"> typedef const struct opaqueCMFormatDescription *CMFormatDescriptionRef;
</span><span class="lines">@@ -48,36 +48,38 @@
</span><span class="cx">     int32_t width() const { return m_width; }
</span><span class="cx">     int32_t height() const { return m_height; }
</span><span class="cx"> 
</span><del>-    AVCaptureVideoPreviewLayer* previewLayer() { return m_videoPreviewLayer.get(); }
-    CMSampleBufferRef currentFrameSampleBuffer() const { return m_buffer.get(); }
-    void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;);
-    RetainPtr&lt;CGImageRef&gt; currentFrameImage();
-
</del><span class="cx"> private:
</span><span class="cx">     AVVideoCaptureSource(AVCaptureDevice*, const AtomicString&amp;, PassRefPtr&lt;MediaConstraints&gt;);
</span><span class="cx">     virtual ~AVVideoCaptureSource();
</span><span class="cx"> 
</span><span class="cx">     void setupCaptureSession() override;
</span><ins>+    void shutdownCaptureSession() override;
+
</ins><span class="cx">     void updateStates() override;
</span><span class="cx"> 
</span><del>-    RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() const override;
</del><ins>+    void initializeCapabilities(RealtimeMediaSourceCapabilities&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     bool applyConstraints(MediaConstraints*);
</span><span class="cx">     bool setFrameRateConstraint(float minFrameRate, float maxFrameRate);
</span><span class="cx"> 
</span><del>-    bool calculateFramerate(CMSampleBufferRef);
</del><ins>+    bool updateFramerate(CMSampleBufferRef);
</ins><span class="cx"> 
</span><span class="cx">     void captureOutputDidOutputSampleBufferFromConnection(AVCaptureOutput*, CMSampleBufferRef, AVCaptureConnection*) override;
</span><span class="cx">     void processNewFrame(RetainPtr&lt;CMSampleBufferRef&gt;);
</span><span class="cx"> 
</span><del>-    RetainPtr&lt;AVCaptureConnection&gt; m_videoConnection;
-    RetainPtr&lt;AVCaptureVideoPreviewLayer&gt; m_videoPreviewLayer;
</del><ins>+    void paintCurrentFrameInContext(GraphicsContext&amp;, const FloatRect&amp;) override;
+    PlatformLayer* platformLayer() const override;
+
+    RetainPtr&lt;CGImageRef&gt; currentFrameCGImage();
+    RefPtr&lt;Image&gt; currentFrameImage() override;
+
</ins><span class="cx">     RetainPtr&lt;CMSampleBufferRef&gt; m_buffer;
</span><span class="cx">     RetainPtr&lt;CGImageRef&gt; m_lastImage;
</span><span class="cx">     Vector&lt;Float64&gt; m_videoFrameTimeStamps;
</span><del>-    Float64 m_frameRate;
-    int32_t m_width;
-    int32_t m_height;
</del><ins>+    mutable RetainPtr&lt;PlatformLayer&gt; m_videoPreviewLayer;
+    Float64 m_frameRate { 0 };
+    int32_t m_width { 0 };
+    int32_t m_height { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -31,10 +31,12 @@
</span><span class="cx"> #import &quot;AVCaptureDeviceManager.h&quot;
</span><span class="cx"> #import &quot;BlockExceptions.h&quot;
</span><span class="cx"> #import &quot;GraphicsContextCG.h&quot;
</span><ins>+#import &quot;ImageBuffer.h&quot;
</ins><span class="cx"> #import &quot;IntRect.h&quot;
</span><span class="cx"> #import &quot;Logging.h&quot;
</span><span class="cx"> #import &quot;MediaConstraints.h&quot;
</span><span class="cx"> #import &quot;NotImplemented.h&quot;
</span><ins>+#import &quot;PlatformLayer.h&quot;
</ins><span class="cx"> #import &quot;RealtimeMediaSourceStates.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">@@ -98,9 +100,6 @@
</span><span class="cx"> 
</span><span class="cx"> AVVideoCaptureSource::AVVideoCaptureSource(AVCaptureDeviceType* device, const AtomicString&amp; id, PassRefPtr&lt;MediaConstraints&gt; constraint)
</span><span class="cx">     : AVMediaCaptureSource(device, id, RealtimeMediaSource::Video, constraint)
</span><del>-    , m_frameRate(0)
-    , m_width(0)
-    , m_height(0)
</del><span class="cx"> {
</span><span class="cx">     currentStates()-&gt;setSourceId(id);
</span><span class="cx">     currentStates()-&gt;setSourceType(RealtimeMediaSourceStates::Camera);
</span><span class="lines">@@ -110,10 +109,11 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;RealtimeMediaSourceCapabilities&gt; AVVideoCaptureSource::capabilities() const
</del><ins>+void AVVideoCaptureSource::initializeCapabilities(RealtimeMediaSourceCapabilities&amp; capabilities)
</ins><span class="cx"> {
</span><del>-    notImplemented();
-    return 0;
</del><ins>+    // FIXME: finish this implementation
+    capabilities.setSourceId(currentStates()-&gt;sourceId());
+    capabilities.addSourceType(RealtimeMediaSourceStates::Camera);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AVVideoCaptureSource::updateStates()
</span><span class="lines">@@ -218,10 +218,14 @@
</span><span class="cx"> void AVVideoCaptureSource::setupCaptureSession()
</span><span class="cx"> {
</span><span class="cx">     RetainPtr&lt;AVCaptureDeviceInputType&gt; videoIn = adoptNS([allocAVCaptureDeviceInputInstance() initWithDevice:device() error:nil]);
</span><del>-    ASSERT([session() canAddInput:videoIn.get()]);
-    if ([session() canAddInput:videoIn.get()])
-        [session() addInput:videoIn.get()];
</del><span class="cx"> 
</span><ins>+    if (![session() canAddInput:videoIn.get()]) {
+        LOG(Media, &quot;AVVideoCaptureSource::setupCaptureSession(%p), unable to add video input device&quot;, this);
+        return;
+    }
+
+    [session() addInput:videoIn.get()];
+
</ins><span class="cx">     if (constraints())
</span><span class="cx">         applyConstraints(constraints());
</span><span class="cx"> 
</span><span class="lines">@@ -231,16 +235,27 @@
</span><span class="cx">                                                          , nil]);
</span><span class="cx">     [videoOutput setVideoSettings:settingsDictionary.get()];
</span><span class="cx">     setVideoSampleBufferDelegate(videoOutput.get());
</span><del>-    ASSERT([session() canAddOutput:videoOutput.get()]);
-    if ([session() canAddOutput:videoOutput.get()])
-        [session() addOutput:videoOutput.get()];
</del><span class="cx"> 
</span><del>-    m_videoConnection = adoptNS([videoOutput.get() connectionWithMediaType:AVMediaTypeVideo]);
-    m_videoPreviewLayer = adoptNS([[AVCaptureVideoPreviewLayer alloc] initWithSession:session()]);
</del><ins>+    if (![session() canAddOutput:videoOutput.get()]) {
+        LOG(Media, &quot;AVVideoCaptureSource::setupCaptureSession(%p), unable to add video sample buffer output delegate&quot;, this);
+        return;
+    }
+    [session() addOutput:videoOutput.get()];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVVideoCaptureSource::calculateFramerate(CMSampleBufferRef sampleBuffer)
</del><ins>+void AVVideoCaptureSource::shutdownCaptureSession()
</ins><span class="cx"> {
</span><ins>+    m_videoPreviewLayer = nullptr;
+    m_buffer = nullptr;
+    m_lastImage = nullptr;
+    m_videoFrameTimeStamps.clear();
+    m_frameRate = 0;
+    m_width = 0;
+    m_height = 0;
+}
+
+bool AVVideoCaptureSource::updateFramerate(CMSampleBufferRef sampleBuffer)
+{
</ins><span class="cx">     CMTime sampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
</span><span class="cx">     if (!CMTIME_IS_NUMERIC(sampleTime))
</span><span class="cx">         return false;
</span><span class="lines">@@ -261,13 +276,19 @@
</span><span class="cx"> 
</span><span class="cx"> void AVVideoCaptureSource::processNewFrame(RetainPtr&lt;CMSampleBufferRef&gt; sampleBuffer)
</span><span class="cx"> {
</span><ins>+    // Ignore frames delivered when the session is not running, we want to hang onto the last image
+    // delivered before it stopped.
+    if (m_lastImage &amp;&amp; (!isProducingData() || !enabled()))
+        return;
+
</ins><span class="cx">     CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer.get());
</span><span class="cx">     if (!formatDescription)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    updateFramerate(sampleBuffer.get());
+
</ins><span class="cx">     bool statesChanged = false;
</span><span class="cx"> 
</span><del>-    statesChanged = calculateFramerate(sampleBuffer.get());
</del><span class="cx">     m_buffer = sampleBuffer;
</span><span class="cx">     m_lastImage = nullptr;
</span><span class="cx"> 
</span><span class="lines">@@ -291,8 +312,24 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RetainPtr&lt;CGImageRef&gt; AVVideoCaptureSource::currentFrameImage()
</del><ins>+RefPtr&lt;Image&gt; AVVideoCaptureSource::currentFrameImage()
</ins><span class="cx"> {
</span><ins>+    if (!currentFrameCGImage())
+        return nullptr;
+
+    FloatRect imageRect(0, 0, m_width, m_height);
+    std::unique_ptr&lt;ImageBuffer&gt; imageBuffer = ImageBuffer::create(imageRect.size(), Unaccelerated);
+
+    if (!imageBuffer)
+        return nullptr;
+
+    paintCurrentFrameInContext(imageBuffer-&gt;context(), imageRect);
+
+    return imageBuffer-&gt;copyImage();
+}
+
+RetainPtr&lt;CGImageRef&gt; AVVideoCaptureSource::currentFrameCGImage()
+{
</ins><span class="cx">     if (m_lastImage)
</span><span class="cx">         return m_lastImage;
</span><span class="cx"> 
</span><span class="lines">@@ -318,7 +355,7 @@
</span><span class="cx"> 
</span><span class="cx"> void AVVideoCaptureSource::paintCurrentFrameInContext(GraphicsContext&amp; context, const FloatRect&amp; rect)
</span><span class="cx"> {
</span><del>-    if (context.paintingDisabled() || !currentFrameImage())
</del><ins>+    if (context.paintingDisabled() || !currentFrameCGImage())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     GraphicsContextStateSaver stateSaver(context);
</span><span class="lines">@@ -329,6 +366,19 @@
</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><ins>+PlatformLayer* AVVideoCaptureSource::platformLayer() const
+{
+    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();
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacWebAudioSourceProviderAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx"> 
</span><span class="cx">     size_t m_listBufferSize { 0 };
</span><span class="cx">     std::unique_ptr&lt;AudioBufferList&gt; m_list;
</span><del>-    RetainPtr&lt;AudioConverterRef&gt; m_converter;
</del><ins>+    AudioConverterRef m_converter;
</ins><span class="cx">     std::unique_ptr&lt;AudioStreamBasicDescription&gt; m_inputDescription;
</span><span class="cx">     std::unique_ptr&lt;AudioStreamBasicDescription&gt; m_outputDescription;
</span><span class="cx">     std::unique_ptr&lt;CARingBuffer&gt; m_ringBuffer;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacWebAudioSourceProviderAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -73,6 +73,11 @@
</span><span class="cx"> 
</span><span class="cx"> WebAudioSourceProviderAVFObjC::~WebAudioSourceProviderAVFObjC()
</span><span class="cx"> {
</span><ins>+    if (m_converter) {
+        // FIXME: make and use a smart pointer for AudioConverter
+        AudioConverterDispose(m_converter);
+        m_converter = nullptr;
+    }
</ins><span class="cx">     if (m_connected)
</span><span class="cx">         m_captureSource-&gt;removeObserver(this);
</span><span class="cx"> }
</span><span class="lines">@@ -123,7 +128,7 @@
</span><span class="cx">     m_readCount += framesToProcess;
</span><span class="cx"> 
</span><span class="cx">     if (m_converter)
</span><del>-        AudioConverterConvertComplexBuffer(m_converter.get(), framesToProcess, m_list.get(), m_list.get());
</del><ins>+        AudioConverterConvertComplexBuffer(m_converter, framesToProcess, m_list.get(), m_list.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebAudioSourceProviderAVFObjC::setClient(AudioSourceProviderClient* client)
</span><span class="lines">@@ -180,9 +185,19 @@
</span><span class="cx">     m_outputDescription-&gt;mBytesPerFrame = sizeof(Float32);
</span><span class="cx">     m_outputDescription-&gt;mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
</span><span class="cx"> 
</span><ins>+    if (m_converter) {
+        // FIXME: make and use a smart pointer for AudioConverter
+        AudioConverterDispose(m_converter);
+        m_converter = nullptr;
+    }
+
</ins><span class="cx">     if (*m_inputDescription != *m_outputDescription) {
</span><span class="cx">         AudioConverterRef outConverter = nullptr;
</span><del>-        AudioConverterNew(m_inputDescription.get(), m_outputDescription.get(), &amp;outConverter);
</del><ins>+        OSStatus err = AudioConverterNew(m_inputDescription.get(), m_outputDescription.get(), &amp;outConverter);
+        if (err) {
+            LOG(Media, &quot;WebAudioSourceProviderAVFObjC::prepare(%p) - AudioConverterNew returned error %i&quot;, this, err);
+            return;
+        }
</ins><span class="cx">         m_converter = outConverter;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -221,6 +236,11 @@
</span><span class="cx">     m_ringBuffer = nullptr;
</span><span class="cx">     m_list = nullptr;
</span><span class="cx">     m_listBufferSize = 0;
</span><ins>+    if (m_converter) {
+        // FIXME: make and use a smart pointer for AudioConverter
+        AudioConverterDispose(m_converter);
+        m_converter = nullptr;
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebAudioSourceProviderAVFObjC::process(CMFormatDescriptionRef, CMSampleBufferRef sampleBuffer)
</span><span class="lines">@@ -234,7 +254,7 @@
</span><span class="cx">     OSStatus err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, nullptr, m_list.get(), m_listBufferSize, kCFAllocatorSystemDefault, kCFAllocatorSystemDefault, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &amp;buffer);
</span><span class="cx"> 
</span><span class="cx">     if (err) {
</span><del>-        LOG(Media, &quot;WebAudioSourceProviderAVFObjC::proess(%p) - CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer returned error %i&quot;, this, err);
</del><ins>+        LOG(Media, &quot;WebAudioSourceProviderAVFObjC::process(%p) - CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer returned error %i&quot;, this, err);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamopenwebrtcRealtimeMediaSourceOwrh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceOwr.h (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceOwr.h        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceOwr.h        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual ~RealtimeMediaSourceOwr() { }
</span><span class="cx"> 
</span><del>-    virtual RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() const { return m_capabilities; }
</del><ins>+    virtual RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() { return m_capabilities; }
</ins><span class="cx">     virtual const RealtimeMediaSourceStates&amp; states() { return m_currentStates; }
</span><span class="cx"> 
</span><span class="cx">     OwrMediaSource* mediaSource() const { return m_mediaSource; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (191720 => 191721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2015-10-29 05:20:51 UTC (rev 191720)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2015-10-29 05:30:40 UTC (rev 191721)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual ~MockSource() { }
</span><span class="cx"> 
</span><del>-    virtual RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() const { return m_capabilities; }
</del><ins>+    virtual RefPtr&lt;RealtimeMediaSourceCapabilities&gt; capabilities() { return m_capabilities; }
</ins><span class="cx">     virtual const RealtimeMediaSourceStates&amp; states() { return m_currentStates; }
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;RealtimeMediaSourceCapabilities&gt; m_capabilities;
</span></span></pre>
</div>
</div>

</body>
</html>