Title: [208851] trunk/Source/WebCore
Revision
208851
Author
[email protected]
Date
2016-11-17 10:43:40 -0800 (Thu, 17 Nov 2016)

Log Message

[MediaStream][Mac] Use AVCapturePreview object for camera/microphone rendering
https://bugs.webkit.org/show_bug.cgi?id=164837
<rdar://problem/29297727>

Reviewed by Jer Noble.

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

* WebCore.xcodeproj/project.pbxproj:

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

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

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

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

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

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

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

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

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (208850 => 208851)


--- trunk/Source/WebCore/ChangeLog	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/ChangeLog	2016-11-17 18:43:40 UTC (rev 208851)
@@ -1,3 +1,109 @@
+2016-11-17  Eric Carlson  <[email protected]>
+
+        [MediaStream][Mac] Use AVCapturePreview object for camera/microphone rendering
+        https://bugs.webkit.org/show_bug.cgi?id=164837
+        <rdar://problem/29297727>
+
+        Reviewed by Jer Noble.
+
+        No new tests, the real capture devices can not be used in layout tests.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        
+        Drive-by fix: clear m_settingMediaStreamSrcObject when the media player is destroyed unless
+        that happens as a side effect of setting video.srcObject.
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::setSrcObject):
+        (WebCore::HTMLMediaElement::clearMediaPlayer):
+        * html/HTMLMediaElement.h:
+
+        Add support for realtime media source that vend a preview interface, while keeping support
+        for those that do not (e.g. the mock capture devices).
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::isAvailable):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSampleBuffer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::prepareVideoSampleBufferFromTrack):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::destroyLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::play):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::pause):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::internalSetVolume):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateTracks):
+
+        * platform/mediastream/MediaStreamPrivate.cpp:
+        (WebCore::MediaStreamPrivate::platformLayer): Deleted, no longer used.
+        * platform/mediastream/MediaStreamPrivate.h:
+
+        Enable/disable the preview when available.
+        * platform/mediastream/MediaStreamTrackPrivate.cpp:
+        (WebCore::MediaStreamTrackPrivate::setEnabled):
+        (WebCore::MediaStreamTrackPrivate::endTrack):
+        (WebCore::MediaStreamTrackPrivate::preview):
+        * platform/mediastream/MediaStreamTrackPrivate.h:
+
+        * platform/mediastream/RealtimeMediaSource.h:
+        (WebCore::RealtimeMediaSource::preview):
+        (WebCore::RealtimeMediaSource::createWeakPtr):
+        (WebCore::RealtimeMediaSource::platformLayer): Deleted.
+
+        Define a realtime media source preview interface.
+        * platform/mediastream/RealtimeMediaSourcePreview.h: Added.
+        (WebCore::RealtimeMediaSourcePreview::~RealtimeMediaSourcePreview):
+        (WebCore::RealtimeMediaSourcePreview::invalidate):
+        (WebCore::RealtimeMediaSourcePreview::createWeakPtr):
+        (WebCore::RealtimeMediaSourcePreview::RealtimeMediaSourcePreview):
+
+        Implement the preview interface.
+        * platform/mediastream/mac/AVAudioCaptureSource.h:
+        * platform/mediastream/mac/AVAudioCaptureSource.mm:
+        (WebCore::AVAudioSourcePreview::create):
+        (WebCore::AVAudioSourcePreview::AVAudioSourcePreview):
+        (WebCore::AVAudioSourcePreview::invalidate):
+        (WebCore::AVAudioSourcePreview::play):
+        (WebCore::AVAudioSourcePreview::pause):
+        (WebCore::AVAudioSourcePreview::setEnabled):
+        (WebCore::AVAudioSourcePreview::setVolume):
+        (WebCore::AVAudioSourcePreview::updateState):
+        (WebCore::AVAudioCaptureSource::createPreview):
+        * platform/mediastream/mac/AVMediaCaptureSource.h:
+        (WebCore::AVMediaCaptureSource::createWeakPtr):
+        * platform/mediastream/mac/AVMediaCaptureSource.mm:
+        (WebCore::AVMediaCaptureSource::AVMediaCaptureSource):
+        (WebCore::AVMediaCaptureSource::reset):
+        (WebCore::AVMediaCaptureSource::preview):
+        (WebCore::AVMediaCaptureSource::removePreview):
+        (WebCore::AVMediaSourcePreview::AVMediaSourcePreview):
+        (WebCore::AVMediaSourcePreview::~AVMediaSourcePreview):
+        (WebCore::AVMediaSourcePreview::invalidate):
+        * platform/mediastream/mac/AVVideoCaptureSource.h:
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        (WebCore::AVVideoSourcePreview::create):
+        (WebCore::AVVideoSourcePreview::AVVideoSourcePreview):
+        (WebCore::AVVideoSourcePreview::invalidate):
+        (WebCore::AVVideoSourcePreview::play):
+        (WebCore::AVVideoSourcePreview::pause):
+        (WebCore::AVVideoSourcePreview::setPaused):
+        (WebCore::AVVideoSourcePreview::setEnabled):
+        (WebCore::AVVideoCaptureSource::shutdownCaptureSession):
+        (WebCore::AVVideoCaptureSource::processNewFrame):
+        (WebCore::AVVideoCaptureSource::createPreview):
+        (WebCore::AVVideoCaptureSource::platformLayer): Deleted.
+
+        * platform/mediastream/mac/MockRealtimeVideoSourceMac.h:
+        * platform/mediastream/mac/MockRealtimeVideoSourceMac.mm:
+        (WebCore::MockRealtimeVideoSourceMac::platformLayer): Deleted.
+        (WebCore::MockRealtimeVideoSourceMac::updatePlatformLayer): Deleted.
+        * platform/mock/MockRealtimeVideoSource.cpp:
+        (WebCore::MockRealtimeVideoSource::applyFrameRate):
+        (WebCore::MockRealtimeVideoSource::applySize):
+        (WebCore::MockRealtimeVideoSource::generateFrame):
+        * platform/mock/MockRealtimeVideoSource.h:
+        (WebCore::MockRealtimeVideoSource::updatePlatformLayer): Deleted.
+
 2016-11-17  Chris Dumez  <[email protected]>
 
         Unreviewed, fix build after r208839.

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (208850 => 208851)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-11-17 18:43:40 UTC (rev 208851)
@@ -305,6 +305,7 @@
 		07C59B6917F784BA000FBCBB /* MediaSourceSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C59B6617F784BA000FBCBB /* MediaSourceSettings.h */; };
 		07C59B6E17F794F6000FBCBB /* JSMediaStreamTrackCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C59B6D17F794F6000FBCBB /* JSMediaStreamTrackCustom.cpp */; };
 		07CE77D516712A6A00C55A47 /* InbandTextTrackPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		07D1503B1DDB6965008F7598 /* RealtimeMediaSourcePreview.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07D637401BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */; };
 		07D637411BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */; };
 		07D6A4EF1BECF2D200174146 /* MockRealtimeMediaSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */; };
