Title: [254564] trunk/Source/WebCore
Revision
254564
Author
you...@apple.com
Date
2020-01-15 06:24:12 -0800 (Wed, 15 Jan 2020)

Log Message

Introduce an abstract SampleBufferDisplayLayer
https://bugs.webkit.org/show_bug.cgi?id=206066

Reviewed by Eric Carlson.

Move use of display layers in MediaPlayerPrivateMediaStreamAVFObjC to a new class LocalSampleBufferDisplayLayer
that implements an interface named SampleBufferDisplayLayer.
A future patch will implement this interface by IPCing to GPUProcess.
We move both layers and handling of the sample queue to LocalSampleBufferDisplayLayer.

Contrary to previously, we do not call again enqueueVideoSample in case we enqueued a sample for later use in the display layer.
Instead, we directly render it, which should not change much since this is a realtime track and in the future the buffer will be in GPUProcess anyway.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/avfoundation/SampleBufferDisplayLayer.h: Added.
(WebCore::SampleBufferDisplayLayer::SampleBufferDisplayLayer):
* platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h: Added.
* platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm: Added.
(-[WebAVSampleBufferStatusChangeListener initWithParent:]):
(-[WebAVSampleBufferStatusChangeListener dealloc]):
(-[WebAVSampleBufferStatusChangeListener invalidate]):
(-[WebAVSampleBufferStatusChangeListener beginObservingLayers]):
(-[WebAVSampleBufferStatusChangeListener stopObservingLayers]):
(-[WebAVSampleBufferStatusChangeListener observeValueForKeyPath:ofObject:change:context:]):
(WebCore::runWithoutAnimations):
(WebCore::LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer):
(WebCore::LocalSampleBufferDisplayLayer::~LocalSampleBufferDisplayLayer):
(WebCore::LocalSampleBufferDisplayLayer::layerStatusDidChange):
(WebCore::LocalSampleBufferDisplayLayer::layerErrorDidChange):
(WebCore::LocalSampleBufferDisplayLayer::rootLayerBoundsDidChange):
(WebCore::LocalSampleBufferDisplayLayer::displayLayer):
(WebCore::LocalSampleBufferDisplayLayer::rootLayer):
(WebCore::LocalSampleBufferDisplayLayer::didFail const):
(WebCore::LocalSampleBufferDisplayLayer::updateDisplayMode):
(WebCore::LocalSampleBufferDisplayLayer::bounds const):
(WebCore::LocalSampleBufferDisplayLayer::updateAffineTransform):
(WebCore::LocalSampleBufferDisplayLayer::updateBoundsAndPosition):
(WebCore::LocalSampleBufferDisplayLayer::ensureLayers):
(WebCore::LocalSampleBufferDisplayLayer::flush):
(WebCore::LocalSampleBufferDisplayLayer::flushAndRemoveImage):
(WebCore::LocalSampleBufferDisplayLayer::enqueueSample):
(WebCore::LocalSampleBufferDisplayLayer::removeOldSamplesFromPendingQueue):
(WebCore::LocalSampleBufferDisplayLayer::addSampleToPendingQueue):
(WebCore::LocalSampleBufferDisplayLayer::clearEnqueuedSamples):
(WebCore::LocalSampleBufferDisplayLayer::requestNotificationWhenReadyForVideoData):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueCorrectedVideoSample):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerStatusDidChange):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::applicationDidBecomeActive):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::flushRenderers):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::destroyLayers):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer const):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::displayLayer):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayMode):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::checkSelectedVideoTrack):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setBufferingPolicy):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayLayer):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerBoundsDidChange):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (254563 => 254564)


--- trunk/Source/WebCore/ChangeLog	2020-01-15 11:45:50 UTC (rev 254563)
+++ trunk/Source/WebCore/ChangeLog	2020-01-15 14:24:12 UTC (rev 254564)
@@ -1,5 +1,71 @@
 2020-01-15  youenn fablet  <you...@apple.com>
 
+        Introduce an abstract SampleBufferDisplayLayer
+        https://bugs.webkit.org/show_bug.cgi?id=206066
+
+        Reviewed by Eric Carlson.
+
+        Move use of display layers in MediaPlayerPrivateMediaStreamAVFObjC to a new class LocalSampleBufferDisplayLayer
+        that implements an interface named SampleBufferDisplayLayer.
+        A future patch will implement this interface by IPCing to GPUProcess.
+        We move both layers and handling of the sample queue to LocalSampleBufferDisplayLayer.
+
+        Contrary to previously, we do not call again enqueueVideoSample in case we enqueued a sample for later use in the display layer.
+        Instead, we directly render it, which should not change much since this is a realtime track and in the future the buffer will be in GPUProcess anyway.
+
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/avfoundation/SampleBufferDisplayLayer.h: Added.
+        (WebCore::SampleBufferDisplayLayer::SampleBufferDisplayLayer):
+        * platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h: Added.
+        * platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm: Added.
+        (-[WebAVSampleBufferStatusChangeListener initWithParent:]):
+        (-[WebAVSampleBufferStatusChangeListener dealloc]):
+        (-[WebAVSampleBufferStatusChangeListener invalidate]):
+        (-[WebAVSampleBufferStatusChangeListener beginObservingLayers]):
+        (-[WebAVSampleBufferStatusChangeListener stopObservingLayers]):
+        (-[WebAVSampleBufferStatusChangeListener observeValueForKeyPath:ofObject:change:context:]):
+        (WebCore::runWithoutAnimations):
+        (WebCore::LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer):
+        (WebCore::LocalSampleBufferDisplayLayer::~LocalSampleBufferDisplayLayer):
+        (WebCore::LocalSampleBufferDisplayLayer::layerStatusDidChange):
+        (WebCore::LocalSampleBufferDisplayLayer::layerErrorDidChange):
+        (WebCore::LocalSampleBufferDisplayLayer::rootLayerBoundsDidChange):
+        (WebCore::LocalSampleBufferDisplayLayer::displayLayer):
+        (WebCore::LocalSampleBufferDisplayLayer::rootLayer):
+        (WebCore::LocalSampleBufferDisplayLayer::didFail const):
+        (WebCore::LocalSampleBufferDisplayLayer::updateDisplayMode):
+        (WebCore::LocalSampleBufferDisplayLayer::bounds const):
+        (WebCore::LocalSampleBufferDisplayLayer::updateAffineTransform):
+        (WebCore::LocalSampleBufferDisplayLayer::updateBoundsAndPosition):
+        (WebCore::LocalSampleBufferDisplayLayer::ensureLayers):
+        (WebCore::LocalSampleBufferDisplayLayer::flush):
+        (WebCore::LocalSampleBufferDisplayLayer::flushAndRemoveImage):
+        (WebCore::LocalSampleBufferDisplayLayer::enqueueSample):
+        (WebCore::LocalSampleBufferDisplayLayer::removeOldSamplesFromPendingQueue):
+        (WebCore::LocalSampleBufferDisplayLayer::addSampleToPendingQueue):
+        (WebCore::LocalSampleBufferDisplayLayer::clearEnqueuedSamples):
+        (WebCore::LocalSampleBufferDisplayLayer::requestNotificationWhenReadyForVideoData):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueCorrectedVideoSample):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerStatusDidChange):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::applicationDidBecomeActive):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::flushRenderers):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::destroyLayers):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer const):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::displayLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayMode):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::checkSelectedVideoTrack):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setBufferingPolicy):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayLayer):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerBoundsDidChange):
+
+2020-01-15  youenn fablet  <you...@apple.com>
+
         Add support for MediaStream audio track rendering in GPUProcess
         https://bugs.webkit.org/show_bug.cgi?id=206175
 

