Source/WebCore/ChangeLog

 12020-01-10 youenn fablet <youenn@apple.com>
 2
 3 Introduce an abstract SampleBufferDisplayLayer
 4 https://bugs.webkit.org/show_bug.cgi?id=206066
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Move use of display layers in MediaPlayerPrivateMediaStreamAVFObjC to a new class LocalSampleBufferDisplayLayer
 9 that implements an interface named SampleBufferDisplayLayer.
 10 A future patch will implement this interface by IPCing to GPUProcess.
 11 We move both layers and handling of the sample queue to LocalSampleBufferDisplayLayer.
 12
 13 Contrary to previously, we do not call again enqueueVideoSample in case we enqueued a sample for later use in the display layer.
 14 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.
 15
 16 * SourcesCocoa.txt:
 17 * WebCore.xcodeproj/project.pbxproj:
 18 * platform/graphics/avfoundation/SampleBufferDisplayLayer.h: Added.
 19 (WebCore::SampleBufferDisplayLayer::SampleBufferDisplayLayer):
 20 * platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h: Added.
 21 * platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm: Added.
 22 (-[WebAVSampleBufferStatusChangeListener initWithParent:]):
 23 (-[WebAVSampleBufferStatusChangeListener dealloc]):
 24 (-[WebAVSampleBufferStatusChangeListener invalidate]):
 25 (-[WebAVSampleBufferStatusChangeListener beginObservingLayers]):
 26 (-[WebAVSampleBufferStatusChangeListener stopObservingLayers]):
 27 (-[WebAVSampleBufferStatusChangeListener observeValueForKeyPath:ofObject:change:context:]):
 28 (WebCore::runWithoutAnimations):
 29 (WebCore::LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer):
 30 (WebCore::LocalSampleBufferDisplayLayer::~LocalSampleBufferDisplayLayer):
 31 (WebCore::LocalSampleBufferDisplayLayer::layerStatusDidChange):
 32 (WebCore::LocalSampleBufferDisplayLayer::layerErrorDidChange):
 33 (WebCore::LocalSampleBufferDisplayLayer::rootLayerBoundsDidChange):
 34 (WebCore::LocalSampleBufferDisplayLayer::displayLayer):
 35 (WebCore::LocalSampleBufferDisplayLayer::rootLayer):
 36 (WebCore::LocalSampleBufferDisplayLayer::didFail const):
 37 (WebCore::LocalSampleBufferDisplayLayer::updateDisplayMode):
 38 (WebCore::LocalSampleBufferDisplayLayer::bounds const):
 39 (WebCore::LocalSampleBufferDisplayLayer::updateAffineTransform):
 40 (WebCore::LocalSampleBufferDisplayLayer::updateBoundsAndPosition):
 41 (WebCore::LocalSampleBufferDisplayLayer::ensureLayers):
 42 (WebCore::LocalSampleBufferDisplayLayer::flush):
 43 (WebCore::LocalSampleBufferDisplayLayer::flushAndRemoveImage):
 44 (WebCore::LocalSampleBufferDisplayLayer::enqueueSample):
 45 (WebCore::LocalSampleBufferDisplayLayer::removeOldSamplesFromPendingQueue):
 46 (WebCore::LocalSampleBufferDisplayLayer::addSampleToPendingQueue):
 47 (WebCore::LocalSampleBufferDisplayLayer::clearEnqueuedSamples):
 48 (WebCore::LocalSampleBufferDisplayLayer::requestNotificationWhenReadyForVideoData):
 49 * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
 50 * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
 51 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC):
 52 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC):
 53 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueCorrectedVideoSample):
 54 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerStatusDidChange):
 55 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::applicationDidBecomeActive):
 56 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::flushRenderers):
 57 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers):
 58 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::destroyLayers):
 59 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer const):
 60 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::displayLayer):
 61 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayMode):
 62 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::checkSelectedVideoTrack):
 63 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setBufferingPolicy):
 64 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayLayer):
 65 (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerBoundsDidChange):
 66
 672020-01-10 youenn fablet <youenn@apple.com>
 68
 69 Clean-up MediaPlayerPrivateMediaStreamAVFObjC.h
 70 https://bugs.webkit.org/show_bug.cgi?id=206060
 71
 72 Reviewed by NOBODY (OOPS!).
 73
 74 No change of behavior.
 75
 76 * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
 77 * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
 78
1792020-01-10 Adrian Perez de Castro <aperez@igalia.com>
280
381 Fix various non-unified build issues introduced since r253538

Source/WebCore/SourcesCocoa.txt

@@platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm @no-unify
253253platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm @no-unify
254254platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.mm @no-unify
255255platform/graphics/avfoundation/objc/InbandTextTrackPrivateLegacyAVFObjC.mm @no-unify
 256platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm @no-unify
256257platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm @no-unify
257258platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm @no-unify
258259platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm @no-unify

Source/WebCore/WebCore.xcodeproj/project.pbxproj

10681068 413C2C341BC29A8F0075204C /* JSDOMConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 413C2C331BC29A7B0075204C /* JSDOMConstructor.h */; };
10691069 413CCD4A20DE034F0065A21A /* MockMediaDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 413CCD4820DE013C0065A21A /* MockMediaDevice.h */; settings = {ATTRIBUTES = (Private, ); }; };
10701070 413E00791DB0E4F2002341D2 /* MemoryRelease.h in Headers */ = {isa = PBXBuildFile; fileRef = 413E00781DB0E4DE002341D2 /* MemoryRelease.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1071 414598C223C8D177002B9CC8 /* LocalSampleBufferDisplayLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */; };
10711072 414B82051D6DF0E50077EBE3 /* StructuredClone.h in Headers */ = {isa = PBXBuildFile; fileRef = 414B82031D6DF0D90077EBE3 /* StructuredClone.h */; };
10721073 414DEDE71F9FE91E0047C40D /* EmptyFrameLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 414DEDE51F9FE9150047C40D /* EmptyFrameLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
10731074 415071581685067300C3C7B3 /* SelectorFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 415071561685067300C3C7B3 /* SelectorFilter.h */; };

