<!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 -> addObserver. Set private stream's public stream pointer.
(WebCore::MediaStream::~MediaStream): setClient -> 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 <eric.carlson@apple.com>
+
+ [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 -> addObserver. Set private stream's public stream pointer.
+ (WebCore::MediaStream::~MediaStream): setClient -> 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 -> 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 "capabilities" 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<> 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 <cdumez@apple.com>
</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<MediaStream*>& mediaStreams()
+{
+ static NeverDestroyed<Vector<MediaStream*>> streams;
+ return streams;
+}
+
+static void registerMediaStream(MediaStream* stream)
+{
+ mediaStreams().append(stream);
+}
+
+static void unRegisterMediaStream(MediaStream* stream)
+{
+ Vector<MediaStream*>& allStreams = mediaStreams();
+ size_t pos = allStreams.find(stream);
+ if (pos != notFound)
+ allStreams.remove(pos);
+}
+
+MediaStream* MediaStream::lookUp(const MediaStreamPrivate& privateStream)
+{
+ Vector<MediaStream*>& allStreams = mediaStreams();
+ for (auto& stream : allStreams) {
+ if (stream->m_private == &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& registry)
</span><span class="lines">@@ -58,7 +88,7 @@
</span><span class="cx">
</span><span class="cx"> Ref<MediaStream> MediaStream::create(ScriptExecutionContext& context)
</span><span class="cx"> {
</span><del>- return MediaStream::create(context);
</del><ins>+ return MediaStream::create(context, MediaStreamPrivate::create(Vector<RefPtr<MediaStreamTrackPrivate>>()));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Ref<MediaStream> MediaStream::create(ScriptExecutionContext& 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->active();
</span><del>- m_private->setClient(this);
</del><ins>+ m_private->addObserver(*this);
+ registerMediaStream(this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> MediaStream::MediaStream(ScriptExecutionContext& context, RefPtr<MediaStreamPrivate>&& streamPrivate)
</span><span class="lines">@@ -105,7 +136,8 @@
</span><span class="cx"> , m_activityEventTimer(*this, &MediaStream::activityEventTimerFired)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_private);
</span><del>- m_private->setClient(this);
</del><ins>+ m_private->addObserver(*this);
+ registerMediaStream(this);
</ins><span class="cx">
</span><span class="cx"> for (auto& trackPrivate : m_private->tracks()) {
</span><span class="cx"> RefPtr<MediaStreamTrack> 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->setClient(nullptr);
</del><ins>+ unRegisterMediaStream(this);
+ m_private->removeObserver(*this);
+ for (auto& track : m_trackSet.values())
+ track->removeObserver(this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RefPtr<MediaStream> 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& trackPrivate)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<MediaStreamTrack> 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& 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->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<MediaStream> {
</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&);
</span><span class="cx"> static MediaStream* lookUp(const URL&);
</span><span class="cx">
</span><ins>+ static MediaStream* lookUp(const MediaStreamPrivate&);
+
</ins><span class="cx"> static Ref<MediaStream> create(ScriptExecutionContext&);
</span><span class="cx"> static Ref<MediaStream> create(ScriptExecutionContext&, MediaStream*);
</span><span class="cx"> static Ref<MediaStream> create(ScriptExecutionContext&, const MediaStreamTrackVector&);
</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<MediaStreamPrivateClient>::ref;
- using RefCounted<MediaStreamPrivateClient>::deref;
</del><ins>+ using RefCounted<MediaStream>::ref;
+ using RefCounted<MediaStream>::deref;
</ins><span class="cx">
</span><span class="cx"> // URLRegistrable
</span><span class="cx"> virtual URLRegistry& 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&) override final;
</span><span class="cx"> virtual void didRemoveTrack(MediaStreamTrackPrivate&) 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&)
+{
+ configureTrackRendering();
+}
+
+void MediaStreamTrack::trackEnabledChanged(MediaStreamTrackPrivate&)
+{
+ 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&) override;
</span><span class="cx"> void trackMutedChanged(MediaStreamTrackPrivate&) override;
</span><span class="cx"> void trackStatesChanged(MediaStreamTrackPrivate&) override;
</span><ins>+ void trackProducingDataChanged(MediaStreamTrackPrivate&) override;
+ void trackEnabledChanged(MediaStreamTrackPrivate&) override;
</ins><span class="cx">
</span><span class="cx"> Vector<Observer*> m_observers;
</span><span class="cx"> Ref<MediaStreamTrackPrivate> 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()->isContextThread());
</span><del>- ASSERT(privateStream->client());
</del><span class="cx">
</span><del>- // FIXME: this class shouldn't know that the private stream client is a MediaStream!
- RefPtr<MediaStream> stream = static_cast<MediaStream*>(privateStream->client());
-
</del><span class="cx"> if (m_signalingState == SignalingStateClosed)
</span><span class="cx"> return;
</span><span class="cx">
</span><ins>+ RefPtr<MediaStream> 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<RealtimeMediaSourceCapabilities> MediaStreamAudioSource::capabilities() const
</del><ins>+RefPtr<RealtimeMediaSourceCapabilities> 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<RealtimeMediaSourceCapabilities> capabilities() const override;
</del><ins>+ RefPtr<RealtimeMediaSourceCapabilities> capabilities() override;
</ins><span class="cx"> const RealtimeMediaSourceStates& states() override;
</span><span class="cx">
</span><span class="cx"> const String& 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->sampleRate();
</span><del>- if (numberOfChannels != m_sourceNumberOfChannels || sourceSampleRate != sampleRate) {
- // The sample-rate must be equal to the context's sample-rate.
- if (!numberOfChannels || numberOfChannels > AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate) {
- // process() will generate silence for these uninitialized values.
- LOG(Media, "MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change", static_cast<unsigned>(numberOfChannels), sourceSampleRate);
- m_sourceNumberOfChannels = 0;
- return;
- }
</del><ins>+ if (numberOfChannels == m_sourceNumberOfChannels && sourceSampleRate == sampleRate)
+ return;
</ins><span class="cx">
</span><del>- // Synchronize with process().
- std::lock_guard<Lock> lock(m_processMutex);
</del><ins>+ // The sample-rate must be equal to the context's sample-rate.
+ if (!numberOfChannels || numberOfChannels > AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate) {
+ // process() will generate silence for these uninitialized values.
+ LOG(Media, "MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change", static_cast<unsigned>(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<Lock> 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<MultiChannelResampler>(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<MultiChannelResampler>(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)->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)->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 = "<group>"; };
</span><span class="cx">                 150524F01B712FF000696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlayerPrivateMediaStreamAVFObjC.h; sourceTree = "<group>"; };
</span><span class="cx">                 150524F11B712FF000696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaPlayerPrivateMediaStreamAVFObjC.mm; sourceTree = "<group>"; };
</span><del>-                150524F21B712FF000696AA9 /* MediaStreamPrivateAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamPrivateAVFObjC.h; sourceTree = "<group>"; };
-                150524F31B712FF000696AA9 /* MediaStreamPrivateAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaStreamPrivateAVFObjC.mm; sourceTree = "<group>"; };
</del><span class="cx">                 15145B8F1B3A1B3E00662BF7 /* MediaDeviceInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaDeviceInfo.h; sourceTree = "<group>"; };
</span><span class="cx">                 15145B911B3A1D4C00662BF7 /* MediaDeviceInfo.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaDeviceInfo.idl; sourceTree = "<group>"; };
</span><span class="cx">                 15739BB81B42012200D258C1 /* JSMediaDevices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaDevices.cpp; sourceTree = "<group>"; };
</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 "MediaPlayerPrivateMediaSourceAVFObjC.h"
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
+#include "MediaPlayerPrivateMediaStreamAVFObjC.h"
+#endif
+
</ins><span class="cx"> #endif // PLATFORM(COCOA)
</span><span class="cx">
</span><span class="cx"> #if PLATFORM(WIN) && USE(AVFOUNDATION) && !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) && USE(AVFOUNDATION)
</span><span class="cx">
</span><span class="cx"> #include "MediaPlayerPrivate.h"
</span><del>-#include "MediaStreamPrivateAVFObjC.h"
-#include "SourceBufferPrivateClient.h"
</del><ins>+#include "MediaStreamPrivate.h"
</ins><span class="cx"> #include <wtf/MediaTime.h>
</span><span class="cx"> #include <wtf/Vector.h>
</span><span class="cx"> #include <wtf/WeakPtr.h>
</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<String>& types);
</span><span class="cx"> static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&);
</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<MediaPlayerPrivateMediaStreamAVFObjC> 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&) override { };
</del><ins>+ // MediaPlayerPrivateInterface
+
+ // FIXME(146853): Implement necessary conformations to standard in HTMLMediaElement for MediaStream
+
+ void load(const String&) override;
</ins><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><del>- void load(const String&, MediaSourcePrivateClient*) override { };
</del><ins>+ void load(const String&, MediaSourcePrivateClient*) override;
</ins><span class="cx"> #endif
</span><del>-#if ENABLE(MEDIA_STREAM)
</del><span class="cx"> void load(MediaStreamPrivate&) 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&, const MediaTime&, const MediaTime&) 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<PlatformTimeRanges> seekable() const override;
</span><del>- MediaTime maxMediaTimeSeekable() const override;
- MediaTime minMediaTimeSeekable() const override;
</del><span class="cx"> std::unique_ptr<PlatformTimeRanges> 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&) override;
</del><ins>+ void setSize(const IntSize&) override { /* No-op */ }
</ins><span class="cx">
</span><span class="cx"> void paint(GraphicsContext&, const FloatRect&) override;
</span><span class="cx"> void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) override;
</span><ins>+ bool metaDataAvailable() const { return m_mediaStreamPrivate && m_readyState >= 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<CGImageRef> 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&);
</ins><span class="cx">
</span><del>- MediaPlayer* m_player;
</del><ins>+ void createPreviewLayers();
+
+ void setPausedImageVisible(bool);
+
+ void scheduleDeferredTask(std::function<void()>);
+
+ // MediaStreamPrivate::Observer
+ void activeStatusChanged() override;
+ void characteristicsChanged() override;
+
+ MediaPlayer* m_player { nullptr };
</ins><span class="cx"> WeakPtrFactory<MediaPlayerPrivateMediaStreamAVFObjC> m_weakPtrFactory;
</span><del>- RefPtr<MediaStreamPrivateAVFObjC> m_MediaStreamPrivate;
- RetainPtr<AVAsset> m_asset;
- RetainPtr<AVCaptureVideoPreviewLayer> m_previewLayer;
- RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
- Vector<RetainPtr<AVSampleBufferAudioRenderer>> m_sampleBufferAudioRenderers;
- RetainPtr<CGImageRef> m_lastImage;
- RetainPtr<id> m_timeJumpedObserver;
- RetainPtr<id> m_durationObserver;
- RetainPtr<AVStreamSession> 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<MediaStreamPrivate> m_mediaStreamPrivate;
+ mutable RetainPtr<CALayer> m_previewLayer;
+ mutable RetainPtr<PlatformLayer> m_videoBackgroundLayer;
+ RetainPtr<CGImageRef> m_pausedImage;
+ std::unique_ptr<Clock> 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) && USE(AVFOUNDATION)
</span><span class="cx">
</span><ins>+#import "AVAudioCaptureSource.h"
</ins><span class="cx"> #import "AVVideoCaptureSource.h"
</span><del>-#import "FileSystem.h"
</del><ins>+#import "Clock.h"
+#import "GraphicsContext.h"
</ins><span class="cx"> #import "Logging.h"
</span><span class="cx"> #import "MediaStreamPrivate.h"
</span><del>-#import "MediaStreamPrivateAVFObjC.h"
-#import "MediaTimeAVFoundation.h"
-#import "PlatformClockCM.h"
-#import "WebCoreSystemInterface.h"
-#import <AVFoundation/AVAsset.h>
-#import <AVFoundation/AVCaptureVideoPreviewLayer.h>
-#import <AVFoundation/AVTime.h>
</del><span class="cx"> #import <QuartzCore/CALayer.h>
</span><ins>+#import <QuartzCore/CATransaction.h>
</ins><span class="cx"> #import <objc_runtime.h>
</span><span class="cx"> #import <wtf/MainThread.h>
</span><span class="cx"> #import <wtf/NeverDestroyed.h>
</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, "MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC(%p)", this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC()
</span><span class="cx"> {
</span><ins>+ LOG(Media, "MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC(%p)", this);
+ if (m_mediaStreamPrivate)
+ m_mediaStreamPrivate->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()
- && isCoreMediaFrameworkAvailable();
</del><ins>+ return AVFoundationLibrary() && isCoreMediaFrameworkAvailable();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-static const HashSet<String>& mimeTypeCache()
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::getSupportedTypes(HashSet<String>& types)
</ins><span class="cx"> {
</span><span class="cx"> static NeverDestroyed<HashSet<String>> 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<String>& types)
-{
- types = mimeTypeCache();
-}
-
</del><span class="cx"> MediaPlayer::SupportsType MediaPlayerPrivateMediaStreamAVFObjC::supportsType(const MediaEngineSupportParameters& 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&)
+{
+ // This media engine only supports MediaStream URLs.
+ scheduleDeferredTask([this] {
+ setNetworkState(MediaPlayer::FormatError);
+ });
+}
+
+#if ENABLE(MEDIA_SOURCE)
+void MediaPlayerPrivateMediaStreamAVFObjC::load(const String&, MediaSourcePrivateClient*)
+{
+ // This media engine only supports MediaStream URLs.
+ scheduleDeferredTask([this] {
+ setNetworkState(MediaPlayer::FormatError);
+ });
+}
+#endif
+
</ins><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::load(MediaStreamPrivate& stream)
</span><span class="cx"> {
</span><span class="cx"> LOG(Media, "MediaPlayerPrivateMediaStreamAVFObjC::load(%p)", this);
</span><span class="cx">
</span><del>- m_MediaStreamPrivate = MediaStreamPrivateAVFObjC::create(*this, stream);
- for (auto track : stream.tracks()) {
- m_MediaStreamPrivate->addTrack(WTF::move(track));
- if (!track->ended()) {
- track->source()->startProducingData();
- track->setEnabled(true);
- }
- }
</del><ins>+ m_mediaStreamPrivate = &stream;
+ m_mediaStreamPrivate->addObserver(*this);
+ m_mediaStreamPrivate->startProducingData();
+
</ins><span class="cx"> m_previewLayer = nullptr;
</span><del>- for (auto& track : m_MediaStreamPrivate->tracks()) {
- if (track->type() == RealtimeMediaSource::Type::Video)
- m_previewLayer = static_cast<AVVideoCaptureSource*>(track->source())->previewLayer();
- }
- m_player->client().mediaPlayerRenderingModeChanged(m_player);
</del><ins>+
+ scheduleDeferredTask([this] {
+ setNetworkState(MediaPlayer::Idle);
+ if (m_readyState < MediaPlayer::ReadyState::HaveMetadata)
+ this->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, "MediaPlayerPrivateMediaStreamAVFObjC::cancelLoad(%p)", 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, "MediaPlayerPrivateMediaStreamAVFObjC::prepareToPlay(%p)", 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<PlatformLayer*>(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->stop();
+
+ RefPtr<Image> image = m_mediaStreamPrivate->currentFrameImage();
+ if (!image)
+ break;
+
+ m_pausedImage = image->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->isProducingData()) {
+ m_waitingForNewFrame = true;
+ break;
+ }
+
+ m_clock->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()->playInternal();
- });
-}
</del><ins>+ LOG(Media, "MediaPlayerPrivateMediaStreamAVFObjC::play(%p)", 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& track : m_MediaStreamPrivate->tracks())
- track->source()->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()->pauseInternal();
- });
-}
</del><ins>+ LOG(Media, "MediaPlayerPrivateMediaStreamAVFObjC::pause(%p)", 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& track : m_MediaStreamPrivate->tracks())
- track->source()->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& track : m_MediaStreamPrivate->tracks()) {
- if (track->type() == RealtimeMediaSource::Type::Audio)
- track->source()->setMuted(muted);
- }
-}
</del><ins>+ LOG(Media, "MediaPlayerPrivateMediaStreamAVFObjC::setMuted(%p)", this);
</ins><span class="cx">
</span><del>-FloatSize MediaPlayerPrivateMediaStreamAVFObjC::naturalSize() const
-{
- FloatSize floatSize(0, 0);
- for (auto& track : m_MediaStreamPrivate->tracks()) {
- if (track->type() == RealtimeMediaSource::Type::Video) {
- AVVideoCaptureSource* source = (AVVideoCaptureSource*)track->source();
- if (!source->stopped() && track->enabled()) {
- if (source->width() > floatSize.width())
- floatSize.setWidth(source->width());
- if (source->height() > floatSize.height())
- floatSize.setHeight(source->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& track : m_MediaStreamPrivate->tracks()) {
- if (track->type() == RealtimeMediaSource::Type::Video)
- return true;
- }
- return false;
</del><ins>+ if (!metaDataAvailable())
+ return false;
+
+ return m_mediaStreamPrivate->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& track : m_MediaStreamPrivate->tracks()) {
- if (track->type() == RealtimeMediaSource::Type::Audio)
- return true;
- }
- return false;
</del><ins>+ if (!metaDataAvailable())
+ return false;
+
+ return m_mediaStreamPrivate->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->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->sizeChanged();
</del><ins>+ if (m_mediaStreamPrivate) {
+ if (m_mediaStreamPrivate->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<PlatformTimeRanges> MediaPlayerPrivateMediaStreamAVFObjC::seekable() const
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::activeStatusChanged()
</ins><span class="cx"> {
</span><del>- return std::make_unique<PlatformTimeRanges>(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& 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->client().mediaPlayerRenderingCanBeAccelerated(m_player))
+ return RenderingModeUnchanged;
+
+ if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->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 = @"MediaPlayerPrivateMediaStreamAVFObjC preview background layer";
+#endif
+
+ m_previewLayer = m_mediaStreamPrivate->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<PlatformTimeRanges> MediaPlayerPrivateMediaStreamAVFObjC::buffered() const
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::characteristicsChanged()
</ins><span class="cx"> {
</span><del>- return std::make_unique<PlatformTimeRanges>();
-}
</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->intrinsicSize();
+ if (intrinsicSize.height() != m_intrinsicSize.height() || intrinsicSize.width() != m_intrinsicSize.width()) {
+ status = updateIntrinsicSize(intrinsicSize);
+ sizeChanged = true;
+ }
+
+ if (m_waitingForNewFrame && m_mediaStreamPrivate->isProducingData())
+ setPausedImageVisible(false);
+
+ MediaPlayer::ReadyState newReadyState = currentReadyState();
+ scheduleDeferredTask([this, sizeChanged, newReadyState, status] {
+ if (newReadyState != m_readyState)
+ setReadyState(newReadyState);
+
+ if (!m_player)
+ return;
+
+ m_player->characteristicChanged();
+ if (sizeChanged) {
+ m_player->sizeChanged();
+ if (status == RenderingModeChanged)
+ m_player->client().mediaPlayerRenderingModeChanged(m_player);
+ }
+ });
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void MediaPlayerPrivateMediaStreamAVFObjC::setSize(const IntSize&)
</del><ins>+std::unique_ptr<PlatformTimeRanges> MediaPlayerPrivateMediaStreamAVFObjC::seekable() const
</ins><span class="cx"> {
</span><del>- // No-op.
</del><ins>+ return std::make_unique<PlatformTimeRanges>();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-RetainPtr<CGImageRef> MediaPlayerPrivateMediaStreamAVFObjC::createImageFromSampleBuffer(CMSampleBufferRef sampleBuffer)
</del><ins>+std::unique_ptr<PlatformTimeRanges> MediaPlayerPrivateMediaStreamAVFObjC::buffered() const
</ins><span class="cx"> {
</span><del>- CVPixelBufferRef imageBuffer = static_cast<CVPixelBufferRef>(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<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
- RetainPtr<CGDataProviderRef> provider = adoptCF(CGDataProviderCreateWithData(NULL, baseAddress, bytesPerRow * height, NULL));
- RetainPtr<CGImageRef> 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<PlatformTimeRanges>();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void MediaPlayerPrivateMediaStreamAVFObjC::paint(GraphicsContext& context, const FloatRect& 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&, const FloatRect&)
</del><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::paintCurrentFrameInContext(GraphicsContext& context, const FloatRect& 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->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<String> description(ASCIILiteral("AVFoundation MediaStream Engine"));
</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 && m_readyState >= MediaPlayer::HaveFutureData;
</span><span class="lines">@@ -420,6 +434,27 @@
</span><span class="cx"> m_player->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->networkStateChanged();
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask(std::function<void()> 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) && USE(AVFOUNDATION)
-
-#include "MediaPlayer.h"
-#include "MediaStreamPrivate.h"
-#include <wtf/Deque.h>
-#include <wtf/HashMap.h>
-#include <wtf/MediaTime.h>
-#include <wtf/RefPtr.h>
-#include <wtf/RetainPtr.h>
-#include <wtf/Vector.h>
-
-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<MediaStreamPrivateAVFObjC> create(MediaPlayerPrivateMediaStreamAVFObjC&, MediaStreamPrivate&);
- 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<PlatformTimeRanges> buffered();
-
- bool hasAudio() const;
- bool hasVideo() const;
-
- void setReadyState(MediaPlayer::ReadyState);
- FloatSize naturalSize() const;
-
- MediaPlayer::ReadyState readyState() const;
-
-private:
- MediaStreamPrivateAVFObjC(MediaPlayerPrivateMediaStreamAVFObjC&, MediaStreamPrivate&);
-
- MediaPlayerPrivateMediaStreamAVFObjC* m_player;
- RefPtr<MediaStreamPrivateClient> m_client;
-};
-
-}
-
-#endif // ENABLE(MEDIA_STREAM) && 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 "config.h"
-#include "MediaStreamPrivateAVFObjC.h"
-
-#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
-
-#import "ContentType.h"
-#import "ExceptionCodePlaceholder.h"
-#import "MediaPlayerPrivateMediaStreamAVFObjC.h"
-#import "MediaStreamPrivate.h"
-#import "SoftLinking.h"
-#import "SourceBufferPrivateAVFObjC.h"
-#import <objc/runtime.h>
-#import <wtf/text/AtomicString.h>
-#import <wtf/text/StringBuilder.h>
-
-namespace WebCore {
-
-#pragma mark -
-#pragma mark MediaStreamPrivateAVFObjC
-
-RefPtr<MediaStreamPrivateAVFObjC> MediaStreamPrivateAVFObjC::create(MediaPlayerPrivateMediaStreamAVFObjC& parent, MediaStreamPrivate& stream)
-{
- return adoptRef(new MediaStreamPrivateAVFObjC(parent, stream));
-}
-
-MediaStreamPrivateAVFObjC::MediaStreamPrivateAVFObjC(MediaPlayerPrivateMediaStreamAVFObjC& parent, MediaStreamPrivate& stream)
- : MediaStreamPrivate(*stream.client())
- , m_player(&parent)
-{
-}
-
-MediaStreamPrivateAVFObjC::~MediaStreamPrivateAVFObjC()
-{
-}
-
-MediaTime MediaStreamPrivateAVFObjC::duration()
-{
- return MediaTime::positiveInfiniteTime();
-}
-
-std::unique_ptr<PlatformTimeRanges> MediaStreamPrivateAVFObjC::buffered()
-{
- return std::unique_ptr<PlatformTimeRanges>();
-}
-
-MediaPlayer::ReadyState MediaStreamPrivateAVFObjC::readyState() const
-{
- return m_player->readyState();
-}
-
-void MediaStreamPrivateAVFObjC::setReadyState(MediaPlayer::ReadyState readyState)
-{
- m_player->setReadyState(readyState);
-}
-
-bool MediaStreamPrivateAVFObjC::hasAudio() const
-{
- return m_player->hasAudio();
-}
-
-bool MediaStreamPrivateAVFObjC::hasVideo() const
-{
- return m_player->hasVideo();
-}
-
-FloatSize MediaStreamPrivateAVFObjC::naturalSize() const
-{
- return m_player->naturalSize();
-}
-
-}
-
-#endif // ENABLE(MEDIA_STREAM) && 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 "config.h"
</span><ins>+#include "MediaStreamPrivate.h"
</ins><span class="cx">
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx">
</span><del>-#include "MediaStreamPrivate.h"
-
</del><ins>+#include "GraphicsContext.h"
+#include "IntRect.h"
</ins><span class="cx"> #include "UUID.h"
</span><ins>+#include <wtf/MainThread.h>
</ins><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="cx"> #include <wtf/Vector.h>
</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& id, const MediaStreamTrackPrivateVector& 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& track : tracks)
</del><ins>+ for (auto& track : tracks) {
+ track->addObserver(*this);
</ins><span class="cx"> m_trackSet.add(track->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& client)
- : m_client(&client)
</del><ins>+MediaStreamPrivate::~MediaStreamPrivate()
</ins><span class="cx"> {
</span><ins>+ for (auto& track : m_trackSet.values())
+ track->removeObserver(*this);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-MediaStreamPrivate::~MediaStreamPrivate()
</del><ins>+void MediaStreamPrivate::addObserver(MediaStreamPrivate::Observer& observer)
</ins><span class="cx"> {
</span><del>- m_client = nullptr;
- m_isActive = false;
</del><ins>+ m_observers.append(&observer);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void MediaStreamPrivate::removeObserver(MediaStreamPrivate::Observer& observer)
+{
+ size_t pos = m_observers.find(&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& track : m_trackSet.values()) {
</span><ins>+
</ins><span class="cx"> if (!track->ended()) {
</span><span class="cx"> newActiveState = true;
</span><del>- break;
</del><ins>+ if (track->source()->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 && notifyClientOption == NotifyClientOption::Notify)
- m_client->activeStatusChanged();
</del><ins>+ if (notifyClientOption == NotifyClientOption::Notify) {
+ for (auto& observer : m_observers)
+ observer->activeStatusChanged();
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void MediaStreamPrivate::addTrack(RefPtr<MediaStreamTrackPrivate>&& track, NotifyClientOption notifyClientOption)
</span><span class="lines">@@ -119,8 +140,10 @@
</span><span class="cx"> track->addObserver(*this);
</span><span class="cx"> m_trackSet.add(track->id(), track);
</span><span class="cx">
</span><del>- if (m_client && notifyClientOption == NotifyClientOption::Notify)
- m_client->didAddTrack(*track.get());
</del><ins>+ if (notifyClientOption == NotifyClientOption::Notify) {
+ for (auto& observer : m_observers)
+ observer->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 && notifyClientOption == NotifyClientOption::Notify)
- m_client->didRemoveTrack(track);
</del><ins>+ if (notifyClientOption == NotifyClientOption::Notify) {
+ for (auto& observer : m_observers)
+ observer->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& track : m_trackSet.values())
+ track->startProducingData();
+}
+
+void MediaStreamPrivate::stopProducingData()
+{
+ for (auto& track : m_trackSet.values())
+ track->stopProducingData();
+}
+
+bool MediaStreamPrivate::isProducingData() const
+{
+ for (auto& track : m_trackSet.values()) {
+ if (track->isProducingData())
+ return true;
+ }
+ return false;
+}
+
+bool MediaStreamPrivate::hasVideo()
+{
+ for (auto& track : m_trackSet.values()) {
+ if (track->type() == RealtimeMediaSource::Type::Video && track->enabled())
+ return true;
+ }
+ return false;
+}
+
+bool MediaStreamPrivate::hasAudio()
+{
+ for (auto& track : m_trackSet.values()) {
+ if (track->type() == RealtimeMediaSource::Type::Audio && track->enabled())
+ return true;
+ }
+ return false;
+}
+
+FloatSize MediaStreamPrivate::intrinsicSize() const
+{
+ FloatSize size;
+
+ if (m_activeVideoTrack) {
+ const RealtimeMediaSourceStates& states = m_activeVideoTrack->source()->states();
+ size.setWidth(states.width());
+ size.setHeight(states.height());
+ }
+
+ return size;
+}
+
+PlatformLayer* MediaStreamPrivate::platformLayer() const
+{
+ if (!m_activeVideoTrack)
+ return nullptr;
+
+ return m_activeVideoTrack->source()->platformLayer();
+}
+
+void MediaStreamPrivate::paintCurrentFrameInContext(GraphicsContext& context, const FloatRect& rect)
+{
+ if (context.paintingDisabled())
+ return;
+
+ if (active() && m_activeVideoTrack)
+ m_activeVideoTrack->source()->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<Image> MediaStreamPrivate::currentFrameImage()
+{
+ if (!active() && !m_activeVideoTrack)
+ return nullptr;
+
+ return m_activeVideoTrack->source()->currentFrameImage();
+}
+
+void MediaStreamPrivate::characteristicsChanged()
+{
+ for (auto& observer : m_observers)
+ observer->characteristicsChanged();
+}
+
+void MediaStreamPrivate::trackMutedChanged(MediaStreamTrackPrivate&)
+{
+ scheduleDeferredTask([this] {
+ characteristicsChanged();
+ });
+}
+
+void MediaStreamPrivate::trackStatesChanged(MediaStreamTrackPrivate&)
+{
+ characteristicsChanged();
+}
+
+void MediaStreamPrivate::trackEnabledChanged(MediaStreamTrackPrivate&)
+{
+ scheduleDeferredTask([this] {
+ characteristicsChanged();
+ });
+}
+
+void MediaStreamPrivate::trackProducingDataChanged(MediaStreamTrackPrivate&)
+{
+ scheduleDeferredTask([this] {
+ characteristicsChanged();
+ });
+}
+
+void MediaStreamPrivate::scheduleDeferredTask(std::function<void()> 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 "FloatSize.h"
</ins><span class="cx"> #include "MediaStreamTrack.h"
</span><span class="cx"> #include "MediaStreamTrackPrivate.h"
</span><span class="cx"> #include <wtf/HashMap.h>
</span><ins>+#include <wtf/MediaTime.h>
</ins><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="cx"> #include <wtf/RefPtr.h>
</span><span class="cx"> #include <wtf/Vector.h>
</span><ins>+#include <wtf/WeakPtr.h>
</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<MediaStreamPrivateClient> {
</del><ins>+class MediaStreamPrivate : public MediaStreamTrackPrivate::Observer, public RefCounted<MediaStreamPrivate> {
</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&) = 0;
- virtual void didRemoveTrack(MediaStreamTrackPrivate&) = 0;
-};
</del><ins>+ virtual void characteristicsChanged() { }
+ virtual void activeStatusChanged() { }
+ virtual void didAddTrack(MediaStreamTrackPrivate&) { }
+ virtual void didRemoveTrack(MediaStreamTrackPrivate&) { }
+ };
</ins><span class="cx">
</span><del>-class MediaStreamPrivate : public MediaStreamTrackPrivate::Observer, public RefCounted<MediaStreamPrivate> {
-public:
</del><span class="cx"> static RefPtr<MediaStreamPrivate> create(const Vector<RefPtr<RealtimeMediaSource>>& audioSources, const Vector<RefPtr<RealtimeMediaSource>>& videoSources);
</span><span class="cx"> static RefPtr<MediaStreamPrivate> create(const MediaStreamTrackPrivateVector&);
</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&);
+ void removeObserver(Observer&);
</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<MediaStreamTrackPrivate>&&, NotifyClientOption = NotifyClientOption::Notify);
</span><span class="cx"> void removeTrack(MediaStreamTrackPrivate&, NotifyClientOption = NotifyClientOption::Notify);
</span><span class="cx">
</span><del>-protected:
- explicit MediaStreamPrivate(MediaStreamPrivateClient&);
</del><ins>+ void startProducingData();
+ void stopProducingData();
+ bool isProducingData() const;
</ins><span class="cx">
</span><ins>+ PlatformLayer* platformLayer() const;
+ RefPtr<Image> currentFrameImage();
+ void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&);
+
+ bool hasVideo();
+ bool hasAudio();
+
+ FloatSize intrinsicSize() const;
+
+ WeakPtr<MediaStreamPrivate> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
</ins><span class="cx"> private:
</span><span class="cx"> MediaStreamPrivate(const String&, const MediaStreamTrackPrivateVector&);
</span><span class="cx">
</span><span class="cx"> void trackEnded(MediaStreamTrackPrivate&) override { }
</span><del>- void trackMutedChanged(MediaStreamTrackPrivate&) override { }
- void trackStatesChanged(MediaStreamTrackPrivate&) override { }
</del><ins>+ void trackMutedChanged(MediaStreamTrackPrivate&) override;
+ void trackStatesChanged(MediaStreamTrackPrivate&) override;
+ void trackProducingDataChanged(MediaStreamTrackPrivate&) override;
+ void trackEnabledChanged(MediaStreamTrackPrivate&) override;
</ins><span class="cx">
</span><del>- MediaStreamPrivateClient* m_client { nullptr };
</del><ins>+ void characteristicsChanged();
+
+ void scheduleDeferredTask(std::function<void()>);
+
+ WeakPtrFactory<MediaStreamPrivate> m_weakPtrFactory;
+ Vector<Observer*> m_observers;
</ins><span class="cx"> String m_id;
</span><ins>+ MediaStreamTrackPrivate* m_activeVideoTrack { nullptr };
+ HashMap<String, RefPtr<MediaStreamTrackPrivate>> m_trackSet;
</ins><span class="cx"> bool m_isActive { false };
</span><del>-
- HashMap<String, RefPtr<MediaStreamTrackPrivate>> m_trackSet;
</del><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> typedef Vector<RefPtr<MediaStreamPrivate>> 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->trackStatesChanged(*this);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void MediaStreamTrackPrivate::sourceProducingDataChanged()
+{
+ for (auto& observer : m_observers)
+ observer->trackProducingDataChanged(*this);
+}
+
+void MediaStreamTrackPrivate::sourceEnabledChanged()
+{
+ for (auto& observer : m_observers)
+ observer->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&) = 0;
</span><span class="cx"> virtual void trackMutedChanged(MediaStreamTrackPrivate&) = 0;
</span><span class="cx"> virtual void trackStatesChanged(MediaStreamTrackPrivate&) = 0;
</span><ins>+ virtual void trackProducingDataChanged(MediaStreamTrackPrivate&) = 0;
+ virtual void trackEnabledChanged(MediaStreamTrackPrivate&) = 0;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> static RefPtr<MediaStreamTrackPrivate> create(RefPtr<RealtimeMediaSource>&&);
</span><span class="lines">@@ -62,6 +64,7 @@
</span><span class="cx">
</span><span class="cx"> void startProducingData() { m_source->startProducingData(); }
</span><span class="cx"> void stopProducingData() { m_source->stopProducingData(); }
</span><ins>+ bool isProducingData() { return m_source->isProducingData(); }
</ins><span class="cx">
</span><span class="cx"> bool muted() const;
</span><span class="cx"> void setMuted(bool muted) const { m_source->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<Observer*> m_observers;
</span><span class="cx"> RefPtr<RealtimeMediaSource> 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->sourceStatesChanged();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void RealtimeMediaSource::isProducingDataDidChange()
+{
+ for (auto& observer : m_observers)
+ observer->sourceProducingDataChanged();
+}
+
+void RealtimeMediaSource::setEnabled(bool enabled)
+{
+ if (m_enabled == enabled)
+ return;
+
+ m_enabled = enabled;
+ for (auto& observer : m_observers)
+ observer->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 "AudioSourceProvider.h"
</span><ins>+#include "Image.h"
</ins><span class="cx"> #include "MediaConstraints.h"
</span><ins>+#include "PlatformLayer.h"
</ins><span class="cx"> #include "RealtimeMediaSourceCapabilities.h"
</span><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="cx"> #include <wtf/Vector.h>
</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& id() const { return m_id; }
</span><span class="cx">
</span><span class="cx"> const String& 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<RealtimeMediaSourceCapabilities> capabilities() const = 0;
</del><ins>+ virtual RefPtr<RealtimeMediaSourceCapabilities> capabilities() = 0;
</ins><span class="cx"> virtual const RealtimeMediaSourceStates& 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<Image> currentFrameImage() { return nullptr; }
+ virtual void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) { }
+
</ins><span class="cx"> protected:
</span><span class="cx"> RealtimeMediaSource(const String& id, Type, const String& 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&, PassRefPtr<MediaConstraints>);
</span><span class="cx"> virtual ~AVAudioCaptureSource();
</span><span class="cx">
</span><del>- RefPtr<RealtimeMediaSourceCapabilities> capabilities() const override;
</del><ins>+ void initializeCapabilities(RealtimeMediaSourceCapabilities&) 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 "CoreMediaSoftLink.h"
</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<RealtimeMediaSourceCapabilities> AVAudioCaptureSource::capabilities() const
</del><ins>+void AVAudioCaptureSource::initializeCapabilities(RealtimeMediaSourceCapabilities&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->mSampleRate)
</span><span class="cx"> observer->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<AVCaptureDeviceInputType> 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, "AVVideoCaptureSource::setupCaptureSession(%p), unable to add audio input device", this);
+ return;
+ }
+ [session() addInput:audioIn.get()];
+
</ins><span class="cx"> RetainPtr<AVCaptureAudioDataOutputType> 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, "AVVideoCaptureSource::setupCaptureSession(%p), unable to add audio sample buffer output delegate", 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<AudioStreamBasicDescription>();
+
+ for (auto& observer : m_observers)
+ observer->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& a, const AudioStreamBasicDescription& 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<Observer*> 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<Lock> 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<AudioStreamBasicDescription>(*streamDescription);
</span><del>- for (auto& observer : observers)
</del><ins>+ for (auto& observer : m_observers)
</ins><span class="cx"> observer->prepare(m_inputDescription.get());
</span><span class="cx"> }
</span><span class="cx">
</span><del>- for (auto& observer : observers)
</del><ins>+ for (auto& observer : m_observers)
</ins><span class="cx"> observer->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<AVMediaCaptureSource> m_audioAVMediaCaptureSource;
-
</del><span class="cx"> String m_videoSourceId;
</span><del>- RefPtr<AVMediaCaptureSource> 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 && !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<RealtimeMediaSource> 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 && !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<RealtimeMediaSource> 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<CaptureDevice>& devices = captureDeviceList();
</span><del>- for (auto captureDevice : devices) {
- if (!captureDevice.m_enabled)
</del><ins>+ for (auto& 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 && captureDevice.m_audioSourceId.isEmpty())
</ins><span class="cx"> continue;
</span><ins>+ if (type == RealtimeMediaSource::Video && captureDevice.m_videoSourceId.isEmpty())
+ continue;
</ins><span class="cx">
</span><ins>+ AVCaptureDeviceType *device = [AVCaptureDevice deviceWithUniqueID:captureDevice.m_captureDeviceID];
+ ASSERT(device);
+
+ RefPtr<AVMediaCaptureSource> 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 && captureDevice.m_videoAVMediaCaptureSource)
- captureDevice.m_videoAVMediaCaptureSource->session();
- else if (type == RealtimeMediaSource::Audio && captureDevice.m_audioAVMediaCaptureSource)
- captureDevice.m_audioAVMediaCaptureSource->session();
</del><ins>+ if (type == RealtimeMediaSource::Video)
+ session = captureSource->session();
+ else if (type == RealtimeMediaSource::Audio)
+ session = captureSource->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 && !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 && !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& 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<AVMediaCaptureSource> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
</ins><span class="cx"> protected:
</span><span class="cx"> AVMediaCaptureSource(AVCaptureDevice*, const AtomicString&, RealtimeMediaSource::Type, PassRefPtr<MediaConstraints>);
</span><span class="cx">
</span><del>- const RealtimeMediaSourceStates& 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&) = 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 &m_currentStates; }
</span><span class="cx"> MediaConstraints* constraints() { return m_constraints.get(); }
</span><span class="cx">
</span><ins>+ RefPtr<RealtimeMediaSourceCapabilities> 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<void ()>);
</span><span class="cx">
</span><del>- void statesDidChanged() { }
-
</del><span class="cx"> private:
</span><span class="cx"> void setupSession();
</span><del>- WeakPtr<AVMediaCaptureSource> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
</del><ins>+ void reset() override;
</ins><span class="cx">
</span><span class="cx"> WeakPtrFactory<AVMediaCaptureSource> m_weakPtrFactory;
</span><span class="cx"> RetainPtr<WebCoreAVMediaCaptureSourceObserver> m_objcObserver;
</span><span class="cx"> RefPtr<MediaConstraints> m_constraints;
</span><ins>+ RefPtr<RealtimeMediaSourceCapabilities> m_capabilities;
</ins><span class="cx"> RealtimeMediaSourceStates m_currentStates;
</span><span class="cx"> RetainPtr<AVCaptureSession> m_session;
</span><span class="cx"> RetainPtr<AVCaptureDevice> 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& 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<RealtimeMediaSourceCapabilities> AVMediaCaptureSource::capabilities()
+{
+ if (!m_capabilities) {
+ m_capabilities = RealtimeMediaSourceCapabilities::create();
+ m_capabilities->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 = [@[@"running"] 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->captureSessionStoppedRunning();
- });
</del><ins>+ m_callback->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->captureOutputDidOutputSampleBufferFromConnection(captureOutput, sampleBuffer, connection);
</del><ins>+ id newValue = [change valueForKey:NSKeyValueChangeNewKey];
+
+#if !LOG_DISABLED
+ bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
+
+ if (willChange)
+ LOG(Media, "WebCoreAVMediaCaptureSourceObserver::observeValueForKeyPath(%p) - will change, keyPath = %s", self, [keyPath UTF8String]);
+ else {
+ RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
+ LOG(Media, "WebCoreAVMediaCaptureSourceObserver::observeValueForKeyPath(%p) - did change, keyPath = %s, value = %s", self, [keyPath UTF8String], [valueString.get() UTF8String]);
+ }
+#endif
+
+ if ([keyPath isEqualToString:@"running"])
+ m_callback->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 "AVMediaCaptureSource.h"
</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&, const FloatRect&);
- RetainPtr<CGImageRef> currentFrameImage();
-
</del><span class="cx"> private:
</span><span class="cx"> AVVideoCaptureSource(AVCaptureDevice*, const AtomicString&, PassRefPtr<MediaConstraints>);
</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<RealtimeMediaSourceCapabilities> capabilities() const override;
</del><ins>+ void initializeCapabilities(RealtimeMediaSourceCapabilities&) 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<CMSampleBufferRef>);
</span><span class="cx">
</span><del>- RetainPtr<AVCaptureConnection> m_videoConnection;
- RetainPtr<AVCaptureVideoPreviewLayer> m_videoPreviewLayer;
</del><ins>+ void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) override;
+ PlatformLayer* platformLayer() const override;
+
+ RetainPtr<CGImageRef> currentFrameCGImage();
+ RefPtr<Image> currentFrameImage() override;
+
</ins><span class="cx"> RetainPtr<CMSampleBufferRef> m_buffer;
</span><span class="cx"> RetainPtr<CGImageRef> m_lastImage;
</span><span class="cx"> Vector<Float64> m_videoFrameTimeStamps;
</span><del>- Float64 m_frameRate;
- int32_t m_width;
- int32_t m_height;
</del><ins>+ mutable RetainPtr<PlatformLayer> 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 "AVCaptureDeviceManager.h"
</span><span class="cx"> #import "BlockExceptions.h"
</span><span class="cx"> #import "GraphicsContextCG.h"
</span><ins>+#import "ImageBuffer.h"
</ins><span class="cx"> #import "IntRect.h"
</span><span class="cx"> #import "Logging.h"
</span><span class="cx"> #import "MediaConstraints.h"
</span><span class="cx"> #import "NotImplemented.h"
</span><ins>+#import "PlatformLayer.h"
</ins><span class="cx"> #import "RealtimeMediaSourceStates.h"
</span><span class="cx"> #import <AVFoundation/AVFoundation.h>
</span><span class="cx"> #import <objc/runtime.h>
</span><span class="lines">@@ -98,9 +100,6 @@
</span><span class="cx">
</span><span class="cx"> AVVideoCaptureSource::AVVideoCaptureSource(AVCaptureDeviceType* device, const AtomicString& id, PassRefPtr<MediaConstraints> 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()->setSourceId(id);
</span><span class="cx"> currentStates()->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<RealtimeMediaSourceCapabilities> AVVideoCaptureSource::capabilities() const
</del><ins>+void AVVideoCaptureSource::initializeCapabilities(RealtimeMediaSourceCapabilities& capabilities)
</ins><span class="cx"> {
</span><del>- notImplemented();
- return 0;
</del><ins>+ // FIXME: finish this implementation
+ capabilities.setSourceId(currentStates()->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<AVCaptureDeviceInputType> 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, "AVVideoCaptureSource::setupCaptureSession(%p), unable to add video input device", 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, "AVVideoCaptureSource::setupCaptureSession(%p), unable to add video sample buffer output delegate", 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<CMSampleBufferRef> 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 && (!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<CGImageRef> AVVideoCaptureSource::currentFrameImage()
</del><ins>+RefPtr<Image> AVVideoCaptureSource::currentFrameImage()
</ins><span class="cx"> {
</span><ins>+ if (!currentFrameCGImage())
+ return nullptr;
+
+ FloatRect imageRect(0, 0, m_width, m_height);
+ std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size(), Unaccelerated);
+
+ if (!imageBuffer)
+ return nullptr;
+
+ paintCurrentFrameInContext(imageBuffer->context(), imageRect);
+
+ return imageBuffer->copyImage();
+}
+
+RetainPtr<CGImageRef> 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& context, const FloatRect& 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 = @"AVVideoCaptureSource preview layer";
+#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<AudioBufferList> m_list;
</span><del>- RetainPtr<AudioConverterRef> m_converter;
</del><ins>+ AudioConverterRef m_converter;
</ins><span class="cx"> std::unique_ptr<AudioStreamBasicDescription> m_inputDescription;
</span><span class="cx"> std::unique_ptr<AudioStreamBasicDescription> m_outputDescription;
</span><span class="cx"> std::unique_ptr<CARingBuffer> 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->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->mBytesPerFrame = sizeof(Float32);
</span><span class="cx"> m_outputDescription->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(), &outConverter);
</del><ins>+ OSStatus err = AudioConverterNew(m_inputDescription.get(), m_outputDescription.get(), &outConverter);
+ if (err) {
+ LOG(Media, "WebAudioSourceProviderAVFObjC::prepare(%p) - AudioConverterNew returned error %i", 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, &buffer);
</span><span class="cx">
</span><span class="cx"> if (err) {
</span><del>- LOG(Media, "WebAudioSourceProviderAVFObjC::proess(%p) - CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer returned error %i", this, err);
</del><ins>+ LOG(Media, "WebAudioSourceProviderAVFObjC::process(%p) - CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer returned error %i", 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<RealtimeMediaSourceCapabilities> capabilities() const { return m_capabilities; }
</del><ins>+ virtual RefPtr<RealtimeMediaSourceCapabilities> capabilities() { return m_capabilities; }
</ins><span class="cx"> virtual const RealtimeMediaSourceStates& 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<RealtimeMediaSourceCapabilities> capabilities() const { return m_capabilities; }
</del><ins>+ virtual RefPtr<RealtimeMediaSourceCapabilities> capabilities() { return m_capabilities; }
</ins><span class="cx"> virtual const RealtimeMediaSourceStates& states() { return m_currentStates; }
</span><span class="cx">
</span><span class="cx"> RefPtr<RealtimeMediaSourceCapabilities> m_capabilities;
</span></span></pre>
</div>
</div>
</body>
</html>