Modified: trunk/Source/WebCore/SourcesCocoa.txt (254563 => 254564)


--- trunk/Source/WebCore/SourcesCocoa.txt	2020-01-15 11:45:50 UTC (rev 254563)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2020-01-15 14:24:12 UTC (rev 254564)
@@ -253,6 +253,7 @@
 platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm @no-unify
 platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.mm @no-unify
 platform/graphics/avfoundation/objc/InbandTextTrackPrivateLegacyAVFObjC.mm @no-unify
+platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm @no-unify
 platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm @no-unify
 platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm @no-unify
 platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm @no-unify

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (254563 => 254564)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-01-15 11:45:50 UTC (rev 254563)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-01-15 14:24:12 UTC (rev 254564)
@@ -1067,6 +1067,7 @@
 		413C2C341BC29A8F0075204C /* JSDOMConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 413C2C331BC29A7B0075204C /* JSDOMConstructor.h */; };
 		413CCD4A20DE034F0065A21A /* MockMediaDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 413CCD4820DE013C0065A21A /* MockMediaDevice.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		413E00791DB0E4F2002341D2 /* MemoryRelease.h in Headers */ = {isa = PBXBuildFile; fileRef = 413E00781DB0E4DE002341D2 /* MemoryRelease.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		414598C223C8D177002B9CC8 /* LocalSampleBufferDisplayLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */; };
 		414B82051D6DF0E50077EBE3 /* StructuredClone.h in Headers */ = {isa = PBXBuildFile; fileRef = 414B82031D6DF0D90077EBE3 /* StructuredClone.h */; };
 		414DEDE71F9FE91E0047C40D /* EmptyFrameLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 414DEDE51F9FE9150047C40D /* EmptyFrameLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		415071581685067300C3C7B3 /* SelectorFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 415071561685067300C3C7B3 /* SelectorFilter.h */; };
@@ -1153,6 +1154,8 @@
 		41F062140F5F192600A07EAC /* InspectorDatabaseResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 41F062120F5F192600A07EAC /* InspectorDatabaseResource.h */; };
 		41F1D21F0EF35C2A00DA8753 /* ScriptCachedFrameData.h in Headers */ = {isa = PBXBuildFile; fileRef = 41F1D21D0EF35C2A00DA8753 /* ScriptCachedFrameData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		41FABD2D1F4DFE4A006A6C97 /* DOMCacheEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FABD2B1F4DFE42006A6C97 /* DOMCacheEngine.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		41FCD6B923CE015500C62567 /* SampleBufferDisplayLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 414598BE23C8AAB8002B9CC8 /* SampleBufferDisplayLayer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		41FCD6BB23CE027700C62567 /* LocalSampleBufferDisplayLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 414598C023C8AD78002B9CC8 /* LocalSampleBufferDisplayLayer.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		427DA71D13735DFA007C57FB /* JSServiceWorkerInternals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 427DA71B13735DFA007C57FB /* JSServiceWorkerInternals.cpp */; };
 		427DA71E13735DFA007C57FB /* JSServiceWorkerInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 427DA71C13735DFA007C57FB /* JSServiceWorkerInternals.h */; };
 		43107BE218CC19DE00CC18E8 /* SelectorPseudoTypeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 43107BE118CC19DE00CC18E8 /* SelectorPseudoTypeMap.h */; };
@@ -7346,6 +7349,9 @@
 		413E00781DB0E4DE002341D2 /* MemoryRelease.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryRelease.h; sourceTree = "<group>"; };
 		413E007B1DB0E707002341D2 /* MemoryReleaseCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryReleaseCocoa.mm; sourceTree = "<group>"; };
 		413FC4CD1FD1DD8C00541C4B /* ServiceWorkerClientQueryOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerClientQueryOptions.h; sourceTree = "<group>"; };
+		414598BE23C8AAB8002B9CC8 /* SampleBufferDisplayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleBufferDisplayLayer.h; sourceTree = "<group>"; };
+		414598C023C8AD78002B9CC8 /* LocalSampleBufferDisplayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalSampleBufferDisplayLayer.h; sourceTree = "<group>"; };
+		414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalSampleBufferDisplayLayer.mm; sourceTree = "<group>"; };
 		4147E2B21C88337F00A7E715 /* FetchBodyOwner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchBodyOwner.h; sourceTree = "<group>"; };
 		4147E2B31C89912600A7E715 /* FetchBodyOwner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchBodyOwner.cpp; sourceTree = "<group>"; };
 		4147E2B41C89912600A7E715 /* FetchLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchLoader.cpp; sourceTree = "<group>"; };
@@ -16325,6 +16331,7 @@
 				076F0D0A12B8192700C26AA4 /* MediaPlayerPrivateAVFoundation.h */,
 				CDBEAEAB19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h */,
 				CDBEAEAA19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm */,
+				414598BE23C8AAB8002B9CC8 /* SampleBufferDisplayLayer.h */,
 				CD336F6317FA0A4D00DDDCD0 /* VideoTrackPrivateAVF.h */,
 				0709D7901AE5557E004E42F8 /* WebMediaSessionManagerMac.cpp */,
 				0709D7911AE5557E004E42F8 /* WebMediaSessionManagerMac.h */,
@@ -26748,6 +26755,8 @@
 				07AA6B6A166D019500D45671 /* InbandTextTrackPrivateAVFObjC.mm */,
 				07367DDD172CA67F00D861B9 /* InbandTextTrackPrivateLegacyAVFObjC.h */,
 				07367DDE172CA67F00D861B9 /* InbandTextTrackPrivateLegacyAVFObjC.mm */,
+				414598C023C8AD78002B9CC8 /* LocalSampleBufferDisplayLayer.h */,
+				414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */,
 				078E43DB1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.h */,
 				078E43DC1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.mm */,
 				DF9AFD7013FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.h */,
@@ -31397,6 +31406,7 @@
 				7633A72613D8B33A008501B6 /* LocaleToScriptMapping.h in Headers */,
 				A516E8B7136E04DB0076C3C0 /* LocalizedDateCache.h in Headers */,
 				935207BE09BD410A00F2038D /* LocalizedStrings.h in Headers */,