73477348 413E00781DB0E4DE002341D2 /* MemoryRelease.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryRelease.h; sourceTree = "<group>"; };
73487349 413E007B1DB0E707002341D2 /* MemoryReleaseCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryReleaseCocoa.mm; sourceTree = "<group>"; };
73497350 413FC4CD1FD1DD8C00541C4B /* ServiceWorkerClientQueryOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerClientQueryOptions.h; sourceTree = "<group>"; };
 7351 414598BE23C8AAB8002B9CC8 /* SampleBufferDisplayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleBufferDisplayLayer.h; sourceTree = "<group>"; };
 7352 414598C023C8AD78002B9CC8 /* LocalSampleBufferDisplayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalSampleBufferDisplayLayer.h; sourceTree = "<group>"; };
 7353 414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalSampleBufferDisplayLayer.mm; sourceTree = "<group>"; };
73507354 4147E2B21C88337F00A7E715 /* FetchBodyOwner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchBodyOwner.h; sourceTree = "<group>"; };
73517355 4147E2B31C89912600A7E715 /* FetchBodyOwner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchBodyOwner.cpp; sourceTree = "<group>"; };
73527356 4147E2B41C89912600A7E715 /* FetchLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchLoader.cpp; sourceTree = "<group>"; };

1631716321 076F0D0A12B8192700C26AA4 /* MediaPlayerPrivateAVFoundation.h */,
1631816322 CDBEAEAB19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h */,
1631916323 CDBEAEAA19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm */,
 16324 414598BE23C8AAB8002B9CC8 /* SampleBufferDisplayLayer.h */,
1632016325 CD336F6317FA0A4D00DDDCD0 /* VideoTrackPrivateAVF.h */,
1632116326 0709D7901AE5557E004E42F8 /* WebMediaSessionManagerMac.cpp */,
1632216327 0709D7911AE5557E004E42F8 /* WebMediaSessionManagerMac.h */,

2674026745 07AA6B6A166D019500D45671 /* InbandTextTrackPrivateAVFObjC.mm */,
2674126746 07367DDD172CA67F00D861B9 /* InbandTextTrackPrivateLegacyAVFObjC.h */,
2674226747 07367DDE172CA67F00D861B9 /* InbandTextTrackPrivateLegacyAVFObjC.mm */,
 26748 414598C023C8AD78002B9CC8 /* LocalSampleBufferDisplayLayer.h */,
 26749 414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */,
2674326750 078E43DB1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.h */,
2674426751 078E43DC1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.mm */,
2674526752 DF9AFD7013FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.h */,

3364033647 41D28D0D2139E05800F4206F /* LibWebRTCStatsCollector.cpp in Sources */,
3364133648 4186BD3E213EE3400001826F /* LibWebRTCUtils.cpp in Sources */,
3364233649 9759E93E14EF1CF80026A2DD /* LoadableTextTrack.cpp in Sources */,
 33650 414598C223C8D177002B9CC8 /* LocalSampleBufferDisplayLayer.mm in Sources */,
3364333651 FABE72FE1059C21100D999DD /* MathMLNames.cpp in Sources */,
3364433652 2D9BF7051DBFBB24007A7D99 /* MediaEncryptedEvent.cpp in Sources */,
3364533653 2D9BF7471DBFDC49007A7D99 /* MediaKeyMessageEvent.cpp in Sources */,

