Unreviewed, rolling out r254564.

This caused internal test crashes.

Reverted changeset:

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

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254779 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index bc6ba4d..c71ff6c 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,5 +1,17 @@
 2020-01-17  Matt Lewis  <jlewis3@apple.com>
 
+        Unreviewed, rolling out r254564.
+
+        This caused internal test crashes.
+
+        Reverted changeset:
+
+        "Introduce an abstract SampleBufferDisplayLayer"
+        https://bugs.webkit.org/show_bug.cgi?id=206066
+        https://trac.webkit.org/changeset/254564
+
+2020-01-17  Matt Lewis  <jlewis3@apple.com>
+
         Unreviewed, rolling out r254688.
 
         This caused internal test crashes.
diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt
index 8906f57..e6f817a 100644
--- a/Source/WebCore/SourcesCocoa.txt
+++ b/Source/WebCore/SourcesCocoa.txt
@@ -253,7 +253,6 @@
 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
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index aa182ff..6507b9a 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -1067,7 +1067,6 @@
 		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 */; };
@@ -1154,8 +1153,6 @@
 		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 */; };
@@ -7350,9 +7347,6 @@
 		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>"; };
@@ -16332,7 +16326,6 @@
 				076F0D0A12B8192700C26AA4 /* MediaPlayerPrivateAVFoundation.h */,
 				CDBEAEAB19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h */,
 				CDBEAEAA19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm */,
-				414598BE23C8AAB8002B9CC8 /* SampleBufferDisplayLayer.h */,
 				CD336F6317FA0A4D00DDDCD0 /* VideoTrackPrivateAVF.h */,
 				0709D7901AE5557E004E42F8 /* WebMediaSessionManagerMac.cpp */,
 				0709D7911AE5557E004E42F8 /* WebMediaSessionManagerMac.h */,
@@ -26757,8 +26750,6 @@
 				07AA6B6A166D019500D45671 /* InbandTextTrackPrivateAVFObjC.mm */,
 				07367DDD172CA67F00D861B9 /* InbandTextTrackPrivateLegacyAVFObjC.h */,
 				07367DDE172CA67F00D861B9 /* InbandTextTrackPrivateLegacyAVFObjC.mm */,
-				414598C023C8AD78002B9CC8 /* LocalSampleBufferDisplayLayer.h */,
-				414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */,
 				078E43DB1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.h */,
 				078E43DC1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.mm */,
 				DF9AFD7013FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.h */,
@@ -31408,7 +31399,6 @@
 				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 */,
@@ -32193,7 +32183,6 @@
 				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 */,
@@ -33663,7 +33652,6 @@
 				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 */,
diff --git a/Source/WebCore/platform/graphics/avfoundation/SampleBufferDisplayLayer.h b/Source/WebCore/platform/graphics/avfoundation/SampleBufferDisplayLayer.h
deleted file mode 100644
index 4ff57d7..0000000
--- a/Source/WebCore/platform/graphics/avfoundation/SampleBufferDisplayLayer.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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))
-{
-}
-
-}
diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h b/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h
deleted file mode 100644
index 29cdea4..0000000
--- a/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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)
diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm b/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm
deleted file mode 100644
index f0c9cc7..0000000
--- a/Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * 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
diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h
index d9af27a..0340a8d 100644
--- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h
+++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h
@@ -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 MediaPlayerPrivateInterface, private MediaStreamPrivate::Observer, private MediaStreamTrackPrivate::Observer, public SampleBufferDisplayLayer::Client
+class MediaPlayerPrivateMediaStreamAVFObjC final : public CanMakeWeakPtr<MediaPlayerPrivateMediaStreamAVFObjC>, public MediaPlayerPrivateInterface, private MediaStreamPrivate::Observer, private MediaStreamTrackPrivate::Observer
 #if !RELEASE_LOG_DISABLED
     , private LoggerHelper
 #endif
@@ -75,6 +75,13 @@
     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"; }
@@ -130,6 +137,10 @@
 
     void flushRenderers();
 
+    using PendingSampleQueue = Deque<Ref<MediaSample>>;
+    void addSampleToPendingQueue(PendingSampleQueue&, MediaSample&);
+    void removeOldSamplesFromPendingQueue(PendingSampleQueue&);
+
     MediaTime calculateTimelineOffset(const MediaSample&, double);
     
     void enqueueVideoSample(MediaStreamTrackPrivate&, MediaSample&);
@@ -201,7 +212,7 @@
     void setVideoFullscreenLayer(PlatformLayer*, WTF::Function<void()>&& completionHandler) override;
     void setVideoFullscreenFrame(FloatRect) override;
 