+				41FCD6BB23CE027700C62567 /* LocalSampleBufferDisplayLayer.h in Headers */,
 				BCE1C41B0D982980003B02F2 /* Location.h in Headers */,
 				6B4D412D23983F88002494C2 /* LoggedInStatus.h in Headers */,
 				A8239E0109B3CF8A00B60641 /* Logging.h in Headers */,
@@ -32181,6 +32191,7 @@
 				293EAE1F1356B2FE0067ACF9 /* RuntimeApplicationChecks.h in Headers */,
 				7C52229E1E1DAE47002CB8F7 /* RuntimeEnabledFeatures.h in Headers */,
 				CE7A6C28208537E200FA2B46 /* SameSiteInfo.h in Headers */,
+				41FCD6B923CE015500C62567 /* SampleBufferDisplayLayer.h in Headers */,
 				CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */,
 				49E911CB0EF86D47009D0CAF /* ScaleTransformOperation.h in Headers */,
 				5DFE8F570D16477C0076E937 /* ScheduledAction.h in Headers */,
@@ -33650,6 +33661,7 @@
 				41D28D0D2139E05800F4206F /* LibWebRTCStatsCollector.cpp in Sources */,
 				4186BD3E213EE3400001826F /* LibWebRTCUtils.cpp in Sources */,
 				9759E93E14EF1CF80026A2DD /* LoadableTextTrack.cpp in Sources */,
+				414598C223C8D177002B9CC8 /* LocalSampleBufferDisplayLayer.mm in Sources */,
 				FABE72FE1059C21100D999DD /* MathMLNames.cpp in Sources */,
 				2D9BF7051DBFBB24007A7D99 /* MediaEncryptedEvent.cpp in Sources */,
 				2D9BF7471DBFDC49007A7D99 /* MediaKeyMessageEvent.cpp in Sources */,

Added: trunk/Source/WebCore/platform/graphics/avfoundation/SampleBufferDisplayLayer.h (0 => 254564)


--- trunk/Source/WebCore/platform/graphics/avfoundation/SampleBufferDisplayLayer.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/SampleBufferDisplayLayer.h	2020-01-15 14:24:12 UTC (rev 254564)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include "PlatformLayer.h"
+#include <wtf/WeakPtr.h>
+
+namespace WTF {
+class MediaTime;
+}
+
+namespace WebCore {
+class IntSize;
+class MediaSample;
+
+class SampleBufferDisplayLayer {
+public:
+    class Client : public CanMakeWeakPtr<Client> {
+    public:
+        virtual ~Client() = default;
+        virtual void sampleBufferDisplayLayerStatusDidChange(SampleBufferDisplayLayer&) = 0;
+        virtual void sampleBufferDisplayLayerBoundsDidChange(SampleBufferDisplayLayer&) = 0;
+        virtual WTF::MediaTime streamTime() const = 0;
+    };
+
+    explicit SampleBufferDisplayLayer(Client&);
+    virtual ~SampleBufferDisplayLayer() = default;
+
+    virtual bool didFail() const = 0;
+
+    virtual void updateDisplayMode(bool hideDisplayLayer, bool hideRootLayer) = 0;
+
+    virtual CGRect bounds() const = 0;
+    virtual void updateAffineTransform(CGAffineTransform) = 0;
+    virtual void updateBoundsAndPosition(CGRect, CGPoint) = 0;
+
+    virtual void flush() = 0;
+    virtual void flushAndRemoveImage() = 0;
+
+    virtual void enqueueSample(MediaSample&) = 0;
+    virtual void clearEnqueuedSamples() = 0;
+
+    virtual PlatformLayer* rootLayer() = 0;
+
+protected:
+    WeakPtr<Client> m_client;
+};
+
+inline SampleBufferDisplayLayer::SampleBufferDisplayLayer(Client& client)
+    : m_client(makeWeakPtr(client))
+{
+}
+
+}

Added: trunk/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h (0 => 254564)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h	2020-01-15 14:24:12 UTC (rev 254564)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
+
+#include "SampleBufferDisplayLayer.h"
+#include <wtf/Deque.h>
+#include <wtf/Forward.h>
+#include <wtf/RetainPtr.h>
+
+OBJC_CLASS AVSampleBufferDisplayLayer;
+OBJC_CLASS WebAVSampleBufferStatusChangeListener;
+
+namespace WebCore {
+
+class WEBCORE_EXPORT LocalSampleBufferDisplayLayer final : public SampleBufferDisplayLayer, public CanMakeWeakPtr<LocalSampleBufferDisplayLayer> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static std::unique_ptr<SampleBufferDisplayLayer> create(Client&, bool hideRootLayer, IntSize);
+
+    LocalSampleBufferDisplayLayer(RetainPtr<AVSampleBufferDisplayLayer>&&, Client&, bool hideRootLayer, IntSize);
+    ~LocalSampleBufferDisplayLayer();
+
+    // API used by WebAVSampleBufferStatusChangeListener
+    void layerStatusDidChange();
+    void layerErrorDidChange();
+    void rootLayerBoundsDidChange();
+
+    PlatformLayer* displayLayer();
+
+    PlatformLayer* rootLayer() final;
+
+private:
+    bool didFail() const final;
+
+    void updateDisplayMode(bool hideDisplayLayer, bool hideRootLayer) final;
+
+    CGRect bounds() const final;
+    void updateAffineTransform(CGAffineTransform)  final;
+    void updateBoundsAndPosition(CGRect, CGPoint) final;
+
+    void flush() final;
+    void flushAndRemoveImage() final;
+
+    void enqueueSample(MediaSample&) final;
+    void clearEnqueuedSamples() final;
+
+    void ensureLayers();
+
+    void removeOldSamplesFromPendingQueue();
+    void addSampleToPendingQueue(MediaSample&);
+    void requestNotificationWhenReadyForVideoData();
+
+private:
+    RetainPtr<WebAVSampleBufferStatusChangeListener> m_statusChangeListener;
+    RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
+    RetainPtr<PlatformLayer> m_rootLayer;
+
+    using PendingSampleQueue = Deque<Ref<MediaSample>>;
+    PendingSampleQueue m_pendingVideoSampleQueue;
+};
+    
+}
+
+#endif // ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)