@@ -7262,6 +7263,7 @@
 		07C8AD111D073D630087C5CE /* AVFoundationMIMETypeCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AVFoundationMIMETypeCache.mm; sourceTree = "<group>"; };
 		07C8AD121D073D630087C5CE /* AVFoundationMIMETypeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVFoundationMIMETypeCache.h; sourceTree = "<group>"; };
 		07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateClient.h; sourceTree = "<group>"; };
+		07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeMediaSourcePreview.h; sourceTree = "<group>"; };
 		07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebAudioSourceProviderAVFObjC.h; sourceTree = "<group>"; };
 		07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebAudioSourceProviderAVFObjC.mm; sourceTree = "<group>"; };
 		07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockRealtimeMediaSource.cpp; sourceTree = "<group>"; };
@@ -15104,6 +15106,7 @@
 		07221B9217CF0AD400848E51 /* mediastream */ = {
 			isa = PBXGroup;
 			children = (
+				07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */,
 				0729B14D17CFCCA0004F1D60 /* mac */,
 				07D6A4F61BF2307D00174146 /* AudioTrackPrivateMediaStream.h */,
 				07B7116A1D899E63009F0FFB /* CaptureDevice.h */,
@@ -28149,6 +28152,7 @@
 				1411DCB1164C39A800D49BC1 /* WidthCache.h in Headers */,
 				939B02EF0EA2DBC400C54570 /* WidthIterator.h in Headers */,
 				0F15ED5C1B7EC7C500EDDFEB /* WillChangeData.h in Headers */,
+				07D1503B1DDB6965008F7598 /* RealtimeMediaSourcePreview.h in Headers */,
 				BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */,
 				7E99AF530B13846468FB01A5 /* WindowFocusAllowedIndicator.h in Headers */,
 				E1E1BF00115FF6FB006F52CA /* WindowsKeyboardCodes.h in Headers */,

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (208850 => 208851)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-11-17 18:43:40 UTC (rev 208851)
@@ -1048,8 +1048,11 @@
     // https://bugs.webkit.org/show_bug.cgi?id=124896
 
     m_mediaStreamSrcObject = mediaStream;
-    if (mediaStream)
+    if (mediaStream) {
+        m_settingMediaStreamSrcObject = true;
         setSrc(DOMURL::createPublicURL(context, *mediaStream));
+        m_settingMediaStreamSrcObject = false;
+    }
 }
 #endif
 
@@ -4983,6 +4986,11 @@
 {
     LOG(Media, "HTMLMediaElement::clearMediaPlayer(%p) - flags = %s", this, actionName(flags).utf8().data());
 
+#if ENABLE(MEDIA_STREAM)
+    if (!m_settingMediaStreamSrcObject)
+        m_mediaStreamSrcObject = nullptr;
+#endif
+
 #if ENABLE(MEDIA_SOURCE)
     detachMediaSource();
 #endif

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (208850 => 208851)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -1023,6 +1023,7 @@
 
 #if ENABLE(MEDIA_STREAM)
     RefPtr<MediaStream> m_mediaStreamSrcObject;
+    bool m_settingMediaStreamSrcObject { false };
 #endif
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h (208850 => 208851)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -186,11 +186,19 @@
     void setVideoFullscreenFrame(FloatRect) override;
 #endif
 
+    bool haveVideoLayer() const { return m_sampleBufferDisplayLayer || m_videoPreviewPlayer; }
+
     MediaPlayer* m_player { nullptr };
     WeakPtrFactory<MediaPlayerPrivateMediaStreamAVFObjC> m_weakPtrFactory;
     RefPtr<MediaStreamPrivate> m_mediaStreamPrivate;
+
+    RefPtr<RealtimeMediaSourcePreview> m_videoPreviewPlayer;
+    RefPtr<MediaStreamTrackPrivate> m_videoTrack;
+
     RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
+#if PLATFORM(MAC)
     RetainPtr<AVSampleBufferRenderSynchronizer> m_synchronizer;
+#endif
     RetainPtr<CGImageRef> m_pausedImage;
     double m_pausedTime { 0 };
     std::unique_ptr<Clock> m_clock;

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (208850 => 208851)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2016-11-17 18:43:40 UTC (rev 208851)
@@ -28,9 +28,7 @@
 
 #if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
 
-#import "AVAudioCaptureSource.h"
 #import "AVFoundationSPI.h"
-#import "AVVideoCaptureSource.h"
 #import "AudioTrackPrivateMediaStream.h"
 #import "Clock.h"
 #import "GraphicsContext.h"
@@ -66,7 +64,6 @@
 MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC(MediaPlayer* player)
     : m_player(player)
     , m_weakPtrFactory(this)
-    , m_synchronizer(adoptNS([allocAVSampleBufferRenderSynchronizerInstance() init]))
     , m_clock(Clock::create())
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
     , m_videoFullscreenLayerManager(VideoFullscreenLayerManager::create())
@@ -103,7 +100,15 @@
 
 bool MediaPlayerPrivateMediaStreamAVFObjC::isAvailable()
 {
-    return AVFoundationLibrary() && isCoreMediaFrameworkAvailable() && getAVSampleBufferDisplayLayerClass() && getAVSampleBufferRenderSynchronizerClass();
+    if (!AVFoundationLibrary() || !isCoreMediaFrameworkAvailable() || !getAVSampleBufferDisplayLayerClass())
+        return false;
+
+#if PLATFORM(MAC)
+    if (!getAVSampleBufferRenderSynchronizerClass())
+        return false;
+#endif
+
+    return true;
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
@@ -147,11 +152,17 @@
 
 void MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSampleBuffer(MediaSample& sample)
 {
-    ASSERT([m_sampleBufferDisplayLayer isReadyForMoreMediaData]);
+    if (m_sampleBufferDisplayLayer) {
+        if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
+            m_sampleQueue.append(sample);
+            requestNotificationWhenReadyForMediaData();
+            return;
+        }
 
-    [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
+        [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
+    }
+
     m_isFrameDisplayed = true;
-
     if (!m_hasEverEnqueuedVideoFrame) {
         m_hasEverEnqueuedVideoFrame = true;
         m_player->firstVideoFrameAvailable();
@@ -164,12 +175,6 @@
     if (&track != m_mediaStreamPrivate->activeVideoTrack() || !shouldEnqueueVideoSampleBuffer())
         return;
 
-    if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
-        m_sampleQueue.append(sample);
-        requestNotificationWhenReadyForMediaData();
-        return;
-    }
-
     enqueueVideoSampleBuffer(sample);
 }
 
@@ -192,37 +197,56 @@
 
 void MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer()
 {
-    if (m_sampleBufferDisplayLayer)
+    if (haveVideoLayer())
         return;
-    
-    m_sampleBufferDisplayLayer = adoptNS([allocAVSampleBufferDisplayLayerInstance() init]);
+
+    CALayer *videoLayer = nil;
+    if (m_mediaStreamPrivate->activeVideoTrack()) {
+        m_videoPreviewPlayer = m_mediaStreamPrivate->activeVideoTrack()->preview();
+        if (m_videoPreviewPlayer)
+            videoLayer = m_videoPreviewPlayer->platformLayer();
+    }
+
+    if (!videoLayer) {
+        m_sampleBufferDisplayLayer = adoptNS([allocAVSampleBufferDisplayLayerInstance() init]);
+        videoLayer = m_sampleBufferDisplayLayer.get();
 #ifndef NDEBUG
-    [m_sampleBufferDisplayLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer"];
+        [m_sampleBufferDisplayLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer"];
 #endif
-    m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
+        m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
 
-    [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
+#if PLATFORM(MAC)
+        m_synchronizer = adoptNS([allocAVSampleBufferRenderSynchronizerInstance() init]);
+        [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
+#endif
+    }
 
     renderingModeChanged();
     
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
-    m_videoFullscreenLayerManager->setVideoLayer(m_sampleBufferDisplayLayer.get(), snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
+    m_videoFullscreenLayerManager->setVideoLayer(videoLayer, snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
 #endif
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::destroyLayer()
 {
-    if (!m_sampleBufferDisplayLayer)
+    if (!haveVideoLayer())
         return;
-    
-    [m_sampleBufferDisplayLayer stopRequestingMediaData];
-    [m_sampleBufferDisplayLayer flush];
-    CMTime currentTime = CMTimebaseGetTime([m_synchronizer timebase]);
-    [m_synchronizer removeRenderer:m_sampleBufferDisplayLayer.get() atTime:currentTime withCompletionHandler:^(BOOL){
-        // No-op.
-    }];
-    m_sampleBufferDisplayLayer = nullptr;
 
+    m_videoPreviewPlayer = nullptr;
+
+    if (m_sampleBufferDisplayLayer) {
+        [m_sampleBufferDisplayLayer stopRequestingMediaData];
+        [m_sampleBufferDisplayLayer flush];
+#if PLATFORM(MAC)
+        CMTime currentTime = CMTimebaseGetTime([m_synchronizer timebase]);
+        [m_synchronizer removeRenderer:m_sampleBufferDisplayLayer.get() atTime:currentTime withCompletionHandler:^(BOOL) {
+            // No-op.
+        }];
+        m_sampleBufferDisplayLayer = nullptr;
+#endif
+    }
+
     renderingModeChanged();
     
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
@@ -282,12 +306,15 @@
 
 PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
 {
-    if (!m_sampleBufferDisplayLayer || m_displayMode == None)
+    if (!haveVideoLayer() || m_displayMode == None)
         return nullptr;
 
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
     return m_videoFullscreenLayerManager->videoInlineLayer();
 #else
+    if (m_videoPreviewPlayer)
+        return m_videoPreviewPlayer->platformLayer();
+
     return m_sampleBufferDisplayLayer.get();
 #endif
 }
@@ -294,7 +321,7 @@
 
 MediaPlayerPrivateMediaStreamAVFObjC::DisplayMode MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode() const
 {
-    if (m_ended || m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)
+    if (m_ended || m_intrinsicSize.isEmpty() || !metaDataAvailable() || !haveVideoLayer())
         return None;
 
     if (m_mediaStreamPrivate->activeVideoTrack() && !m_mediaStreamPrivate->activeVideoTrack()->enabled())
@@ -344,7 +371,21 @@
 
     m_clock->start();
     m_playing = true;
-    [m_synchronizer setRate:1];
+
+    if (m_videoPreviewPlayer)
+        m_videoPreviewPlayer->play();
+#if PLATFORM(MAC)
+    else
+        [m_synchronizer setRate:1];
+#endif
+
+    for (const auto& track : m_audioTrackMap.values()) {
+        if (!track->enabled() || !track->streamTrack()->preview())
+            continue;
+
+        track->streamTrack()->preview()->play();
+    }
+
     m_haveEverPlayed = true;
     scheduleDeferredTask([this] {
         updateDisplayMode();
@@ -361,7 +402,21 @@
 
     m_pausedTime = m_clock->currentTime();
     m_playing = false;
-    [m_synchronizer setRate:0];
+
+    if (m_videoPreviewPlayer)
+        m_videoPreviewPlayer->pause();
+#if PLATFORM(MAC)
+    else
+        [m_synchronizer setRate:0];
+#endif
+
+    for (const auto& track : m_audioTrackMap.values()) {
+        if (!track->enabled() || !track->streamTrack()->preview())
+            continue;
+
+        track->streamTrack()->preview()->pause();
+    }
+
     updateDisplayMode();
     updatePausedImage();
 }
@@ -379,7 +434,12 @@
     if (!metaDataAvailable())
         return;
 
-    // FIXME: Set volume once we actually play audio.
+    for (const auto& track : m_audioTrackMap.values()) {
+        if (!track->enabled() || !track->streamTrack()->preview())
+            continue;
+
+        track->streamTrack()->preview()->setVolume(volume);
+    }
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::setVolume(float volume)
@@ -627,9 +687,10 @@
     std::function<void(RefPtr<VideoTrackPrivateMediaStream>, int)> enableVideoTrack = [this](auto track, int index)
     {
         track->setTrackIndex(index);
-        track->setSelected(track->streamTrack() == m_mediaStreamPrivate->activeVideoTrack());
+        bool selected = track->streamTrack() == m_mediaStreamPrivate->activeVideoTrack();
+        track->setSelected(selected);
 
-        if (track->selected())
+        if (selected)
             ensureLayer();
     };
     updateTracksOfType(m_videoTrackMap, RealtimeMediaSource::Video, currentTracks, &VideoTrackPrivateMediaStream::create, m_player, &MediaPlayer::removeVideoTrack, &MediaPlayer::addVideoTrack, enableVideoTrack, (MediaStreamTrackPrivate::Observer*) this);

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp	2016-11-17 18:43:40 UTC (rev 208851)
@@ -239,14 +239,6 @@
     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())

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -93,7 +93,6 @@
     void stopProducingData();
     bool isProducingData() const;
 
-    PlatformLayer* platformLayer() const;
     RefPtr<Image> currentFrameImage();
     void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&);
 

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2016-11-17 18:43:40 UTC (rev 208851)
@@ -101,6 +101,9 @@
     // Always update the enabled state regardless of the track being ended.
     m_isEnabled = enabled;
 
+    if (m_preview)
+        m_preview->setEnabled(enabled);
+
     for (auto& observer : m_observers)
         observer->trackEnabledChanged(*this);
 }
@@ -115,6 +118,7 @@
     // trackEnded method once.
     m_isEnded = true;
 
+    m_preview = nullptr;
     m_source->requestStop(this);
 
     for (auto& observer : m_observers)
@@ -166,6 +170,15 @@
     }
 }
 
+RealtimeMediaSourcePreview* MediaStreamTrackPrivate::preview()
+{
+    if (m_preview)
+        return m_preview.get();
+
+    m_preview = m_source->preview();
+    return m_preview.get();
+}
+
 void MediaStreamTrackPrivate::applyConstraints(const MediaConstraints& constraints, RealtimeMediaSource::SuccessHandler successHandler, RealtimeMediaSource::FailureHandler failureHandler)
 {
     m_source->applyConstraints(constraints, successHandler, failureHandler);

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -96,6 +96,7 @@
     AudioSourceProvider* audioSourceProvider();
 
     void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&);
+    RealtimeMediaSourcePreview* preview();
 
 private:
     MediaStreamTrackPrivate(Ref<RealtimeMediaSource>&&, String&& id);
@@ -110,6 +111,7 @@
     Vector<Observer*> m_observers;
     Ref<RealtimeMediaSource> m_source;
     RefPtr<MediaConstraints> m_constraints;
+    RefPtr<RealtimeMediaSourcePreview> m_preview;
 
     String m_id;
     bool m_isEnabled;

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -42,6 +42,7 @@
 #include "MediaSample.h"
 #include "PlatformLayer.h"
 #include "RealtimeMediaSourceCapabilities.h"
+#include "RealtimeMediaSourcePreview.h"
 #include <wtf/RefCounted.h>
 #include <wtf/Vector.h>
 #include <wtf/WeakPtr.h>
@@ -126,9 +127,9 @@
 
     virtual AudioSourceProvider* audioSourceProvider() { return nullptr; }
 
-    virtual PlatformLayer* platformLayer() const { return nullptr; }
     virtual RefPtr<Image> currentFrameImage() { return nullptr; }
     virtual void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) { }
+    virtual RefPtr<RealtimeMediaSourcePreview> preview() { return nullptr; }
 
     void setWidth(int);
     void setHeight(int);

Copied: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h (from rev 208850, trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h) (0 => 208851)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "PlatformLayer.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class RealtimeMediaSourcePreview : public RefCounted<RealtimeMediaSourcePreview> {
+public:
+    virtual ~RealtimeMediaSourcePreview() { }
+
+    virtual void play() const = 0;
+    virtual void pause() const = 0;
+    virtual void setEnabled(bool) = 0;
+
+    virtual PlatformLayer* platformLayer() const = 0;
+    virtual void setVolume(double) const = 0;
+
+    virtual void invalidate() { m_weakPtrFactory.revokeAll(); }
+
+    WeakPtr<RealtimeMediaSourcePreview> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
+protected:
+    RealtimeMediaSourcePreview()
+        : m_weakPtrFactory(this)
+    {
+    }
+
+private:
+    WeakPtrFactory<RealtimeMediaSourcePreview> m_weakPtrFactory;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -67,6 +67,7 @@
     void shutdownCaptureSession() override;
     void updateSettings(RealtimeMediaSourceSettings&) override;
     AudioSourceProvider* audioSourceProvider() override;
+    RefPtr<AVMediaSourcePreview> createPreview() final;
 
     RetainPtr<AVCaptureConnection> m_audioConnection;
 

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm	2016-11-17 18:43:40 UTC (rev 208851)
@@ -47,15 +47,31 @@
 typedef AVCaptureDeviceInput AVCaptureDeviceInputType;
 typedef AVCaptureOutput AVCaptureOutputType;
 
+#if !PLATFORM(IOS)
+typedef AVCaptureAudioPreviewOutput AVCaptureAudioPreviewOutputType;
+#endif
+
 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
 
 SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioChannel)
 SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioDataOutput)
+SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioPreviewOutput)
 SOFT_LINK_CLASS(AVFoundation, AVCaptureConnection)
 SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice)
 SOFT_LINK_CLASS(AVFoundation, AVCaptureDeviceInput)
 SOFT_LINK_CLASS(AVFoundation, AVCaptureOutput)
 
+#define AVCaptureAudioPreviewOutput getAVCaptureAudioPreviewOutputClass()
+
+#define AVCaptureAudioChannel getAVCaptureAudioChannelClass()
+#define AVCaptureAudioDataOutput getAVCaptureAudioDataOutputClass()
+#define AVCaptureConnection getAVCaptureConnectionClass()
+#define AVCaptureDevice getAVCaptureDeviceClass()
+#define AVCaptureDeviceFormat getAVCaptureDeviceFormatClass()
+#define AVCaptureDeviceInput getAVCaptureDeviceInputClass()
+#define AVCaptureOutput getAVCaptureOutputClass()
+#define AVFrameRateRange getAVFrameRateRangeClass()
+
 SOFT_LINK_POINTER(AVFoundation, AVMediaTypeAudio, NSString *)
 
 #define AVMediaTypeAudio getAVMediaTypeAudio()
@@ -62,6 +78,79 @@
 
 namespace WebCore {
 
+#if !PLATFORM(IOS)
+class AVAudioSourcePreview: public AVMediaSourcePreview {
+public:
+    static RefPtr<AVMediaSourcePreview> create(AVCaptureSession *, AVAudioCaptureSource*);
+
+private:
+    AVAudioSourcePreview(AVCaptureSession *, AVAudioCaptureSource*);
+
+    void invalidate() final;
+
+    void play() const final;
+    void pause() const final;
+    void setVolume(double) const final;
+    void setEnabled(bool) final;
+    PlatformLayer* platformLayer() const final { return nullptr; }
+
+    void updateState() const;
+
+    RetainPtr<AVCaptureAudioPreviewOutputType> m_audioPreviewOutput;
+    mutable double m_volume { 1 };
+    mutable bool m_paused { false };
+    mutable bool m_enabled { true };
+};
+
+RefPtr<AVMediaSourcePreview> AVAudioSourcePreview::create(AVCaptureSession *session, AVAudioCaptureSource* parent)
+{
+    return adoptRef(new AVAudioSourcePreview(session, parent));
+}
+
+AVAudioSourcePreview::AVAudioSourcePreview(AVCaptureSession *session, AVAudioCaptureSource* parent)
+    : AVMediaSourcePreview(parent)
+{
+    m_audioPreviewOutput = adoptNS([allocAVCaptureAudioPreviewOutputInstance() init]);
+    setVolume(1);
+    [session addOutput:m_audioPreviewOutput.get()];
+}
+
+void AVAudioSourcePreview::invalidate()
+{
+    m_audioPreviewOutput = nullptr;
+    AVMediaSourcePreview::invalidate();
+}
+
+void AVAudioSourcePreview::play() const
+{
+    m_paused = false;
+    updateState();
+}
+
+void AVAudioSourcePreview::pause() const
+{
+    m_paused = true;
+    updateState();
+}
+
+void AVAudioSourcePreview::setEnabled(bool enabled)
+{
+    m_enabled = enabled;
+    updateState();
+}
+
+void AVAudioSourcePreview::setVolume(double volume) const
+{
+    m_volume = volume;
+    m_audioPreviewOutput.get().volume = volume;
+}
+
+void AVAudioSourcePreview::updateState() const
+{
+    m_audioPreviewOutput.get().volume = (!m_enabled || m_paused) ? 0 : m_volume;
+}
+#endif
+
 RefPtr<AVMediaCaptureSource> AVAudioCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString& id, const MediaConstraints* constraints, String& invalidConstraint)
 {
     auto source = adoptRef(new AVAudioCaptureSource(device, id));
@@ -213,6 +302,15 @@
     return m_audioSourceProvider.get();
 }
 
+RefPtr<AVMediaSourcePreview> AVAudioCaptureSource::createPreview()
+{
+#if !PLATFORM(IOS)
+    return AVAudioSourcePreview::create(session(), this);
+#else
+    return nullptr;
+#endif
+}
+    
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -32,7 +32,6 @@
 #include "RealtimeMediaSource.h"
 #include "Timer.h"
 #include <wtf/Function.h>
-#include <wtf/RetainPtr.h>
 
 OBJC_CLASS AVCaptureAudioDataOutput;
 OBJC_CLASS AVCaptureConnection;
@@ -46,6 +45,21 @@
 
 namespace WebCore {
 
+class AVMediaCaptureSource;
+
+class AVMediaSourcePreview: public RealtimeMediaSourcePreview {
+public:
+    virtual ~AVMediaSourcePreview();
+
+    void invalidate() override;
+
+protected:
+    AVMediaSourcePreview(AVMediaCaptureSource*);
+
+private:
+    WeakPtr<AVMediaCaptureSource> m_parent;
+};
+
 class AVMediaCaptureSource : public RealtimeMediaSource {
 public:
     virtual ~AVMediaCaptureSource();
@@ -62,6 +76,10 @@
     void stopProducingData() final;
     bool isProducingData() const final { return m_isRunning; }
 
+    RefPtr<RealtimeMediaSourcePreview> preview() final;
+    void removePreview(AVMediaSourcePreview*);
+    WeakPtr<AVMediaCaptureSource> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
 protected:
     AVMediaCaptureSource(AVCaptureDevice*, const AtomicString&, RealtimeMediaSource::Type);
 
@@ -81,6 +99,8 @@
     void setVideoSampleBufferDelegate(AVCaptureVideoDataOutput*);
     void setAudioSampleBufferDelegate(AVCaptureAudioDataOutput*);
 
+    virtual RefPtr<AVMediaSourcePreview> createPreview() = 0;
+
 private:
     void setupSession();
     void reset() final;
@@ -97,6 +117,8 @@
     RefPtr<RealtimeMediaSourceCapabilities> m_capabilities;
     RetainPtr<AVCaptureSession> m_session;
     RetainPtr<AVCaptureDevice> m_device;
+    Vector<WeakPtr<RealtimeMediaSourcePreview>> m_previews;
+    WeakPtrFactory<AVMediaCaptureSource> m_weakPtrFactory;
     bool m_isRunning { false};
 };
 

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm	2016-11-17 18:43:40 UTC (rev 208851)
@@ -126,6 +126,7 @@
     : RealtimeMediaSource(id, type, emptyString())
     , m_objcObserver(adoptNS([[WebCoreAVMediaCaptureSourceObserver alloc] initWithCallback:this]))
     , m_device(device)
+    , m_weakPtrFactory(this)
 {
     setName(device.localizedName);
     setPersistentID(device.uniqueID);
@@ -235,6 +236,13 @@
     m_isRunning = false;
     for (NSString *keyName in sessionKVOProperties())
         [m_session removeObserver:m_objcObserver.get() forKeyPath:keyName];
+
+    for (const auto& preview : m_previews) {
+        if (preview)
+            preview->invalidate();
+    }
+    m_previews.clear();
+
     shutdownCaptureSession();
     m_session = nullptr;
 }
@@ -266,6 +274,45 @@
     return nullptr;
 }
 
+RefPtr<RealtimeMediaSourcePreview> AVMediaCaptureSource::preview()
+{
+    RefPtr<AVMediaSourcePreview> preview = createPreview();
+    if (!preview)
+        return nullptr;
+
+    m_previews.append(preview->createWeakPtr());
+    return preview.leakRef();
+}
+
+void AVMediaCaptureSource::removePreview(AVMediaSourcePreview* preview)
+{
+    size_t index;
+    for (index = 0; index < m_previews.size(); ++index) {
+        if (m_previews[index].get() == preview)
+            break;
+    }
+
+    if (index < m_previews.size())
+        m_previews.remove(index);
+}
+
+AVMediaSourcePreview::AVMediaSourcePreview(AVMediaCaptureSource* parent)
+    : m_parent(parent->createWeakPtr())
+{
+}
+
+AVMediaSourcePreview::~AVMediaSourcePreview()
+{
+    if (m_parent)
+        m_parent->removePreview(this);
+}
+
+void AVMediaSourcePreview::invalidate()
+{
+    m_parent = nullptr;
+    RealtimeMediaSourcePreview::invalidate();
+}
+
 NSArray* sessionKVOProperties()
 {
     static NSArray* keys = [@[@"running"] retain];

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -41,6 +41,7 @@
 
 class FloatRect;
 class GraphicsContext;
+class AVVideoSourcePreview;
 
 class AVVideoCaptureSource : public AVMediaCaptureSource {
 public:
@@ -77,8 +78,8 @@
     void processNewFrame(RetainPtr<CMSampleBufferRef>);
 
     void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) final;
-    PlatformLayer* platformLayer() const final;
 
+    RefPtr<AVMediaSourcePreview> createPreview() final;
     RetainPtr<CGImageRef> currentFrameCGImage();
     RefPtr<Image> currentFrameImage() final;
 
@@ -85,8 +86,8 @@
     RetainPtr<NSString> m_pendingPreset;
     RetainPtr<CMSampleBufferRef> m_buffer;
     RetainPtr<CGImageRef> m_lastImage;
+
     Vector<Float64> m_videoFrameTimeStamps;
-    mutable RetainPtr<PlatformLayer> m_videoPreviewLayer;
     Float64 m_frameRate { 0 };
     int32_t m_width { 0 };
     int32_t m_height { 0 };

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm	2016-11-17 18:43:40 UTC (rev 208851)
@@ -38,6 +38,7 @@
 #import "NotImplemented.h"
 #import "PlatformLayer.h"
 #import "RealtimeMediaSourceCenter.h"
+#import "RealtimeMediaSourcePreview.h"
 #import "RealtimeMediaSourceSettings.h"
 #import <AVFoundation/AVFoundation.h>
 #import <objc/runtime.h>
@@ -90,6 +91,90 @@
 
 namespace WebCore {
 
+class AVVideoSourcePreview: public AVMediaSourcePreview {
+public:
+    static RefPtr<AVMediaSourcePreview> create(AVCaptureSession *, AVCaptureDeviceTypedef *, AVVideoCaptureSource*);
+
+private:
+    AVVideoSourcePreview(AVCaptureSession *, AVCaptureDeviceTypedef *, AVVideoCaptureSource*);
+
+    void invalidate() final;
+
+    void play() const final;
+    void pause() const final;
+    void setVolume(double) const final { };
+    void setEnabled(bool) final;
+    PlatformLayer* platformLayer() const final { return m_previewBackgroundLayer.get(); }
+    
+    void setPaused(bool) const;
+
+    RetainPtr<AVCaptureVideoPreviewLayerType> m_previewLayer;
+    RetainPtr<PlatformLayer> m_previewBackgroundLayer;
+    RetainPtr<AVCaptureDeviceTypedef> m_device;
+};
+
+RefPtr<AVMediaSourcePreview> AVVideoSourcePreview::create(AVCaptureSession *session, AVCaptureDeviceTypedef* device, AVVideoCaptureSource* parent)
+{
+    return adoptRef(new AVVideoSourcePreview(session, device, parent));
+}
+
+AVVideoSourcePreview::AVVideoSourcePreview(AVCaptureSession *session, AVCaptureDeviceTypedef* device, AVVideoCaptureSource* parent)
+    : AVMediaSourcePreview(parent)
+{
+    m_device = device;
+    m_previewLayer = adoptNS([allocAVCaptureVideoPreviewLayerInstance() initWithSession:session]);
+#ifndef NDEBUG
+    m_previewLayer.get().name = @"AVVideoCaptureSource preview layer";
+#endif
+
+    m_previewLayer.get().contentsGravity = kCAGravityResize;
+    m_previewLayer.get().anchorPoint = CGPointZero;
+#if !PLATFORM(IOS)
+    m_previewLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+#endif
+
+    m_previewBackgroundLayer = adoptNS([[CALayer alloc] init]);
+    m_previewBackgroundLayer.get().name = @"AVVideoSourcePreview parent layer";
+    m_previewBackgroundLayer.get().contentsGravity = kCAGravityResizeAspect;
+    m_previewBackgroundLayer.get().anchorPoint = CGPointZero;
+    m_previewBackgroundLayer.get().needsDisplayOnBoundsChange = YES;
+#if !PLATFORM(IOS)
+    m_previewBackgroundLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+#endif
+
+    [m_previewBackgroundLayer addSublayer:m_previewLayer.get()];
+}
+
+void AVVideoSourcePreview::invalidate()
+{
+    m_previewLayer = nullptr;
+    m_previewBackgroundLayer = nullptr;
+    m_device = nullptr;
+    AVMediaSourcePreview::invalidate();
+}
+
+void AVVideoSourcePreview::play() const
+{
+    setPaused(false);
+}
+
+void AVVideoSourcePreview::pause() const
+{
+    setPaused(true);
+}
+
+void AVVideoSourcePreview::setPaused(bool paused) const
+{
+    [m_device lockForConfiguration:nil];
+    m_previewLayer.get().connection.enabled = !paused;
+    [m_device unlockForConfiguration];
+}
+
+void AVVideoSourcePreview::setEnabled(bool enabled)
+{
+    m_previewLayer.get().hidden = !enabled;
+}
+
 const OSType videoCaptureFormat = kCVPixelFormatType_32BGRA;
 
 RefPtr<AVMediaCaptureSource> AVVideoCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString& id, const MediaConstraints* constraints, String& invalidConstraint)
@@ -215,7 +300,7 @@
 {
     NSString *preset = bestSessionPresetForVideoDimensions(size.width(), size.height());
     if (!preset || ![session() canSetSessionPreset:preset]) {
-        LOG(Media, "AVVideoCaptureSource::applySize%p), unable find or set preset for width: %i, height: %i", this, size.width(), size.height());
+        LOG(Media, "AVVideoCaptureSource::applySize(%p), unable find or set preset for width: %i, height: %i", this, size.width(), size.height());
         return false;
     }
 
@@ -318,7 +403,6 @@
 
 void AVVideoCaptureSource::shutdownCaptureSession()
 {
-    m_videoPreviewLayer = nullptr;
     m_buffer = nullptr;
     m_lastImage = nullptr;
     m_videoFrameTimeStamps.clear();
@@ -365,12 +449,14 @@
     ASSERT(newSampleBuffer);
 
     CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(newSampleBuffer, true);
-    for (CFIndex i = 0; i < CFArrayGetCount(attachmentsArray); ++i) {
-        CFMutableDictionaryRef attachments = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachmentsArray, i);
-        CFDictionarySetValue(attachments, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
+    if (attachmentsArray) {
+        for (CFIndex i = 0; i < CFArrayGetCount(attachmentsArray); ++i) {
+            CFMutableDictionaryRef attachments = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachmentsArray, i);
+            CFDictionarySetValue(attachments, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
+        }
     }
 
-    m_buffer = newSampleBuffer;
+    m_buffer = adoptCF(newSampleBuffer);
     m_lastImage = nullptr;
 
     bool settingsChanged = false;
@@ -450,17 +536,9 @@
     CGContextDrawImage(context.platformContext(), CGRectMake(0, 0, paintRect.width(), paintRect.height()), m_lastImage.get());
 }
 
-PlatformLayer* AVVideoCaptureSource::platformLayer() const
+RefPtr<AVMediaSourcePreview> AVVideoCaptureSource::createPreview()
 {
-    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();
+    return AVVideoSourcePreview::create(session(), device(), this);
 }
 
 NSString *AVVideoCaptureSource::bestSessionPresetForVideoDimensions(Optional<int> width, Optional<int> height) const

Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -54,8 +54,7 @@
     RetainPtr<CMSampleBufferRef> CMSampleBufferFromPixelBuffer(CVPixelBufferRef);
     RetainPtr<CVPixelBufferRef> pixelBufferFromCGImage(CGImageRef) const;
 
-    PlatformLayer* platformLayer() const override;
-    void updatePlatformLayer() const override;
+    PlatformLayer* platformLayer() const;
     void updateSampleBuffer() override;
 
     mutable RetainPtr<CGImageRef> m_previewImage;

Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm (208850 => 208851)


--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm	2016-11-17 18:43:40 UTC (rev 208851)
@@ -120,49 +120,6 @@
     return adoptCF(pixelBuffer);
 }
 
-PlatformLayer* MockRealtimeVideoSourceMac::platformLayer() const
-{
-    if (m_previewLayer)
-        return m_previewLayer.get();
-
-    m_previewLayer = adoptNS([[CALayer alloc] init]);
-    m_previewLayer.get().name = @"MockRealtimeVideoSourceMac preview layer";
-    m_previewLayer.get().contentsGravity = kCAGravityResizeAspect;
-    m_previewLayer.get().anchorPoint = CGPointZero;
-    m_previewLayer.get().needsDisplayOnBoundsChange = YES;
-#if !PLATFORM(IOS)
-    m_previewLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
-#endif
-
-    updatePlatformLayer();
-
-    return m_previewLayer.get();
-}
-
-void MockRealtimeVideoSourceMac::updatePlatformLayer() const
-{
-    if (!m_previewLayer)
-        return;
-
-    [CATransaction begin];
-    [CATransaction setAnimationDuration:0];
-    [CATransaction setDisableActions:YES];
-
-    do {
-        RefPtr<Image> image = imageBuffer()->copyImage();
-        if (!image)
-            break;
-
-        m_previewImage = image->nativeImage();
-        if (!m_previewImage)
-            break;
-
-        m_previewLayer.get().contents = (NSObject*)(m_previewImage.get());
-    } while (0);
-
-    [CATransaction commit];
-}
-
 void MockRealtimeVideoSourceMac::updateSampleBuffer()
 {
     auto pixelBuffer = pixelBufferFromCGImage(imageBuffer()->copyImage()->nativeImage().get());

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (208850 => 208851)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2016-11-17 18:43:40 UTC (rev 208851)
@@ -138,7 +138,6 @@
     if (m_timer.isActive())
         m_timer.startRepeating(std::chrono::milliseconds(lround(1000 / rate)));
 
-    updatePlatformLayer();
     updateSampleBuffer();
     return true;
 }
@@ -168,7 +167,6 @@
     m_statsFont.update(nullptr);
 
     m_imageBuffer = nullptr;
-    updatePlatformLayer();
 
     return true;
 }
@@ -339,7 +337,6 @@
     drawAnimation(context);
     drawBoxes(context);
 
-    updatePlatformLayer();
     updateSampleBuffer();
 }
 

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (208850 => 208851)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2016-11-17 18:43:40 UTC (rev 208851)
@@ -53,7 +53,6 @@
 
 protected:
     MockRealtimeVideoSource(const String&);
-    virtual void updatePlatformLayer() const { }
     virtual void updateSampleBuffer() { }
 
     ImageBuffer* imageBuffer() const;
@@ -77,7 +76,6 @@
     bool applyFacingMode(RealtimeMediaSourceSettings::VideoFacingMode) override { return true; }
     bool applyAspectRatio(double) override { return true; }
 
-    PlatformLayer* platformLayer() const override { return nullptr; }
     RefPtr<Image> currentFrameImage() override;
     void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) override;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to