-    MediaTime streamTime() const final;
+    MediaTime streamTime() const;
 
     AudioSourceProvider* audioSourceProvider() final;
 
@@ -209,11 +220,14 @@
 
     void applicationDidBecomeActive() final;
 
-    bool hideRootLayer() const { return (!m_activeVideoTrack || m_waitingForFirstImage) && m_displayMode != PaintItBlack; }
+    bool hideBackgroundLayer() 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;
@@ -230,6 +244,7 @@
 
     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 };
@@ -239,13 +254,8 @@
     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;
diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm
index df9e205..5fcf9ab 100644
--- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm
+++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 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,16 +31,20 @@
 #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>
 
@@ -48,6 +52,127 @@
 #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;
 
@@ -58,6 +183,7 @@
 
 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
@@ -72,6 +198,8 @@
 {
     INFO_LOG(LOGIDENTIFIER);
 
+    [m_statusChangeListener invalidate];
+
     for (const auto& track : m_audioTrackMap.values())
         track->pause();
 
@@ -141,6 +269,33 @@
 #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();
@@ -175,19 +330,37 @@
     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->didFail())
+        if ([m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed)
             return;
 
         if (sample.videoRotation() != m_videoRotation || sample.videoMirrored() != m_videoMirrored) {
             m_videoRotation = sample.videoRotation();
             m_videoMirrored = sample.videoMirrored();
-            m_sampleBufferDisplayLayer->updateAffineTransform(videoTransformationMatrix(sample, true));
-            updateDisplayLayer();
+            runWithoutAnimations([this, &sample] {
+                m_sampleBufferDisplayLayer.get().affineTransform = videoTransformationMatrix(sample, true);
+                updateDisplayLayer();
+            });
         }
-        m_sampleBufferDisplayLayer->enqueueSample(sample);
+
+        if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
+            addSampleToPendingQueue(m_pendingVideoSampleQueue, sample);
+            requestNotificationWhenReadyForVideoData();
+            return;
+        }
+
+        [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
     }
 
     if (!m_hasEverEnqueuedVideoFrame) {
@@ -242,26 +415,61 @@
     }
 }
 
+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
     return nullptr;
 }
 