Added: trunk/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm (0 => 254564)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm	2020-01-15 14:24:12 UTC (rev 254564)
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#import "config.h"
+#import "LocalSampleBufferDisplayLayer.h"
+
+#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
+
+#import "Color.h"
+#import "IntSize.h"
+#import "MediaSample.h"
+
+#import <AVFoundation/AVSampleBufferDisplayLayer.h>
+#import <QuartzCore/CALayer.h>
+#import <QuartzCore/CATransaction.h>
+
+#import <wtf/MainThread.h>
+
+#import <pal/cocoa/AVFoundationSoftLink.h>
+
+using namespace WebCore;
+
+@interface WebAVSampleBufferStatusChangeListener : NSObject {
+    LocalSampleBufferDisplayLayer* _parent;
+}
+
+- (id)initWithParent:(LocalSampleBufferDisplayLayer*)callback;
+- (void)invalidate;
+- (void)beginObservingLayers;
+- (void)stopObservingLayers;
+@end
+
+@implementation WebAVSampleBufferStatusChangeListener
+
+- (id)initWithParent:(LocalSampleBufferDisplayLayer*)parent
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _parent = parent;
+
+    return self;
+}
+
+- (void)dealloc
+{
+    [self invalidate];
+    [super dealloc];
+}
+
+- (void)invalidate
+{
+    [self stopObservingLayers];
+    _parent = nullptr;
+}
+
+- (void)beginObservingLayers
+{
+    ASSERT(_parent);
+    ASSERT(_parent->displayLayer());
+    ASSERT(_parent->rootLayer());
+
+    [_parent->displayLayer() addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
+    [_parent->displayLayer() addObserver:self forKeyPath:@"error" options:NSKeyValueObservingOptionNew context:nil];
+    [_parent->rootLayer() addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:nil];
+}
+
+- (void)stopObservingLayers
+{
+    if (!_parent)
+        return;
+
+    if (_parent->displayLayer()) {
+        [_parent->displayLayer() removeObserver:self forKeyPath:@"status"];
+        [_parent->displayLayer() removeObserver:self forKeyPath:@"error"];
+    }
+    if (_parent->rootLayer())
+        [_parent->rootLayer() removeObserver:self forKeyPath:@"bounds"];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(keyPath);
+    ASSERT(_parent);
+
+    if (!_parent)
+        return;
+
+    if ([object isKindOfClass:PAL::getAVSampleBufferDisplayLayerClass()]) {
+        ASSERT(object == _parent->displayLayer());
+
+        if ([keyPath isEqualToString:@"status"]) {
+            callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self)] {
+                if (!protectedSelf->_parent)
+                    return;
+
+                protectedSelf->_parent->layerStatusDidChange();
+            });
+            return;
+        }
+
+        if ([keyPath isEqualToString:@"error"]) {
+            callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self)] {
+                if (!protectedSelf->_parent)
+                    return;
+
+                protectedSelf->_parent->layerErrorDidChange();
+            });
+            return;
+        }
+    }
+
+    if ([[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
+        return;
+
+    if ((CALayer *)object == _parent->rootLayer()) {
+        if ([keyPath isEqualToString:@"bounds"]) {
+            if (!_parent)
+                return;
+
+            if (isMainThread()) {
+                _parent->rootLayerBoundsDidChange();
+                return;
+            }
+
+            callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self)] {
+                if (!protectedSelf->_parent)
+                    return;
+
+                protectedSelf->_parent->rootLayerBoundsDidChange();
+            });
+        }
+    }
+
+}
+@end
+
+namespace WebCore {
+
+static void runWithoutAnimations(const WTF::Function<void()>& function)
+{
+    [CATransaction begin];
+    [CATransaction setAnimationDuration:0];
+    [CATransaction setDisableActions:YES];
+    function();
+    [CATransaction commit];
+}
+
+std::unique_ptr<SampleBufferDisplayLayer> LocalSampleBufferDisplayLayer::create(Client& client, bool hideRootLayer, IntSize size)
+{
+    auto sampleBufferDisplayLayer = adoptNS([PAL::allocAVSampleBufferDisplayLayerInstance() init]);
+    if (!sampleBufferDisplayLayer)
+        return nullptr;
+
+    return makeUnique<LocalSampleBufferDisplayLayer>(WTFMove(sampleBufferDisplayLayer), client, hideRootLayer, size);
+}
+
+LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer(RetainPtr<AVSampleBufferDisplayLayer>&& sampleBufferDisplayLayer, Client& client, bool hideRootLayer, IntSize size)
+    : SampleBufferDisplayLayer(client)
+    , m_statusChangeListener(adoptNS([[WebAVSampleBufferStatusChangeListener alloc] initWithParent:this]))
+    , m_sampleBufferDisplayLayer(WTFMove(sampleBufferDisplayLayer))
+{
+    m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
+    m_sampleBufferDisplayLayer.get().anchorPoint = { .5, .5 };
+    m_sampleBufferDisplayLayer.get().needsDisplayOnBoundsChange = YES;
+    m_sampleBufferDisplayLayer.get().videoGravity = AVLayerVideoGravityResizeAspectFill;
+
+    m_rootLayer = adoptNS([[CALayer alloc] init]);
+    m_rootLayer.get().hidden = hideRootLayer;
+
+    m_rootLayer.get().backgroundColor = cachedCGColor(Color::black);
+    m_rootLayer.get().needsDisplayOnBoundsChange = YES;
+
+    m_rootLayer.get().bounds = CGRectMake(0, 0, size.width(), size.height());
+
+    [m_statusChangeListener beginObservingLayers];
+
+    [m_rootLayer addSublayer:m_sampleBufferDisplayLayer.get()];
+
+#ifndef NDEBUG
+    [m_sampleBufferDisplayLayer setName:@"LocalSampleBufferDisplayLayer AVSampleBufferDisplayLayer"];
+    [m_rootLayer setName:@"LocalSampleBufferDisplayLayer AVSampleBufferDisplayLayer parent"];
+#endif
+}
+
+LocalSampleBufferDisplayLayer::~LocalSampleBufferDisplayLayer()
+{
+    [m_statusChangeListener stopObservingLayers];
+
+    m_pendingVideoSampleQueue.clear();
+
+    [m_sampleBufferDisplayLayer stopRequestingMediaData];
+    [m_sampleBufferDisplayLayer flush];
+    m_sampleBufferDisplayLayer = nullptr;
+
+    m_rootLayer = nullptr;
+}
+
+void LocalSampleBufferDisplayLayer::layerStatusDidChange()
+{
+    ASSERT(isMainThread());
+    if (m_sampleBufferDisplayLayer.get().status != AVQueuedSampleBufferRenderingStatusRendering)
+        return;
+    if (!m_client)
+        return;
+    m_client->sampleBufferDisplayLayerStatusDidChange(*this);
+}
+
+void LocalSampleBufferDisplayLayer::layerErrorDidChange()
+{
+    ASSERT(isMainThread());
+    // FIXME: Log error.
+}
+
+void LocalSampleBufferDisplayLayer::rootLayerBoundsDidChange()
+{
+    ASSERT(isMainThread());
+    if (!m_client)
+        return;
+    m_client->sampleBufferDisplayLayerBoundsDidChange(*this);
+}
+
+PlatformLayer* LocalSampleBufferDisplayLayer::displayLayer()
+{
+    return m_sampleBufferDisplayLayer.get();
+}
+
+PlatformLayer* LocalSampleBufferDisplayLayer::rootLayer()
+{
+    return m_rootLayer.get();
+}
+
+bool LocalSampleBufferDisplayLayer::didFail() const
+{
+    return [m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed;
+}
+
+void LocalSampleBufferDisplayLayer::updateDisplayMode(bool hideDisplayLayer, bool hideRootLayer)
+{
+    if (m_rootLayer.get().hidden == hideRootLayer && m_sampleBufferDisplayLayer.get().hidden == hideDisplayLayer)
+        return;
+
+    runWithoutAnimations([&] {
+        m_sampleBufferDisplayLayer.get().hidden = hideDisplayLayer;
+        m_rootLayer.get().hidden = hideRootLayer;
+    });
+}
+
+CGRect LocalSampleBufferDisplayLayer::bounds() const
+{
+    return m_rootLayer.get().bounds;
+}
+
+void LocalSampleBufferDisplayLayer::updateAffineTransform(CGAffineTransform transform)
+{
+    runWithoutAnimations([&] {
+        m_sampleBufferDisplayLayer.get().affineTransform = transform;
+    });
+}
+
+void LocalSampleBufferDisplayLayer::updateBoundsAndPosition(CGRect videoBounds, CGPoint position)
+{
+    runWithoutAnimations([&] {
+        m_sampleBufferDisplayLayer.get().bounds = videoBounds;
+        m_sampleBufferDisplayLayer.get().position = position;
+    });
+}
+
+void LocalSampleBufferDisplayLayer::flush()
+{
+    [m_sampleBufferDisplayLayer flush];
+}
+
+void LocalSampleBufferDisplayLayer::flushAndRemoveImage()
+{
+    [m_sampleBufferDisplayLayer flushAndRemoveImage];
+}
+
+void LocalSampleBufferDisplayLayer::enqueueSample(MediaSample& sample)
+{
+    if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
+        addSampleToPendingQueue(sample);
+        requestNotificationWhenReadyForVideoData();
+        return;
+    }
+
+    [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
+}
+
+void LocalSampleBufferDisplayLayer::removeOldSamplesFromPendingQueue()
+{
+    if (m_pendingVideoSampleQueue.isEmpty() || !m_client)
+        return;
+
+    auto decodeTime = m_pendingVideoSampleQueue.first()->decodeTime();
+    if (!decodeTime.isValid() || decodeTime < MediaTime::zeroTime()) {
+        while (m_pendingVideoSampleQueue.size() > 5)
+            m_pendingVideoSampleQueue.removeFirst();
+
+        return;
+    }
+
+    MediaTime now = m_client->streamTime();
+    while (!m_pendingVideoSampleQueue.isEmpty()) {
+        if (m_pendingVideoSampleQueue.first()->decodeTime() > now)
+            break;
+        m_pendingVideoSampleQueue.removeFirst();
+    }
+}
+
+void LocalSampleBufferDisplayLayer::addSampleToPendingQueue(MediaSample& sample)
+{
+    removeOldSamplesFromPendingQueue();
+    m_pendingVideoSampleQueue.append(sample);
+}
+
+void LocalSampleBufferDisplayLayer::clearEnqueuedSamples()
+{
+    m_pendingVideoSampleQueue.clear();
+}
+
+void LocalSampleBufferDisplayLayer::requestNotificationWhenReadyForVideoData()
+{
+    auto weakThis = makeWeakPtr(*this);
+    [m_sampleBufferDisplayLayer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^{
+        if (!weakThis)
+            return;
+
+        [m_sampleBufferDisplayLayer stopRequestingMediaData];
+
+        while (!m_pendingVideoSampleQueue.isEmpty()) {
+            if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
+                requestNotificationWhenReadyForVideoData();
+                return;
+            }
+
+            auto sample = m_pendingVideoSampleQueue.takeFirst();
+            enqueueSample(sample.get());
+        }
+    }];
+}
+
+}
+
+#endif

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h	2020-01-15 11:45:50 UTC (rev 254563)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h	2020-01-15 14:24:12 UTC (rev 254564)
@@ -30,10 +30,10 @@
 #include "MediaPlayerPrivate.h"
 #include "MediaSample.h"
 #include "MediaStreamPrivate.h"