Source/WebCore/platform/graphics/avfoundation/SampleBufferDisplayLayer.h

 1/*
 2 * Copyright (C) 2020 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
 29
 30#include "PlatformLayer.h"
 31#include <wtf/WeakPtr.h>
 32
 33namespace WTF {
 34class MediaTime;
 35}
 36
 37namespace WebCore {
 38class IntSize;
 39class MediaSample;
 40
 41class SampleBufferDisplayLayer {
 42public:
 43 class Client : public CanMakeWeakPtr<Client> {
 44 public:
 45 virtual ~Client() = default;
 46 virtual void sampleBufferDisplayLayerStatusDidChange(SampleBufferDisplayLayer&) = 0;
 47 virtual void sampleBufferDisplayLayerBoundsDidChange(SampleBufferDisplayLayer&) = 0;
 48 virtual WTF::MediaTime streamTime() const = 0;
 49 };
 50
 51 explicit SampleBufferDisplayLayer(Client&);
 52 virtual ~SampleBufferDisplayLayer() = default;
 53
 54 virtual bool didFail() const = 0;
 55
 56 virtual void updateDisplayMode(bool hideDisplayLayer, bool hideRootLayer) = 0;
 57
 58 virtual CGRect bounds() const = 0;
 59 virtual void updateAffineTransform(CGAffineTransform) = 0;
 60 virtual void updateBoundsAndPosition(CGRect, CGPoint) = 0;
 61
 62 virtual void flush() = 0;
 63 virtual void flushAndRemoveImage() = 0;
 64
 65 virtual void enqueueSample(MediaSample&) = 0;
 66 virtual void clearEnqueuedSamples() = 0;
 67
 68 virtual PlatformLayer* displayLayer() = 0;
 69 virtual PlatformLayer* rootLayer() = 0;
 70
 71protected:
 72 WeakPtr<Client> m_client;
 73};
 74
 75inline SampleBufferDisplayLayer::SampleBufferDisplayLayer(Client& client)
 76 : m_client(makeWeakPtr(client))
 77{
 78}
 79
 80}
 81
 82#endif // ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)

Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h

 1/*
 2 * Copyright (C) 2020 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
 29
 30#include "SampleBufferDisplayLayer.h"
 31#include <wtf/Deque.h>
 32#include <wtf/Forward.h>
 33#include <wtf/RetainPtr.h>
 34
 35OBJC_CLASS AVSampleBufferDisplayLayer;
 36OBJC_CLASS WebAVSampleBufferStatusChangeListener;
 37
 38namespace WebCore {
 39
 40class LocalSampleBufferDisplayLayer final : public SampleBufferDisplayLayer, public CanMakeWeakPtr<LocalSampleBufferDisplayLayer> {
 41 WTF_MAKE_FAST_ALLOCATED;
 42public:
 43 static std::unique_ptr<SampleBufferDisplayLayer> create(Client&, bool hideRootLayer, IntSize);
 44
 45 LocalSampleBufferDisplayLayer(RetainPtr<AVSampleBufferDisplayLayer>&&, Client&, bool hideRootLayer, IntSize);
 46 ~LocalSampleBufferDisplayLayer();
 47
 48 // API used by WebAVSampleBufferStatusChangeListener
 49 void layerStatusDidChange();
 50 void layerErrorDidChange();
 51 void rootLayerBoundsDidChange();
 52
 53 PlatformLayer* displayLayer() final;
 54 PlatformLayer* rootLayer() final;
 55
 56private:
 57 bool didFail() const final;
 58
 59 void updateDisplayMode(bool hideDisplayLayer, bool hideRootLayer) final;
 60
 61 CGRect bounds() const final;
 62 void updateAffineTransform(CGAffineTransform) final;
 63 void updateBoundsAndPosition(CGRect, CGPoint) final;
 64
 65 void flush() final;
 66 void flushAndRemoveImage() final;
 67
 68 void enqueueSample(MediaSample&) final;
 69 void clearEnqueuedSamples() final;
 70
 71 void ensureLayers();
 72
 73 void removeOldSamplesFromPendingQueue();
 74 void addSampleToPendingQueue(MediaSample&);
 75 void requestNotificationWhenReadyForVideoData();
 76
 77private:
 78 RetainPtr<WebAVSampleBufferStatusChangeListener> m_statusChangeListener;
 79 RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
 80 RetainPtr<PlatformLayer> m_rootLayer;
 81
 82 using PendingSampleQueue = Deque<Ref<MediaSample>>;
 83 PendingSampleQueue m_pendingVideoSampleQueue;
 84};
 85
 86}
 87
 88#endif // ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)

Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm

 1/*
 2 * Copyright (C) 2020 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#import "config.h"
 27#import "LocalSampleBufferDisplayLayer.h"
 28
 29#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
 30
 31#import "Color.h"
 32#import "IntSize.h"
 33#import "MediaSample.h"
 34
 35#import <AVFoundation/AVSampleBufferDisplayLayer.h>
 36#import <QuartzCore/CALayer.h>
 37#import <QuartzCore/CATransaction.h>
 38
 39#import <wtf/MainThread.h>
 40
 41#import <pal/cocoa/AVFoundationSoftLink.h>
 42
 43using namespace WebCore;
 44
 45@interface WebAVSampleBufferStatusChangeListener : NSObject {
 46 LocalSampleBufferDisplayLayer* _parent;
 47}
 48
 49- (id)initWithParent:(LocalSampleBufferDisplayLayer*)callback;
 50- (void)invalidate;
 51- (void)beginObservingLayers;
 52- (void)stopObservingLayers;
 53@end
 54
 55@implementation WebAVSampleBufferStatusChangeListener
 56
 57- (id)initWithParent:(LocalSampleBufferDisplayLayer*)parent
 58{
 59 if (!(self = [super init]))
 60 return nil;
 61
 62 _parent = parent;
 63
 64 return self;
 65}
 66
 67- (void)dealloc
 68{
 69 [self invalidate];
 70 [super dealloc];
 71}
 72
 73- (void)invalidate
 74{
 75 [self stopObservingLayers];
 76 _parent = nullptr;
 77}
 78
 79- (void)beginObservingLayers
 80{
 81 ASSERT(_parent);
 82 ASSERT(_parent->displayLayer());
 83 ASSERT(_parent->rootLayer());
 84
 85 [_parent->displayLayer() addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
 86 [_parent->displayLayer() addObserver:self forKeyPath:@"error" options:NSKeyValueObservingOptionNew context:nil];
 87 [_parent->rootLayer() addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:nil];
 88}
 89
 90- (void)stopObservingLayers
 91{
 92 if (!_parent)
 93 return;
 94
 95 if (_parent->displayLayer()) {
 96 [_parent->displayLayer() removeObserver:self forKeyPath:@"status"];
 97 [_parent->displayLayer() removeObserver:self forKeyPath:@"error"];
 98 }
 99 if (_parent->rootLayer())
 100 [_parent->rootLayer() removeObserver:self forKeyPath:@"bounds"];
 101}
 102
 103- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 104{
 105 UNUSED_PARAM(context);
 106 UNUSED_PARAM(keyPath);
 107 ASSERT(_parent);
 108
 109 if (!_parent)
 110 return;
 111
 112 if ([object isKindOfClass:PAL::getAVSampleBufferDisplayLayerClass()]) {
 113 RetainPtr<AVSampleBufferDisplayLayer> layer = (AVSampleBufferDisplayLayer *)object;
 114 ASSERT(layer.get() == _parent->displayLayer());
 115
 116 if ([keyPath isEqualToString:@"status"]) {
 117 RetainPtr<NSNumber> status = [change valueForKey:NSKeyValueChangeNewKey];
 118 callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self), layer = WTFMove(layer), status = WTFMove(status)] {
 119 if (!protectedSelf->_parent)
 120 return;
 121
 122 protectedSelf->_parent->layerStatusDidChange();
 123 });
 124 return;
 125 }
 126
 127 if ([keyPath isEqualToString:@"error"]) {
 128 RetainPtr<NSNumber> status = [change valueForKey:NSKeyValueChangeNewKey];
 129 callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self), layer = WTFMove(layer), status = WTFMove(status)] {
 130 if (!protectedSelf->_parent)
 131 return;
 132
 133 protectedSelf->_parent->layerErrorDidChange();
 134 });
 135 return;
 136 }
 137 }
 138
 139 if ([[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
 140 return;
 141
 142 if ((CALayer *)object == _parent->rootLayer()) {
 143 if ([keyPath isEqualToString:@"bounds"]) {
 144 if (!_parent)
 145 return;
 146
 147 if (isMainThread()) {
 148 _parent->rootLayerBoundsDidChange();
 149 return;
 150 }
 151
 152 callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self)] {
 153 if (!protectedSelf->_parent)
 154 return;
 155
 156 protectedSelf->_parent->rootLayerBoundsDidChange();
 157 });
 158 }
 159 }
 160
 161}
 162@end
 163
 164namespace WebCore {
 165
 166static void runWithoutAnimations(const WTF::Function<void()>& function)
 167{
 168 [CATransaction begin];
 169 [CATransaction setAnimationDuration:0];
 170 [CATransaction setDisableActions:YES];
 171 function();
 172 [CATransaction commit];
 173}
 174
 175std::unique_ptr<SampleBufferDisplayLayer> LocalSampleBufferDisplayLayer::create(Client& client, bool hideRootLayer, IntSize size)
 176{
 177 auto sampleBufferDisplayLayer = adoptNS([PAL::allocAVSampleBufferDisplayLayerInstance() init]);
 178 if (!sampleBufferDisplayLayer)
 179 return nullptr;
 180
 181 return makeUnique<LocalSampleBufferDisplayLayer>(WTFMove(sampleBufferDisplayLayer), client, hideRootLayer, size);
 182}
 183
 184LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer(RetainPtr<AVSampleBufferDisplayLayer>&& sampleBufferDisplayLayer, Client& client, bool hideRootLayer, IntSize size)
 185 : SampleBufferDisplayLayer(client)
 186 , m_statusChangeListener(adoptNS([[WebAVSampleBufferStatusChangeListener alloc] initWithParent:this]))
 187 , m_sampleBufferDisplayLayer(WTFMove(sampleBufferDisplayLayer))
 188{
 189 m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
 190 m_sampleBufferDisplayLayer.get().anchorPoint = { .5, .5 };
 191 m_sampleBufferDisplayLayer.get().needsDisplayOnBoundsChange = YES;
 192 m_sampleBufferDisplayLayer.get().videoGravity = AVLayerVideoGravityResizeAspectFill;
 193
 194 m_rootLayer = adoptNS([[CALayer alloc] init]);
 195 m_rootLayer.get().hidden = hideRootLayer;
 196
 197 m_rootLayer.get().backgroundColor = cachedCGColor(Color::black);
 198 m_rootLayer.get().needsDisplayOnBoundsChange = YES;
 199
 200 m_rootLayer.get().bounds = CGRectMake(0, 0, size.width(), size.height());
 201
 202 [m_statusChangeListener beginObservingLayers];
 203
 204 [m_rootLayer addSublayer:m_sampleBufferDisplayLayer.get()];
 205
 206#ifndef NDEBUG
 207 [m_sampleBufferDisplayLayer setName:@"LocalSampleBufferDisplayLayer AVSampleBufferDisplayLayer"];
 208 [m_rootLayer setName:@"LocalSampleBufferDisplayLayer AVSampleBufferDisplayLayer parent"];
 209#endif
 210}
 211
 212LocalSampleBufferDisplayLayer::~LocalSampleBufferDisplayLayer()
 213{
 214 [m_statusChangeListener stopObservingLayers];
 215
 216 m_pendingVideoSampleQueue.clear();
 217
 218 [m_sampleBufferDisplayLayer stopRequestingMediaData];
 219 [m_sampleBufferDisplayLayer flush];
 220 m_sampleBufferDisplayLayer = nullptr;
 221
 222 m_rootLayer = nullptr;
 223}
 224
 225void LocalSampleBufferDisplayLayer::layerStatusDidChange()
 226{
 227 ASSERT(isMainThread());
 228 if (m_sampleBufferDisplayLayer.get().status != AVQueuedSampleBufferRenderingStatusRendering)
 229 return;
 230 if (!m_client)
 231 return;
 232 m_client->sampleBufferDisplayLayerStatusDidChange(*this);
 233}
 234
 235void LocalSampleBufferDisplayLayer::layerErrorDidChange()
 236{
 237 ASSERT(isMainThread());
 238 // FIXME: Log error.
 239}
 240
 241void LocalSampleBufferDisplayLayer::rootLayerBoundsDidChange()
 242{
 243 ASSERT(isMainThread());
 244 if (!m_client)
 245 return;
 246 m_client->sampleBufferDisplayLayerBoundsDidChange(*this);
 247}
 248
 249PlatformLayer* LocalSampleBufferDisplayLayer::displayLayer()
 250{
 251 return m_sampleBufferDisplayLayer.get();
 252}
 253
 254PlatformLayer* LocalSampleBufferDisplayLayer::rootLayer()
 255{
 256 return m_rootLayer.get();
 257}
 258
 259bool LocalSampleBufferDisplayLayer::didFail() const
 260{
 261 return [m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed;
 262}
 263
 264void LocalSampleBufferDisplayLayer::updateDisplayMode(bool hideDisplayLayer, bool hideRootLayer)
 265{
 266 if (m_rootLayer.get().hidden == hideRootLayer && m_sampleBufferDisplayLayer.get().hidden == hideDisplayLayer)
 267 return;
 268
 269 runWithoutAnimations([&] {
 270 m_sampleBufferDisplayLayer.get().hidden = hideDisplayLayer;
 271 m_rootLayer.get().hidden = hideRootLayer;
 272 });
 273}
 274
 275CGRect LocalSampleBufferDisplayLayer::bounds() const
 276{
 277 return m_rootLayer.get().bounds;
 278}
 279
 280void LocalSampleBufferDisplayLayer::updateAffineTransform(CGAffineTransform transform)
 281{
 282 runWithoutAnimations([&] {
 283 m_sampleBufferDisplayLayer.get().affineTransform = transform;
 284 });
 285}
 286
 287void LocalSampleBufferDisplayLayer::updateBoundsAndPosition(CGRect videoBounds, CGPoint position)
 288{
 289 runWithoutAnimations([&] {
 290 m_sampleBufferDisplayLayer.get().bounds = videoBounds;
 291 m_sampleBufferDisplayLayer.get().position = position;
 292 });
 293}
 294
 295void LocalSampleBufferDisplayLayer::flush()
 296{
 297 [m_sampleBufferDisplayLayer flush];
 298}
 299
 300void LocalSampleBufferDisplayLayer::flushAndRemoveImage()
 301{
 302 [m_sampleBufferDisplayLayer flushAndRemoveImage];
 303}
 304
 305void LocalSampleBufferDisplayLayer::enqueueSample(MediaSample& sample)
 306{
 307 if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
 308 addSampleToPendingQueue(sample);
 309 requestNotificationWhenReadyForVideoData();
 310 return;
 311 }
 312
 313 [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
 314}
 315
 316void LocalSampleBufferDisplayLayer::removeOldSamplesFromPendingQueue()
 317{
 318 if (m_pendingVideoSampleQueue.isEmpty() || !m_client)
 319 return;
 320
 321 auto decodeTime = m_pendingVideoSampleQueue.first()->decodeTime();
 322 if (!decodeTime.isValid() || decodeTime < MediaTime::zeroTime()) {
 323 while (m_pendingVideoSampleQueue.size() > 5)
 324 m_pendingVideoSampleQueue.removeFirst();
 325
 326 return;
 327 }
 328
 329 MediaTime now = m_client->streamTime();
 330 while (!m_pendingVideoSampleQueue.isEmpty()) {
 331 if (m_pendingVideoSampleQueue.first()->decodeTime() > now)
 332 break;
 333 m_pendingVideoSampleQueue.removeFirst();
 334 }
 335}
 336
 337void LocalSampleBufferDisplayLayer::addSampleToPendingQueue(MediaSample& sample)
 338{
 339 removeOldSamplesFromPendingQueue();
 340 m_pendingVideoSampleQueue.append(sample);
 341}
 342
 343void LocalSampleBufferDisplayLayer::clearEnqueuedSamples()
 344{
 345 m_pendingVideoSampleQueue.clear();
 346}
 347
 348void LocalSampleBufferDisplayLayer::requestNotificationWhenReadyForVideoData()
 349{
 350 auto weakThis = makeWeakPtr(*this);
 351 [m_sampleBufferDisplayLayer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^{
 352 if (!weakThis)
 353 return;
 354
 355 [m_sampleBufferDisplayLayer stopRequestingMediaData];
 356
 357 while (!m_pendingVideoSampleQueue.isEmpty()) {
 358 if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
 359 requestNotificationWhenReadyForVideoData();
 360 return;
 361 }
 362
 363 // FIXME: we should reenqueue in client.
 364 auto sample = m_pendingVideoSampleQueue.takeFirst();
 365 enqueueSample(sample.get());
 366 }
 367 }];
 368}
 369
 370}
 371
 372#endif

Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h

11/*
2  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
 2 * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2323 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
26 #ifndef MediaPlayerPrivateMediaStreamAVFObjC_h
27 #define MediaPlayerPrivateMediaStreamAVFObjC_h
 26#pragma once
2827
2928#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
3029
3130#include "MediaPlayerPrivate.h"
3231#include "MediaSample.h"
3332#include "MediaStreamPrivate.h"
34 #include <CoreGraphics/CGAffineTransform.h>
 33#include "SampleBufferDisplayLayer.h"
3534#include <wtf/Deque.h>
36 #include <wtf/Function.h>
 35#include <wtf/Forward.h>
3736#include <wtf/LoggerHelper.h>
38 #include <wtf/MediaTime.h>
39 #include <wtf/WeakPtr.h>
4037
41 OBJC_CLASS AVSampleBufferAudioRenderer;
4238OBJC_CLASS AVSampleBufferDisplayLayer;
43 OBJC_CLASS AVSampleBufferRenderSynchronizer;
44 OBJC_CLASS AVStreamSession;
45 OBJC_CLASS NSNumber;
4639OBJC_CLASS WebAVSampleBufferStatusChangeListener;
4740
4841namespace PAL {

@@class PixelBufferConformerCV;
5851class VideoFullscreenLayerManagerObjC;
5952class VideoTrackPrivateMediaStream;
6053
61 class MediaPlayerPrivateMediaStreamAVFObjC final : public CanMakeWeakPtr<MediaPlayerPrivateMediaStreamAVFObjC>, public MediaPlayerPrivateInterface, private MediaStreamPrivate::Observer, private MediaStreamTrackPrivate::Observer
 54class MediaPlayerPrivateMediaStreamAVFObjC final : public MediaPlayerPrivateInterface, private MediaStreamPrivate::Observer, private MediaStreamTrackPrivate::Observer, public SampleBufferDisplayLayer::Client
6255#if !RELEASE_LOG_DISABLED
6356 , private LoggerHelper
6457#endif

@@public:
8275 void ensureLayers();
8376 void destroyLayers();
8477
85  void layerStatusDidChange(AVSampleBufferDisplayLayer*);
86  void layerErrorDidChange(AVSampleBufferDisplayLayer*);
87  void backgroundLayerBoundsChanged();
88 
89  PlatformLayer* displayLayer();
90  PlatformLayer* backgroundLayer();
91 
9278#if !RELEASE_LOG_DISABLED
9379 const Logger& logger() const final { return m_logger.get(); }
9480 const char* logClassName() const override { return "MediaPlayerPrivateMediaStreamAVFObjC"; }

@@private:
144130
145131 void flushRenderers();
146132
147  using PendingSampleQueue = Deque<Ref<MediaSample>>;
148  void addSampleToPendingQueue(PendingSampleQueue&, MediaSample&);
149  void removeOldSamplesFromPendingQueue(PendingSampleQueue&);
150 
151133 MediaTime calculateTimelineOffset(const MediaSample&, double);
152134
153135 void enqueueVideoSample(MediaStreamTrackPrivate&, MediaSample&);

@@private:
219201 void setVideoFullscreenLayer(PlatformLayer*, WTF::Function<void()>&& completionHandler) override;
220202 void setVideoFullscreenFrame(FloatRect) override;
221203
222  MediaTime streamTime() const;
 204 MediaTime streamTime() const final;
223205
224206 AudioSourceProvider* audioSourceProvider() final;
225207

@@private:
227209
228210 void applicationDidBecomeActive() final;
229211
230  bool hideBackgroundLayer() const { return (!m_activeVideoTrack || m_waitingForFirstImage) && m_displayMode != PaintItBlack; }
 212 bool hideRootLayer() const { return (!m_activeVideoTrack || m_waitingForFirstImage) && m_displayMode != PaintItBlack; }
231213
232214 MediaPlayer* m_player { nullptr };
233215 RefPtr<MediaStreamPrivate> m_mediaStreamPrivate;
234216 RefPtr<MediaStreamTrackPrivate> m_activeVideoTrack;
235  RetainPtr<WebAVSampleBufferStatusChangeListener> m_statusChangeListener;
236  RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
237  RetainPtr<PlatformLayer> m_backgroundLayer;
238217 std::unique_ptr<PAL::Clock> m_clock;
239218
240219 MediaTime m_pausedTime;

@@private:
251230
252231 HashMap<String, RefPtr<AudioTrackPrivateMediaStreamCocoa>> m_audioTrackMap;
253232 HashMap<String, RefPtr<VideoTrackPrivateMediaStream>> m_videoTrackMap;
254  PendingSampleQueue m_pendingVideoSampleQueue;
255233
256234 MediaPlayer::NetworkState m_networkState { MediaPlayer::NetworkState::Empty };
257235 MediaPlayer::ReadyState m_readyState { MediaPlayer::ReadyState::HaveNothing };

@@private:
261239 PlaybackState m_playbackState { PlaybackState::None };
262240 MediaSample::VideoRotation m_videoRotation { MediaSample::VideoRotation::None };
263241 CGAffineTransform m_videoTransform;
 242 std::unique_ptr<SampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
264243 std::unique_ptr<VideoFullscreenLayerManagerObjC> m_videoFullscreenLayerManager;
265244
 245 // SampleBufferDisplayLayer::Client
 246 void sampleBufferDisplayLayerStatusDidChange(SampleBufferDisplayLayer&) final;
 247 void sampleBufferDisplayLayerBoundsDidChange(SampleBufferDisplayLayer&) final;
 248
266249#if !RELEASE_LOG_DISABLED
267250 Ref<const Logger> m_logger;
268251 const void* m_logIdentifier;

@@private:
283266}
284267
285268#endif // ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
286 
287 #endif // MediaPlayerPrivateMediaStreamAVFObjC_h

Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm

11/*
2  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
 2 * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

3131#import "AudioTrackPrivateMediaStreamCocoa.h"
3232#import "GraphicsContextCG.h"
3333#import "Logging.h"
 34#import "LocalSampleBufferDisplayLayer.h"
3435#import "MediaStreamPrivate.h"
3536#import "PixelBufferConformerCV.h"
3637#import "VideoFullscreenLayerManagerObjC.h"
3738#import "VideoTrackPrivateMediaStream.h"
38 #import <AVFoundation/AVSampleBufferDisplayLayer.h>
39 #import <QuartzCore/CALayer.h>
40 #import <QuartzCore/CATransaction.h>
 39#import <CoreGraphics/CGAffineTransform.h>
4140#import <objc_runtime.h>
4241#import <pal/avfoundation/MediaTimeAVFoundation.h>
4342#import <pal/spi/mac/AVFoundationSPI.h>
4443#import <pal/system/Clock.h>
45 #import <wtf/Function.h>
4644#import <wtf/MainThread.h>
4745#import <wtf/NeverDestroyed.h>
4846

5048#import <pal/cf/CoreMediaSoftLink.h>
5149#import <pal/cocoa/AVFoundationSoftLink.h>
5250
53 using namespace WebCore;
54 
55 @interface WebAVSampleBufferStatusChangeListener : NSObject {
56  MediaPlayerPrivateMediaStreamAVFObjC* _parent;
57 }
58 
59 - (id)initWithParent:(MediaPlayerPrivateMediaStreamAVFObjC*)callback;
60 - (void)invalidate;
61 - (void)beginObservingLayers;
62 - (void)stopObservingLayers;
63 @end
64 
65 @implementation WebAVSampleBufferStatusChangeListener
66 
67 - (id)initWithParent:(MediaPlayerPrivateMediaStreamAVFObjC*)parent
68 {
69  if (!(self = [super init]))
70  return nil;
71 
72  _parent = parent;
73 
74  return self;
75 }
76 
77 - (void)dealloc
78 {
79  [self invalidate];
80  [super dealloc];
81 }
82 
83 - (void)invalidate
84 {
85  [self stopObservingLayers];
86  _parent = nullptr;
87 }
88 
89 - (void)beginObservingLayers
90 {
91  ASSERT(_parent);
92  ASSERT(_parent->displayLayer());
93  ASSERT(_parent->backgroundLayer());
94 
95  [_parent->displayLayer() addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
96  [_parent->displayLayer() addObserver:self forKeyPath:@"error" options:NSKeyValueObservingOptionNew context:nil];
97  [_parent->backgroundLayer() addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:nil];
98 }
99 
100 - (void)stopObservingLayers
101 {
102  if (!_parent)
103  return;
104 
105  if (_parent->displayLayer()) {
106  [_parent->displayLayer() removeObserver:self forKeyPath:@"status"];
107  [_parent->displayLayer() removeObserver:self forKeyPath:@"error"];
108  }
109  if (_parent->backgroundLayer())
110  [_parent->backgroundLayer() removeObserver:self forKeyPath:@"bounds"];
111 }
112 
113 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
114 {
115  UNUSED_PARAM(context);
116  UNUSED_PARAM(keyPath);
117  ASSERT(_parent);
118 
119  if (!_parent)
120  return;
121 
122  if ([object isKindOfClass:PAL::getAVSampleBufferDisplayLayerClass()]) {
123  RetainPtr<AVSampleBufferDisplayLayer> layer = (AVSampleBufferDisplayLayer *)object;
124  ASSERT(layer.get() == _parent->displayLayer());
125 
126  if ([keyPath isEqualToString:@"status"]) {
127  RetainPtr<NSNumber> status = [change valueForKey:NSKeyValueChangeNewKey];
128  callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self), layer = WTFMove(layer), status = WTFMove(status)] {
129  if (!protectedSelf->_parent)
130  return;
131 
132  protectedSelf->_parent->layerStatusDidChange(layer.get());
133  });
134  return;
135  }
136 
137  if ([keyPath isEqualToString:@"error"]) {
138  RetainPtr<NSNumber> status = [change valueForKey:NSKeyValueChangeNewKey];
139  callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self), layer = WTFMove(layer), status = WTFMove(status)] {
140  if (!protectedSelf->_parent)
141  return;
142 
143  protectedSelf->_parent->layerErrorDidChange(layer.get());
144  });
145  return;
146  }
147  }
148 
149  if ([[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
150  return;
151 
152  if ((CALayer *)object == _parent->backgroundLayer()) {
153  if ([keyPath isEqualToString:@"bounds"]) {
154  if (!_parent)
155  return;
156 
157  if (isMainThread()) {
158  _parent->backgroundLayerBoundsChanged();
159  return;
160  }
161 
162  callOnMainThread([protectedSelf = RetainPtr<WebAVSampleBufferStatusChangeListener>(self)] {
163  if (!protectedSelf->_parent)
164  return;
165 
166  protectedSelf->_parent->backgroundLayerBoundsChanged();
167  });
168  }
169  }
170 
171 }
172 @end
173 
17451namespace WebCore {
17552using namespace PAL;
17653

@@static const double rendererLatency = 0.02;
18158
18259MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC(MediaPlayer* player)
18360 : m_player(player)
184  , m_statusChangeListener(adoptNS([[WebAVSampleBufferStatusChangeListener alloc] initWithParent:this]))
18561 , m_clock(PAL::Clock::create())
18662 , m_videoFullscreenLayerManager(makeUnique<VideoFullscreenLayerManagerObjC>())
18763#if !RELEASE_LOG_DISABLED

@@MediaPlayerPrivateMediaStreamAVFObjC::~MediaPlayerPrivateMediaStreamAVFObjC()
19672{
19773 INFO_LOG(LOGIDENTIFIER);
19874
199  [m_statusChangeListener invalidate];
200 
20175 for (const auto& track : m_audioTrackMap.values())
20276 track->pause();
20377

@@MediaPlayer::SupportsType MediaPlayerPrivateMediaStreamAVFObjC::supportsType(con
267141#pragma mark -
268142#pragma mark AVSampleBuffer Methods
269143
270 void MediaPlayerPrivateMediaStreamAVFObjC::removeOldSamplesFromPendingQueue(PendingSampleQueue& queue)
271 {
272  if (queue.isEmpty())
273  return;
274 
275  auto decodeTime = queue.first()->decodeTime();
276  if (!decodeTime.isValid() || decodeTime < MediaTime::zeroTime()) {
277  while (queue.size() > 5)
278  queue.removeFirst();
279 
280  return;
281  }
282 
283  MediaTime now = streamTime();
284  while (!queue.isEmpty()) {
285  if (queue.first()->decodeTime() > now)
286  break;
287  queue.removeFirst();
288  }
289 }
290 
291 void MediaPlayerPrivateMediaStreamAVFObjC::addSampleToPendingQueue(PendingSampleQueue& queue, MediaSample& sample)
292 {
293  removeOldSamplesFromPendingQueue(queue);
294  queue.append(sample);
295 }
296 
297144MediaTime MediaPlayerPrivateMediaStreamAVFObjC::calculateTimelineOffset(const MediaSample& sample, double latency)
298145{
299146 MediaTime sampleTime = sample.outputPresentationTime();

@@CGAffineTransform MediaPlayerPrivateMediaStreamAVFObjC::videoTransformationMatri
328175 return m_videoTransform;
329176}
330177
331 static void runWithoutAnimations(const WTF::Function<void()>& function)
332 {
333  [CATransaction begin];
334  [CATransaction setAnimationDuration:0];
335  [CATransaction setDisableActions:YES];
336  function();
337  [CATransaction commit];
338 }
339 
340178void MediaPlayerPrivateMediaStreamAVFObjC::enqueueCorrectedVideoSample(MediaSample& sample)
341179{
342180 if (m_sampleBufferDisplayLayer) {
343  if ([m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed)
 181 if (m_sampleBufferDisplayLayer->didFail())
344182 return;
345183
346184 if (sample.videoRotation() != m_videoRotation || sample.videoMirrored() != m_videoMirrored) {
347185 m_videoRotation = sample.videoRotation();
348186 m_videoMirrored = sample.videoMirrored();
349  runWithoutAnimations([this, &sample] {
350  m_sampleBufferDisplayLayer.get().affineTransform = videoTransformationMatrix(sample, true);
351  updateDisplayLayer();
352  });
 187 m_sampleBufferDisplayLayer->updateAffineTransform(videoTransformationMatrix(sample, true));
 188 updateDisplayLayer();
353189 }
354 
355  if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
356  addSampleToPendingQueue(m_pendingVideoSampleQueue, sample);
357  requestNotificationWhenReadyForVideoData();
358  return;
359  }
360 
361  [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
 190 m_sampleBufferDisplayLayer->enqueueSample(sample);
362191 }
363192
364193 if (!m_hasEverEnqueuedVideoFrame) {

@@void MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSample(MediaStreamTrackPr
413242 }
414243}
415244
416 void MediaPlayerPrivateMediaStreamAVFObjC::requestNotificationWhenReadyForVideoData()
417 {
418  auto weakThis = makeWeakPtr(*this);
419  [m_sampleBufferDisplayLayer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^ {
420  if (!weakThis)
421  return;
422 
423  [m_sampleBufferDisplayLayer stopRequestingMediaData];
424 
425  if (!m_activeVideoTrack) {
426  m_pendingVideoSampleQueue.clear();
427  return;
428  }
429 
430  while (!m_pendingVideoSampleQueue.isEmpty()) {
431  if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
432  requestNotificationWhenReadyForVideoData();
433  return;
434  }
435 
436  auto sample = m_pendingVideoSampleQueue.takeFirst();
437  enqueueVideoSample(*m_activeVideoTrack.get(), sample.get());
438  }
439  }];
440 }
441 
442245AudioSourceProvider* MediaPlayerPrivateMediaStreamAVFObjC::audioSourceProvider()
443246{
444247 // FIXME: This should return a mix of all audio tracks - https://bugs.webkit.org/show_bug.cgi?id=160305
445248 return nullptr;
446249}
447250
448 void MediaPlayerPrivateMediaStreamAVFObjC::layerErrorDidChange(AVSampleBufferDisplayLayer* layer)
 251void MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerStatusDidChange(SampleBufferDisplayLayer& layer)
449252{
 253 ASSERT(&layer == m_sampleBufferDisplayLayer.get());
450254 UNUSED_PARAM(layer);
451  ERROR_LOG(LOGIDENTIFIER, "error = ", [[layer.error localizedDescription] UTF8String]);
452 }
453 
454 void MediaPlayerPrivateMediaStreamAVFObjC::layerStatusDidChange(AVSampleBufferDisplayLayer* layer)
455 {
456  ALWAYS_LOG(LOGIDENTIFIER, "status = ", (int)layer.status);
457 
458  if (layer.status != AVQueuedSampleBufferRenderingStatusRendering)
459  return;
460  if (!m_sampleBufferDisplayLayer || !m_activeVideoTrack || layer != m_sampleBufferDisplayLayer)
 255 if (!m_activeVideoTrack)
461256 return;
462257
463  auto track = m_videoTrackMap.get(m_activeVideoTrack->id());
464  if (track)
 258 if (auto track = m_videoTrackMap.get(m_activeVideoTrack->id()))
465259 track->setTimelineOffset(MediaTime::invalidTime());
466260}
467261
468262void MediaPlayerPrivateMediaStreamAVFObjC::applicationDidBecomeActive()
469263{
470  if (m_sampleBufferDisplayLayer && [m_sampleBufferDisplayLayer status] == AVQueuedSampleBufferRenderingStatusFailed) {
 264 if (m_sampleBufferDisplayLayer && m_sampleBufferDisplayLayer->didFail()) {
471265 flushRenderers();
472266 if (m_imagePainter.mediaSample)
473267 enqueueCorrectedVideoSample(*m_imagePainter.mediaSample);

@@void MediaPlayerPrivateMediaStreamAVFObjC::applicationDidBecomeActive()
478272void MediaPlayerPrivateMediaStreamAVFObjC::flushRenderers()
479273{
480274 if (m_sampleBufferDisplayLayer)
481  [m_sampleBufferDisplayLayer flush];
 275 m_sampleBufferDisplayLayer->flush();
482276}
483277
484278void MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers()

@@void MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers()
489283 if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->activeVideoTrack() || !m_mediaStreamPrivate->activeVideoTrack()->enabled())
490284 return;
491285
492  m_sampleBufferDisplayLayer = adoptNS([PAL::allocAVSampleBufferDisplayLayerInstance() init]);
 286 auto size = snappedIntRect(m_player->playerContentBoxRect()).size();
 287 m_sampleBufferDisplayLayer = LocalSampleBufferDisplayLayer::create(*this, hideRootLayer(), size);
 288
493289 if (!m_sampleBufferDisplayLayer) {
494  ERROR_LOG(LOGIDENTIFIER, "+[AVSampleBufferDisplayLayer alloc] failed.");
 290 ERROR_LOG(LOGIDENTIFIER, "Creating the SampleBufferDisplayLayer failed.");
495291 return;
496292 }
497293
498  m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
499  m_sampleBufferDisplayLayer.get().anchorPoint = { .5, .5 };
500  m_sampleBufferDisplayLayer.get().needsDisplayOnBoundsChange = YES;
501  m_sampleBufferDisplayLayer.get().videoGravity = AVLayerVideoGravityResizeAspectFill;
502 
503  m_backgroundLayer = adoptNS([[CALayer alloc] init]);
504  m_backgroundLayer.get().hidden = hideBackgroundLayer();
505 
506  m_backgroundLayer.get().backgroundColor = cachedCGColor(Color::black);
507  m_backgroundLayer.get().needsDisplayOnBoundsChange = YES;
508 
509  auto size = snappedIntRect(m_player->playerContentBoxRect()).size();
510  m_backgroundLayer.get().bounds = CGRectMake(0, 0, size.width(), size.height());
511 
512  [m_statusChangeListener beginObservingLayers];
513 
514  [m_backgroundLayer addSublayer:m_sampleBufferDisplayLayer.get()];
515 
516 #ifndef NDEBUG
517  [m_sampleBufferDisplayLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer"];
518  [m_backgroundLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer parent"];
519 #endif
520 
521294 updateRenderingMode();
522295 updateDisplayLayer();
523296
524  m_videoFullscreenLayerManager->setVideoLayer(m_backgroundLayer.get(), size);
 297 m_videoFullscreenLayerManager->setVideoLayer(m_sampleBufferDisplayLayer->rootLayer(), size);
525298}
526299
527300void MediaPlayerPrivateMediaStreamAVFObjC::destroyLayers()
528301{
529  [m_statusChangeListener stopObservingLayers];
530  if (m_sampleBufferDisplayLayer) {
531  m_pendingVideoSampleQueue.clear();
532  [m_sampleBufferDisplayLayer stopRequestingMediaData];
533  [m_sampleBufferDisplayLayer flush];
 302 if (m_sampleBufferDisplayLayer)
534303 m_sampleBufferDisplayLayer = nullptr;
535  }
536  m_backgroundLayer = nullptr;
537304
538305 updateRenderingMode();
539306

@@void MediaPlayerPrivateMediaStreamAVFObjC::prepareToPlay()
600367
601368PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
602369{
603  if (!m_backgroundLayer || m_displayMode == None)
 370 if (!m_sampleBufferDisplayLayer || !m_sampleBufferDisplayLayer->rootLayer() || m_displayMode == None)
604371 return nullptr;
605372
606373 return m_videoFullscreenLayerManager->videoInlineLayer();
607374}
608375
609 PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::displayLayer()
610 {
611  return m_sampleBufferDisplayLayer.get();
612 }
613 
614 PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::backgroundLayer()
615 {
616  return m_backgroundLayer.get();
617 }
618 
619376MediaPlayerPrivateMediaStreamAVFObjC::DisplayMode MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode() const
620377{
621378 if (m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)

@@bool MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayMode()
651408 INFO_LOG(LOGIDENTIFIER, "updated to ", static_cast<int>(displayMode));
652409 m_displayMode = displayMode;
653410
654  auto hidden = m_displayMode < PausedImage;
655  if (m_sampleBufferDisplayLayer && m_sampleBufferDisplayLayer.get().hidden != hidden) {
656  runWithoutAnimations([this, hidden] {
657  m_sampleBufferDisplayLayer.get().hidden = hidden;
658  });
659  }
660  hidden = hideBackgroundLayer();
661  if (m_backgroundLayer && m_backgroundLayer.get().hidden != hidden) {
662  runWithoutAnimations([this, hidden] {
663  m_backgroundLayer.get().hidden = hidden;
664  });
665  }
 411 if (m_sampleBufferDisplayLayer)
 412 m_sampleBufferDisplayLayer->updateDisplayMode(m_displayMode < PausedImage, hideRootLayer());
666413
667414 return true;
668415}

@@void MediaPlayerPrivateMediaStreamAVFObjC::checkSelectedVideoTrack()
1021768 m_waitingForFirstImage = true;
1022769 }
1023770 ensureLayers();
1024  m_sampleBufferDisplayLayer.get().hidden = hideVideoLayer || m_displayMode < PausedImage;
1025  m_backgroundLayer.get().hidden = hideBackgroundLayer();
 771 if (m_sampleBufferDisplayLayer) {
 772 if (!m_activeVideoTrack)
 773 m_sampleBufferDisplayLayer->clearEnqueuedSamples();
 774 m_sampleBufferDisplayLayer->updateDisplayMode(hideVideoLayer || m_displayMode < PausedImage, hideRootLayer());
 775 }
1026776
1027777 m_pendingSelectedTrackCheck = false;
1028778 updateDisplayMode();

@@void MediaPlayerPrivateMediaStreamAVFObjC::setNetworkState(MediaPlayer::NetworkS
1171921
1172922void MediaPlayerPrivateMediaStreamAVFObjC::setBufferingPolicy(MediaPlayer::BufferingPolicy policy)
1173923{
1174  if (policy != MediaPlayer::BufferingPolicy::Default)
1175  [m_sampleBufferDisplayLayer flushAndRemoveImage];
 924 if (policy != MediaPlayer::BufferingPolicy::Default && m_sampleBufferDisplayLayer)
 925 m_sampleBufferDisplayLayer->flushAndRemoveImage();
1176926}
1177927
1178928void MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask(Function<void ()>&& function)

@@void MediaPlayerPrivateMediaStreamAVFObjC::CurrentFramePainter::reset()
1195945
1196946void MediaPlayerPrivateMediaStreamAVFObjC::updateDisplayLayer()
1197947{
1198  if (!m_backgroundLayer || !m_sampleBufferDisplayLayer)
 948 if (!m_sampleBufferDisplayLayer)
1199949 return;
1200950
1201  auto backgroundBounds = m_backgroundLayer.get().bounds;
1202  auto videoBounds = backgroundBounds;
 951 auto bounds = m_sampleBufferDisplayLayer->bounds();
 952 auto videoBounds = bounds;
1203953 if (m_videoRotation == MediaSample::VideoRotation::Right || m_videoRotation == MediaSample::VideoRotation::Left)
1204954 std::swap(videoBounds.size.width, videoBounds.size.height);
1205955
1206  m_sampleBufferDisplayLayer.get().bounds = videoBounds;
1207  m_sampleBufferDisplayLayer.get().position = { backgroundBounds.size.width / 2, backgroundBounds.size.height / 2};
 956 m_sampleBufferDisplayLayer->updateBoundsAndPosition(videoBounds, { bounds.size.width / 2, bounds.size.height / 2});
1208957}
1209958
1210 void MediaPlayerPrivateMediaStreamAVFObjC::backgroundLayerBoundsChanged()
 959void MediaPlayerPrivateMediaStreamAVFObjC::sampleBufferDisplayLayerBoundsDidChange(SampleBufferDisplayLayer&)
1211960{
1212  runWithoutAnimations([this] {
1213  updateDisplayLayer();
1214  });
 961 updateDisplayLayer();
1215962}
1216963
1217964#if !RELEASE_LOG_DISABLED