-void MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerStatusDidChange(SampleBufferDisplayLayer& layer)
+void MediaPlayerPrivateMediaStreamAVFObjC::layerErrorDidChange(AVSampleBufferDisplayLayer* layer)
 {
-    ASSERT(&layer == m_sampleBufferDisplayLayer.get());
     UNUSED_PARAM(layer);
-    if (!m_activeVideoTrack)
+    ERROR_LOG(LOGIDENTIFIER, "error = ", [[layer.error localizedDescription] UTF8String]);
+}
+
+void MediaPlayerPrivateMediaStreamAVFObjC::layerStatusDidChange(AVSampleBufferDisplayLayer* layer)
+{
+    ALWAYS_LOG(LOGIDENTIFIER, "status = ", (int)layer.status);
+
+    if (layer.status != AVQueuedSampleBufferRenderingStatusRendering)
+        return;
+    if (!m_sampleBufferDisplayLayer || !m_activeVideoTrack || layer != m_sampleBufferDisplayLayer)
         return;
 
-    if (auto track = m_videoTrackMap.get(m_activeVideoTrack->id()))
+    auto track = m_videoTrackMap.get(m_activeVideoTrack->id());
+    if (track)
         track->setTimelineOffset(MediaTime::invalidTime());
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::applicationDidBecomeActive()
 {
-    if (m_sampleBufferDisplayLayer && m_sampleBufferDisplayLayer->didFail()) {
+    if (m_sampleBufferDisplayLayer && [m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed) {
         flushRenderers();
         if (m_imagePainter.mediaSample)
             enqueueCorrectedVideoSample(*m_imagePainter.mediaSample);
@@ -272,7 +480,7 @@
 void MediaPlayerPrivateMediaStreamAVFObjC::flushRenderers()
 {
     if (m_sampleBufferDisplayLayer)
-        m_sampleBufferDisplayLayer->flush();
+        [m_sampleBufferDisplayLayer flush];
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers()
@@ -283,24 +491,51 @@
     if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->activeVideoTrack() || !m_mediaStreamPrivate->activeVideoTrack()->enabled())
         return;
 
-    auto size = snappedIntRect(m_player->playerContentBoxRect()).size();
-    m_sampleBufferDisplayLayer = LocalSampleBufferDisplayLayer::create(*this, hideRootLayer(), size);
-
+    m_sampleBufferDisplayLayer = adoptNS([PAL::allocAVSampleBufferDisplayLayerInstance() init]);
     if (!m_sampleBufferDisplayLayer) {
-        ERROR_LOG(LOGIDENTIFIER, "Creating the SampleBufferDisplayLayer failed.");
+        ERROR_LOG(LOGIDENTIFIER, "+[AVSampleBufferDisplayLayer alloc] 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_sampleBufferDisplayLayer->rootLayer(), size);
+    m_videoFullscreenLayerManager->setVideoLayer(m_backgroundLayer.get(), size);
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::destroyLayers()
 {
-    if (m_sampleBufferDisplayLayer)
+    [m_statusChangeListener stopObservingLayers];
+    if (m_sampleBufferDisplayLayer) {
+        m_pendingVideoSampleQueue.clear();
+        [m_sampleBufferDisplayLayer stopRequestingMediaData];
+        [m_sampleBufferDisplayLayer flush];
         m_sampleBufferDisplayLayer = nullptr;
+    }
+    m_backgroundLayer = nullptr;
 
     updateRenderingMode();
     
@@ -367,12 +602,22 @@
 
 PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
 {
-    if (!m_sampleBufferDisplayLayer || !m_sampleBufferDisplayLayer->rootLayer() || m_displayMode == None)
+    if (!m_backgroundLayer || 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)
@@ -408,8 +653,18 @@
     INFO_LOG(LOGIDENTIFIER, "updated to ", static_cast<int>(displayMode));
     m_displayMode = displayMode;
 
-    if (m_sampleBufferDisplayLayer)
-        m_sampleBufferDisplayLayer->updateDisplayMode(m_displayMode < PausedImage, hideRootLayer());
+    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;
+        });
+    }
 
     return true;
 }
@@ -768,11 +1023,8 @@
                 m_waitingForFirstImage = true;
         }
         ensureLayers();
-        if (m_sampleBufferDisplayLayer) {
-            if (!m_activeVideoTrack)
-                m_sampleBufferDisplayLayer->clearEnqueuedSamples();
-            m_sampleBufferDisplayLayer->updateDisplayMode(hideVideoLayer || m_displayMode < PausedImage, hideRootLayer());
-        }
+        m_sampleBufferDisplayLayer.get().hidden = hideVideoLayer || m_displayMode < PausedImage;
+        m_backgroundLayer.get().hidden = hideBackgroundLayer();
 
         m_pendingSelectedTrackCheck = false;
         updateDisplayMode();
@@ -921,8 +1173,8 @@
 
 void MediaPlayerPrivateMediaStreamAVFObjC::setBufferingPolicy(MediaPlayer::BufferingPolicy policy)
 {
-    if (policy != MediaPlayer::BufferingPolicy::Default && m_sampleBufferDisplayLayer)
-        m_sampleBufferDisplayLayer->flushAndRemoveImage();
+    if (policy != MediaPlayer::BufferingPolicy::Default)
+        [m_sampleBufferDisplayLayer flushAndRemoveImage];
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask(Function<void ()>&& function)
@@ -945,20 +1197,23 @@
 
 void MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayLayer()
 {
-    if (!m_sampleBufferDisplayLayer)
+    if (!m_backgroundLayer || !m_sampleBufferDisplayLayer)
         return;
 
-    auto bounds = m_sampleBufferDisplayLayer->bounds();
-    auto videoBounds = bounds;
+    auto backgroundBounds = m_backgroundLayer.get().bounds;
+    auto videoBounds = backgroundBounds;
     if (m_videoRotation == MediaSample::VideoRotation::Right || m_videoRotation == MediaSample::VideoRotation::Left)
         std::swap(videoBounds.size.width, videoBounds.size.height);
 
-    m_sampleBufferDisplayLayer->updateBoundsAndPosition(videoBounds, { bounds.size.width / 2, bounds.size.height / 2});
+    m_sampleBufferDisplayLayer.get().bounds = videoBounds;
+    m_sampleBufferDisplayLayer.get().position = { backgroundBounds.size.width / 2, backgroundBounds.size.height / 2};
 }
 
-void MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerBoundsDidChange(SampleBufferDisplayLayer&)
+void MediaPlayerPrivateMediaStreamAVFObjC::backgroundLayerBoundsChanged()
 {
-    updateDisplayLayer();
+    runWithoutAnimations([this] {
+        updateDisplayLayer();
+    });
 }
 
 #if !RELEASE_LOG_DISABLED