+#include "SampleBufferDisplayLayer.h"
 #include <wtf/Deque.h>
 #include <wtf/Forward.h>
 #include <wtf/LoggerHelper.h>
-#include <wtf/WeakPtr.h>
 
 OBJC_CLASS AVSampleBufferDisplayLayer;
 OBJC_CLASS WebAVSampleBufferStatusChangeListener;
@@ -51,7 +51,7 @@
 class VideoFullscreenLayerManagerObjC;
 class VideoTrackPrivateMediaStream;
 
-class MediaPlayerPrivateMediaStreamAVFObjC final : public CanMakeWeakPtr<MediaPlayerPrivateMediaStreamAVFObjC>, public MediaPlayerPrivateInterface, private MediaStreamPrivate::Observer, private MediaStreamTrackPrivate::Observer
+class MediaPlayerPrivateMediaStreamAVFObjC final : public MediaPlayerPrivateInterface, private MediaStreamPrivate::Observer, private MediaStreamTrackPrivate::Observer, public SampleBufferDisplayLayer::Client
 #if !RELEASE_LOG_DISABLED
     , private LoggerHelper
 #endif
@@ -75,13 +75,6 @@
     void ensureLayers();
     void destroyLayers();
 
-    void layerStatusDidChange(AVSampleBufferDisplayLayer*);
-    void layerErrorDidChange(AVSampleBufferDisplayLayer*);
-    void backgroundLayerBoundsChanged();
-
-    PlatformLayer* displayLayer();
-    PlatformLayer* backgroundLayer();
-
 #if !RELEASE_LOG_DISABLED
     const Logger& logger() const final { return m_logger.get(); }
     const char* logClassName() const override { return "MediaPlayerPrivateMediaStreamAVFObjC"; }
@@ -137,10 +130,6 @@
 
     void flushRenderers();
 
-    using PendingSampleQueue = Deque<Ref<MediaSample>>;
-    void addSampleToPendingQueue(PendingSampleQueue&, MediaSample&);
-    void removeOldSamplesFromPendingQueue(PendingSampleQueue&);
-
     MediaTime calculateTimelineOffset(const MediaSample&, double);
     
     void enqueueVideoSample(MediaStreamTrackPrivate&, MediaSample&);
@@ -212,7 +201,7 @@
     void setVideoFullscreenLayer(PlatformLayer*, WTF::Function<void()>&& completionHandler) override;
     void setVideoFullscreenFrame(FloatRect) override;
 
-    MediaTime streamTime() const;
+    MediaTime streamTime() const final;
 
     AudioSourceProvider* audioSourceProvider() final;
 
@@ -220,14 +209,11 @@
 
     void applicationDidBecomeActive() final;
 
-    bool hideBackgroundLayer() const { return (!m_activeVideoTrack || m_waitingForFirstImage) && m_displayMode != PaintItBlack; }
+    bool hideRootLayer() const { return (!m_activeVideoTrack || m_waitingForFirstImage) && m_displayMode != PaintItBlack; }
 
     MediaPlayer* m_player { nullptr };
     RefPtr<MediaStreamPrivate> m_mediaStreamPrivate;
     RefPtr<MediaStreamTrackPrivate> m_activeVideoTrack;
-    RetainPtr<WebAVSampleBufferStatusChangeListener> m_statusChangeListener;
-    RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
-    RetainPtr<PlatformLayer> m_backgroundLayer;
     std::unique_ptr<PAL::Clock> m_clock;
 
     MediaTime m_pausedTime;
@@ -244,7 +230,6 @@
 
     HashMap<String, RefPtr<AudioTrackPrivateMediaStream>> m_audioTrackMap;
     HashMap<String, RefPtr<VideoTrackPrivateMediaStream>> m_videoTrackMap;
-    PendingSampleQueue m_pendingVideoSampleQueue;
 
     MediaPlayer::NetworkState m_networkState { MediaPlayer::NetworkState::Empty };
     MediaPlayer::ReadyState m_readyState { MediaPlayer::ReadyState::HaveNothing };
@@ -254,8 +239,13 @@
     PlaybackState m_playbackState { PlaybackState::None };
     MediaSample::VideoRotation m_videoRotation { MediaSample::VideoRotation::None };
     CGAffineTransform m_videoTransform;
+    std::unique_ptr<SampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
     std::unique_ptr<VideoFullscreenLayerManagerObjC> m_videoFullscreenLayerManager;
 
+    // SampleBufferDisplayLayer::Client
+    void sampleBufferDisplayLayerStatusDidChange(SampleBufferDisplayLayer&) final;
+    void sampleBufferDisplayLayerBoundsDidChange(SampleBufferDisplayLayer&) final;
+
 #if !RELEASE_LOG_DISABLED
     Ref<const Logger> m_logger;
     const void* m_logIdentifier;

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2020-01-15 11:45:50 UTC (rev 254563)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2020-01-15 14:24:12 UTC (rev 254564)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,20 +31,16 @@
 #import "AudioTrackPrivateMediaStream.h"
 #import "GraphicsContextCG.h"
 #import "Logging.h"
+#import "LocalSampleBufferDisplayLayer.h"
 #import "MediaStreamPrivate.h"
 #import "PixelBufferConformerCV.h"
 #import "VideoFullscreenLayerManagerObjC.h"
 #import "VideoTrackPrivateMediaStream.h"
-#import <AVFoundation/AVSampleBufferDisplayLayer.h>
 #import <CoreGraphics/CGAffineTransform.h>
-#import <QuartzCore/CALayer.h>
-#import <QuartzCore/CATransaction.h>
 #import <objc_runtime.h>
 #import <pal/avfoundation/MediaTimeAVFoundation.h>
 #import <pal/spi/mac/AVFoundationSPI.h>
 #import <pal/system/Clock.h>
-#import <wtf/Deque.h>
-#import <wtf/Function.h>
 #import <wtf/MainThread.h>
 #import <wtf/NeverDestroyed.h>
 
@@ -52,127 +48,6 @@
 #import <pal/cf/CoreMediaSoftLink.h>
 #import <pal/cocoa/AVFoundationSoftLink.h>
 
-using namespace WebCore;
-
-@interface WebAVSampleBufferStatusChangeListener : NSObject {
-    MediaPlayerPrivateMediaStreamAVFObjC* _parent;
-}
-
-- (id)initWithParent:(MediaPlayerPrivateMediaStreamAVFObjC*)callback;
-- (void)invalidate;
-- (void)beginObservingLayers;
-- (void)stopObservingLayers;
-@end
-
-@implementation WebAVSampleBufferStatusChangeListener
-
-- (id)initWithParent:(MediaPlayerPrivateMediaStreamAVFObjC*)parent
-{
-    if (!(self = [super init]))
-        return nil;
-
-    _parent = parent;
-
-    return self;
-}
-
-- (void)dealloc
-{
-    [self invalidate];
-    [super dealloc];
-}
-
-- (void)invalidate
-{
-    [self stopObservingLayers];
-    _parent = nullptr;
-}
-
-- (void)beginObservingLayers
-{
-    ASSERT(_parent);
-    ASSERT(_parent->displayLayer());
-    ASSERT(_parent->backgroundLayer());
-
-    [_parent->displayLayer() addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
-    [_parent->displayLayer() addObserver:self forKeyPath:@"error" options:NSKeyValueObservingOptionNew context:nil];
-    [_parent->backgroundLayer() addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:nil];
-}
-
-- (void)stopObservingLayers
-{
-    if (!_parent)
-        return;
-
-    if (_parent->displayLayer()) {
-        [_parent->displayLayer() removeObserver:self forKeyPath:@"status"];
-        [_parent->displayLayer() removeObserver:self forKeyPath:@"error"];
-    }
-    if (_parent->backgroundLayer())
-        [_parent->backgroundLayer() removeObserver:self forKeyPath:@"bounds"];
-}
-
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
-    UNUSED_PARAM(context);
-    UNUSED_PARAM(keyPath);
-    ASSERT(_parent);
-
-    if (!_parent)
-        return;
-
-    if ([object isKindOfClass:PAL::getAVSampleBufferDisplayLayerClass()]) {
-        RetainPtr<AVSampleBufferDisplayLayer> layer = (AVSampleBufferDisplayLayer *)object;
-        ASSERT(layer.get() == _parent->displayLayer());
-
-        if ([keyPath isEqualToString:@"status"]) {
-            RetainPtr<NSNumber> status = [change valueForKey:NSKeyValueChangeNewKey];
-            callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self), layer = WTFMove(layer), status = WTFMove(status)] {
-                if (!protectedSelf->_parent)
-                    return;
-
-                protectedSelf->_parent->layerStatusDidChange(layer.get());
-            });
-            return;
-        }
-
-        if ([keyPath isEqualToString:@"error"]) {
-            RetainPtr<NSNumber> status = [change valueForKey:NSKeyValueChangeNewKey];
-            callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self), layer = WTFMove(layer), status = WTFMove(status)] {
-                if (!protectedSelf->_parent)
-                    return;
-
-                protectedSelf->_parent->layerErrorDidChange(layer.get());
-            });
-            return;
-        }
-    }
-
-    if ([[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
-        return;
-
-    if ((CALayer *)object == _parent->backgroundLayer()) {
-        if ([keyPath isEqualToString:@"bounds"]) {
-            if (!_parent)
-                return;
-
-            if (isMainThread()) {
-                _parent->backgroundLayerBoundsChanged();
-                return;
-            }
-
-            callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self)] {
-                if (!protectedSelf->_parent)
-                    return;
-
-                protectedSelf->_parent->backgroundLayerBoundsChanged();
-            });
-        }
-    }
-
-}
-@end
-
 namespace WebCore {
 using namespace PAL;
 
@@ -183,7 +58,6 @@
 
 MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC(MediaPlayer* player)
     : m_player(player)
-    , m_statusChangeListener(adoptNS([[WebAVSampleBufferStatusChangeListener alloc] initWithParent:this]))
     , m_clock(PAL::Clock::create())
     , m_videoFullscreenLayerManager(makeUnique<VideoFullscreenLayerManagerObjC>())
 #if !RELEASE_LOG_DISABLED
@@ -198,8 +72,6 @@
 {
     INFO_LOG(LOGIDENTIFIER);
 
-    [m_statusChangeListener invalidate];
-
     for (const auto& track : m_audioTrackMap.values())
         track->pause();
 
@@ -269,33 +141,6 @@
 #pragma mark -
 #pragma mark AVSampleBuffer Methods
 
-void MediaPlayerPrivateMediaStreamAVFObjC::removeOldSamplesFromPendingQueue(PendingSampleQueue& queue)
-{
-    if (queue.isEmpty())
-        return;
-
-    auto decodeTime = queue.first()->decodeTime();
-    if (!decodeTime.isValid() || decodeTime < MediaTime::zeroTime()) {
-        while (queue.size() > 5)
-            queue.removeFirst();
-
-        return;
-    }
-
-    MediaTime now = streamTime();
-    while (!queue.isEmpty()) {
-        if (queue.first()->decodeTime() > now)
-            break;
-        queue.removeFirst();
-    }
-}
-
-void MediaPlayerPrivateMediaStreamAVFObjC::addSampleToPendingQueue(PendingSampleQueue& queue, MediaSample& sample)
-{
-    removeOldSamplesFromPendingQueue(queue);
-    queue.append(sample);
-}
-
 MediaTime MediaPlayerPrivateMediaStreamAVFObjC::calculateTimelineOffset(const MediaSample& sample, double latency)
 {
     MediaTime sampleTime = sample.outputPresentationTime();
@@ -330,37 +175,19 @@
     return m_videoTransform;
 }
 
-static void runWithoutAnimations(const WTF::Function<void()>& function)
-{
-    [CATransaction begin];
-    [CATransaction setAnimationDuration:0];
-    [CATransaction setDisableActions:YES];
-    function();
-    [CATransaction commit];
-}
-
 void MediaPlayerPrivateMediaStreamAVFObjC::enqueueCorrectedVideoSample(MediaSample& sample)
 {
     if (m_sampleBufferDisplayLayer) {
-        if ([m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed)
+        if (m_sampleBufferDisplayLayer->didFail())
             return;
 
         if (sample.videoRotation() != m_videoRotation || sample.videoMirrored() != m_videoMirrored) {
             m_videoRotation = sample.videoRotation();
             m_videoMirrored = sample.videoMirrored();
-            runWithoutAnimations([this, &sample] {
-                m_sampleBufferDisplayLayer.get().affineTransform = videoTransformationMatrix(sample, true);
-                updateDisplayLayer();
-            });
+            m_sampleBufferDisplayLayer->updateAffineTransform(videoTransformationMatrix(sample, true));
+            updateDisplayLayer();
         }
-
-        if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
-            addSampleToPendingQueue(m_pendingVideoSampleQueue, sample);
-            requestNotificationWhenReadyForVideoData();
-            return;
-        }
-
-        [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
+        m_sampleBufferDisplayLayer->enqueueSample(sample);
     }
 
     if (!m_hasEverEnqueuedVideoFrame) {
@@ -415,32 +242,6 @@
     }
 }
 
-void MediaPlayerPrivateMediaStreamAVFObjC::requestNotificationWhenReadyForVideoData()
-{
-    auto weakThis = makeWeakPtr(*this);
-    [m_sampleBufferDisplayLayer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^ {
-        if (!weakThis)
-            return;
-
-        [m_sampleBufferDisplayLayer stopRequestingMediaData];
-
-        if (!m_activeVideoTrack) {
-            m_pendingVideoSampleQueue.clear();
-            return;
-        }
-
-        while (!m_pendingVideoSampleQueue.isEmpty()) {
-            if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
-                requestNotificationWhenReadyForVideoData();
-                return;
-            }
-
-            auto sample = m_pendingVideoSampleQueue.takeFirst();
-            enqueueVideoSample(*m_activeVideoTrack.get(), sample.get());
-        }
-    }];
-}
-
 AudioSourceProvider* MediaPlayerPrivateMediaStreamAVFObjC::audioSourceProvider()
 {
     // FIXME: This should return a mix of all audio tracks - https://bugs.webkit.org/show_bug.cgi?id=160305
@@ -447,29 +248,20 @@
     return nullptr;
 }
 
-void MediaPlayerPrivateMediaStreamAVFObjC::layerErrorDidChange(AVSampleBufferDisplayLayer* layer)
+void MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerStatusDidChange(SampleBufferDisplayLayer& layer)
 {
+    ASSERT(&layer == m_sampleBufferDisplayLayer.get());
     UNUSED_PARAM(layer);
-    ERROR_LOG(LOGIDENTIFIER, "error = ", [[layer.error localizedDescription] UTF8String]);
-}
-
-void MediaPlayerPrivateMediaStreamAVFObjC::layerStatusDidChange(AVSampleBufferDisplayLayer* layer)
-{
-    ALWAYS_LOG(LOGIDENTIFIER, "status = ", (int)layer.status);
-
-    if (layer.status != AVQueuedSampleBufferRenderingStatusRendering)
+    if (!m_activeVideoTrack)
         return;
-    if (!m_sampleBufferDisplayLayer || !m_activeVideoTrack || layer != m_sampleBufferDisplayLayer)
-        return;
 
-    auto track = m_videoTrackMap.get(m_activeVideoTrack->id());
-    if (track)
+    if (auto track = m_videoTrackMap.get(m_activeVideoTrack->id()))
         track->setTimelineOffset(MediaTime::invalidTime());
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::applicationDidBecomeActive()
 {
-    if (m_sampleBufferDisplayLayer && [m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed) {
+    if (m_sampleBufferDisplayLayer && m_sampleBufferDisplayLayer->didFail()) {
         flushRenderers();
         if (m_imagePainter.mediaSample)
             enqueueCorrectedVideoSample(*m_imagePainter.mediaSample);
@@ -480,7 +272,7 @@
 void MediaPlayerPrivateMediaStreamAVFObjC::flushRenderers()
 {
     if (m_sampleBufferDisplayLayer)
-        [m_sampleBufferDisplayLayer flush];
+        m_sampleBufferDisplayLayer->flush();
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers()
@@ -491,51 +283,24 @@
     if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->activeVideoTrack() || !m_mediaStreamPrivate->activeVideoTrack()->enabled())
         return;
 
-    m_sampleBufferDisplayLayer = adoptNS([PAL::allocAVSampleBufferDisplayLayerInstance() init]);
+    auto size = snappedIntRect(m_player->playerContentBoxRect()).size();
+    m_sampleBufferDisplayLayer = LocalSampleBufferDisplayLayer::create(*this, hideRootLayer(), size);
+
     if (!m_sampleBufferDisplayLayer) {
-        ERROR_LOG(LOGIDENTIFIER, "+[AVSampleBufferDisplayLayer alloc] failed.");
+        ERROR_LOG(LOGIDENTIFIER, "Creating the SampleBufferDisplayLayer failed.");
         return;
     }
 
-    m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
-    m_sampleBufferDisplayLayer.get().anchorPoint = { .5, .5 };
-    m_sampleBufferDisplayLayer.get().needsDisplayOnBoundsChange = YES;
-    m_sampleBufferDisplayLayer.get().videoGravity = AVLayerVideoGravityResizeAspectFill;
-
-    m_backgroundLayer = adoptNS([[CALayer alloc] init]);
-    m_backgroundLayer.get().hidden = hideBackgroundLayer();
-
-    m_backgroundLayer.get().backgroundColor = cachedCGColor(Color::black);
-    m_backgroundLayer.get().needsDisplayOnBoundsChange = YES;
-
-    auto size = snappedIntRect(m_player->playerContentBoxRect()).size();
-    m_backgroundLayer.get().bounds = CGRectMake(0, 0, size.width(), size.height());
-
-    [m_statusChangeListener beginObservingLayers];
-
-    [m_backgroundLayer addSublayer:m_sampleBufferDisplayLayer.get()];
-
-#ifndef NDEBUG
-    [m_sampleBufferDisplayLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer"];
-    [m_backgroundLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer parent"];
-#endif
-
     updateRenderingMode();
     updateDisplayLayer();
 
-    m_videoFullscreenLayerManager->setVideoLayer(m_backgroundLayer.get(), size);
+    m_videoFullscreenLayerManager->setVideoLayer(m_sampleBufferDisplayLayer->rootLayer(), size);
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::destroyLayers()
 {
-    [m_statusChangeListener stopObservingLayers];
-    if (m_sampleBufferDisplayLayer) {
-        m_pendingVideoSampleQueue.clear();
-        [m_sampleBufferDisplayLayer stopRequestingMediaData];
-        [m_sampleBufferDisplayLayer flush];
+    if (m_sampleBufferDisplayLayer)
         m_sampleBufferDisplayLayer = nullptr;
-    }
-    m_backgroundLayer = nullptr;
 
     updateRenderingMode();
     
@@ -602,22 +367,12 @@
 
 PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
 {
-    if (!m_backgroundLayer || m_displayMode == None)
+    if (!m_sampleBufferDisplayLayer || !m_sampleBufferDisplayLayer->rootLayer() || m_displayMode == None)
         return nullptr;
 
     return m_videoFullscreenLayerManager->videoInlineLayer();
 }
 
-PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::displayLayer()
-{
-    return m_sampleBufferDisplayLayer.get();
-}
-
-PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::backgroundLayer()
-{
-    return m_backgroundLayer.get();
-}
-
 MediaPlayerPrivateMediaStreamAVFObjC::DisplayMode MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode() const
 {
     if (m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)
@@ -653,18 +408,8 @@
     INFO_LOG(LOGIDENTIFIER, "updated to ", static_cast<int>(displayMode));
     m_displayMode = displayMode;
 
-    auto hidden = m_displayMode < PausedImage;
-    if (m_sampleBufferDisplayLayer && m_sampleBufferDisplayLayer.get().hidden != hidden) {
-        runWithoutAnimations([this, hidden] {
-            m_sampleBufferDisplayLayer.get().hidden = hidden;
-        });
-    }
-    hidden = hideBackgroundLayer();
-    if (m_backgroundLayer && m_backgroundLayer.get().hidden != hidden) {
-        runWithoutAnimations([this, hidden] {
-            m_backgroundLayer.get().hidden = hidden;
-        });
-    }
+    if (m_sampleBufferDisplayLayer)
+        m_sampleBufferDisplayLayer->updateDisplayMode(m_displayMode < PausedImage, hideRootLayer());
 
     return true;
 }
@@ -1023,8 +768,11 @@
                 m_waitingForFirstImage = true;
         }
         ensureLayers();
-        m_sampleBufferDisplayLayer.get().hidden = hideVideoLayer || m_displayMode < PausedImage;
-        m_backgroundLayer.get().hidden = hideBackgroundLayer();
+        if (m_sampleBufferDisplayLayer) {
+            if (!m_activeVideoTrack)
+                m_sampleBufferDisplayLayer->clearEnqueuedSamples();
+            m_sampleBufferDisplayLayer->updateDisplayMode(hideVideoLayer || m_displayMode < PausedImage, hideRootLayer());
+        }
 
         m_pendingSelectedTrackCheck = false;
         updateDisplayMode();
@@ -1173,8 +921,8 @@
 
 void MediaPlayerPrivateMediaStreamAVFObjC::setBufferingPolicy(MediaPlayer::BufferingPolicy policy)
 {
-    if (policy != MediaPlayer::BufferingPolicy::Default)
-        [m_sampleBufferDisplayLayer flushAndRemoveImage];
+    if (policy != MediaPlayer::BufferingPolicy::Default && m_sampleBufferDisplayLayer)
+        m_sampleBufferDisplayLayer->flushAndRemoveImage();
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask(Function<void ()>&& function)
@@ -1197,23 +945,20 @@
 
 void MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayLayer()
 {
-    if (!m_backgroundLayer || !m_sampleBufferDisplayLayer)
+    if (!m_sampleBufferDisplayLayer)
         return;
 
-    auto backgroundBounds = m_backgroundLayer.get().bounds;
-    auto videoBounds = backgroundBounds;
+    auto bounds = m_sampleBufferDisplayLayer->bounds();
+    auto videoBounds = bounds;
     if (m_videoRotation == MediaSample::VideoRotation::Right || m_videoRotation == MediaSample::VideoRotation::Left)
         std::swap(videoBounds.size.width, videoBounds.size.height);
 
-    m_sampleBufferDisplayLayer.get().bounds = videoBounds;
-    m_sampleBufferDisplayLayer.get().position = { backgroundBounds.size.width / 2, backgroundBounds.size.height / 2};
+    m_sampleBufferDisplayLayer->updateBoundsAndPosition(videoBounds, { bounds.size.width / 2, bounds.size.height / 2});
 }
 
-void MediaPlayerPrivateMediaStreamAVFObjC::backgroundLayerBoundsChanged()
+void MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerBoundsDidChange(SampleBufferDisplayLayer&)
 {
-    runWithoutAnimations([this] {
-        updateDisplayLayer();
-    });
+    updateDisplayLayer();
 }
 
 #if !RELEASE_LOG_DISABLED
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to