Bug Summary

File:Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm
Warning:line 815, column 45
Call argument is uncounted and unsafe

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple arm64-apple-macosx15.5.0 -O2 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name MediaPlayerPrivateMediaSourceAVFObjC.mm -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=osx -analyzer-checker=security.insecureAPI.decodeValueOfObjCType -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -target-sdk-version=15.5 -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -fno-modulemap-allow-subdirectory-search -fdefine-target-os-macros -enable-tlsdesc -target-cpu apple-m1 -target-feature +v8.4a -target-feature +aes -target-feature +altnzcv -target-feature +ccdp -target-feature +ccpp -target-feature +complxnum -target-feature +crc -target-feature +dotprod -target-feature +flagm -target-feature +fp-armv8 -target-feature +fp16fml -target-feature +fptoint -target-feature +fullfp16 -target-feature +jsconv -target-feature +lse -target-feature +neon -target-feature +pauth -target-feature +perfmon -target-feature +predres -target-feature +ras -target-feature +rcpc -target-feature +rdm -target-feature +sb -target-feature +sha2 -target-feature +sha3 -target-feature +specrestrict -target-feature +ssbs -target-abi darwinpcs -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone -dwarf-version=5 -debugger-tuning=lldb -fdebug-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -target-linker-version 1167.5 -fcoverage-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -resource-dir /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/llvm-project/build/lib/clang/21 -dependency-file /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/MediaPlayerPrivateMediaSourceAVFObjC.d -skip-unused-modulemap-deps -MT dependencies -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk -iquote /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-generated-files.hmap -iquote /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-project-headers.hmap -isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore/PAL/ThirdParty/dav1d/include -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/PrivateFrameworks -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks -include-pch /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PrecompiledHeaders/SharedPrecompiledHeaders/8691176753837006916/WebCorePrefix.h.gch -D _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D CLANG_WEBKIT_BRANCH=1 -D NDEBUG -D BUILDING_WEBKIT -D GL_SILENCE_DEPRECATION=1 -D GLES_SILENCE_DEPRECATION=1 -D OBJC_OLD_DISPATCH_PROTOTYPES=0 -D __clang_analyzer__ -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-own-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-all-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/include -I PAL -I ForwardingHeaders -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/libxslt -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/libxml2 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebCore -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/WebKitAdditions -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/WebKitAdditions -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/macosx15.0-additions.sdk/usr/local/include -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/webrtc -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/webrtc -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/webm -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/webm -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/PAL.build/DerivedSources -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/Release/PAL.build/DerivedSources -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources-normal/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources -F/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release -I/usr/local/include -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include -internal-isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/llvm-project/build/lib/clang/21/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/SubFrameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/Library/Frameworks -Wno-trigraphs -Werror -Wno-missing-field-initializers -Wmissing-prototypes -Wunreachable-code -Wno-implicit-atomic-properties -Wno-objc-interface-ivars -Wno-arc-repeated-use-of-weak -Wimplicit-retain-self -Wnon-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wduplicate-method-match -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wsign-compare -Wno-shorten-64-to-32 -Wnewline-eof -Wno-selector -Wno-strict-selector-match -Wundeclared-selector -Wdeprecated-implementations -Wno-c++11-extensions -Wno-implicit-fallthrough -Wprotocol -Wdeprecated-declarations -Winvalid-offsetof -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wall -Wc99-designator -Wconditional-uninitialized -Wextra -Wdeprecated-enum-enum-conversion -Wdeprecated-enum-float-conversion -Wenum-float-conversion -Wfinal-dtor-non-final-class -Wformat=2 -Wmisleading-indentation -Wpointer-to-int-cast -Wreorder-init-list -Wundef -Wunused-but-set-variable -Wvla -Werror=unguarded-availability -Wno-elaborated-enum-base -Wcast-qual -Wchar-subscripts -Wextra-tokens -Winit-self -Wmissing-noreturn -Wpacked -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wexit-time-destructors -Wglobal-constructors -Wtautological-compare -Wimplicit-fallthrough -Wvla -Wno-unknown-warning-option -Wliteral-conversion -Wthread-safety -Wno-profile-instr-out-of-date -Wno-profile-instr-unprofiled -Wunsafe-buffer-usage -std=c++2b -fdeprecated-macro -ferror-limit 19 -fmacro-backtrace-limit=0 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 1 -fblocks -fencode-extended-block-signature -fno-rtti -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fno-cxx-modules -fno-implicit-modules -fskip-odr-check-in-gmf -fobjc-runtime=macosx-15.5.0 -fobjc-weak -fobjc-exceptions -fexceptions -fpascal-strings -fmax-type-align=16 -fdiagnostics-show-note-include-stack -vectorize-loops -vectorize-slp -fsafe-buffer-usage-suggestions -analyzer-output=html -analyzer-config report-in-main-source-file=true -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -analyzer-checker optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker security.insecureAPI.UncheckedReturn -analyzer-checker security.insecureAPI.getpw -analyzer-checker security.insecureAPI.gets -analyzer-checker security.insecureAPI.mkstemp -analyzer-checker security.insecureAPI.mktemp -analyzer-disable-checker security.insecureAPI.rand -analyzer-disable-checker security.insecureAPI.strcpy -analyzer-checker security.insecureAPI.vfork -analyzer-disable-checker alpha,apiModeling,core,cplusplus,deadcode,debug,fuchsia,nullability,optin,osx,security,unix,webkit -analyzer-checker alpha.webkit.ForwardDeclChecker,alpha.webkit.MemoryUnsafeCastChecker,alpha.webkit.NoUncheckedPtrMemberChecker,alpha.webkit.NoUnretainedMemberChecker,alpha.webkit.RetainPtrCtorAdoptChecker,alpha.webkit.UncheckedCallArgsChecker,alpha.webkit.UncheckedLocalVarsChecker,alpha.webkit.UncountedCallArgsChecker,alpha.webkit.UncountedLocalVarsChecker,alpha.webkit.UnretainedCallArgsChecker,alpha.webkit.UnretainedLambdaCapturesChecker,alpha.webkit.UnretainedLocalVarsChecker,webkit.NoUncountedMemberChecker,webkit.RefCntblBaseVirtualDtor,webkit.UncountedLambdaCapturesChecker -analyzer-config max-nodes=10000000 -analyzer-config verbose-report-filename=true -fdwarf2-cfi-asm -o /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/MediaPlayerPrivateMediaSourceAVFObjC.plist -x objective-c++ /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm
1/*
2 * Copyright (C) 2013-2024 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 "MediaPlayerPrivateMediaSourceAVFObjC.h"
28
29#if ENABLE(MEDIA_SOURCE)(defined 1 && 1) && USE(AVFOUNDATION)(defined 1 && 1)
30
31#import "AVAssetMIMETypeCache.h"
32#import "AVAssetTrackUtilities.h"
33#import "AVStreamDataParserMIMETypeCache.h"
34#import "AudioMediaStreamTrackRenderer.h"
35#import "AudioVideoRendererAVFObjC.h"
36#import "CDMInstance.h"
37#import "CDMSessionAVContentKeySession.h"
38#import "ContentTypeUtilities.h"
39#import "GraphicsContext.h"
40#import "IOSurface.h"
41#import "Logging.h"
42#import "MediaPlayerIdentifier.h"
43#import "MediaSessionManagerCocoa.h"
44#import "MediaSourcePrivate.h"
45#import "MediaSourcePrivateAVFObjC.h"
46#import "MediaSourcePrivateClient.h"
47#import "MediaStrategy.h"
48#import "MessageClientForTesting.h"
49#import "MessageForTesting.h"
50#import "PixelBufferConformerCV.h"
51#import "PlatformDynamicRangeLimitCocoa.h"
52#import "PlatformScreen.h"
53#import "PlatformStrategies.h"
54#import "ShareableBitmap.h"
55#import "SourceBufferPrivateAVFObjC.h"
56#import "SpatialAudioExperienceHelper.h"
57#import "TextTrackRepresentation.h"
58#import "VideoFrameCV.h"
59#import "VideoLayerManagerObjC.h"
60#import "VideoMediaSampleRenderer.h"
61#import "WebSampleBufferVideoRendering.h"
62#import <AVFoundation/AVFoundation.h>
63#import <CoreMedia/CMTime.h>
64#import <QuartzCore/CALayer.h>
65#import <objc_runtime.h>
66#import <pal/avfoundation/MediaTimeAVFoundation.h>
67#import <pal/spi/cf/CFNotificationCenterSPI.h>
68#import <pal/spi/cocoa/AVFoundationSPI.h>
69#import <pal/spi/cocoa/QuartzCoreSPI.h>
70#import <wtf/BlockObjCExceptions.h>
71#import <wtf/Deque.h>
72#import <wtf/FileSystem.h>
73#import <wtf/MachSendRightAnnotated.h>
74#import <wtf/MainThread.h>
75#import <wtf/NativePromise.h>
76#import <wtf/NeverDestroyed.h>
77#import <wtf/TZoneMallocInlines.h>
78#import <wtf/WeakPtr.h>
79#import <wtf/darwin/DispatchExtras.h>
80#import <wtf/spi/cocoa/NSObjCRuntimeSPI.h>
81
82#import "CoreVideoSoftLink.h"
83#import <pal/cf/CoreMediaSoftLink.h>
84#import <pal/cocoa/AVFoundationSoftLink.h>
85#import <pal/cocoa/MediaToolboxSoftLink.h>
86
87@interface AVSampleBufferDisplayLayer (Staging_100128644)
88@property (assign, nonatomic) BOOL preventsAutomaticBackgroundingDuringVideoPlayback;
89@end
90
91namespace WebCore {
92
93#pragma mark -
94#pragma mark MediaPlayerPrivateMediaSourceAVFObjC
95
96Ref<AudioVideoRenderer> MediaPlayerPrivateMediaSourceAVFObjC::createRenderer(LoggerHelper& loggerHelper, HTMLMediaElementIdentifier mediaElementIdentifier, MediaPlayerIdentifier playerIdentifier)
97{
98 if (hasPlatformStrategies()) {
99 if (RefPtr renderer = platformStrategies()->mediaStrategy()->createAudioVideoRenderer(&loggerHelper, mediaElementIdentifier, playerIdentifier))
100 return renderer.releaseNonNull();
101 }
102 return AudioVideoRendererAVFObjC::create(Ref { loggerHelper.logger() }, loggerHelper.logIdentifier());
103}
104
105MediaPlayerPrivateMediaSourceAVFObjC::MediaPlayerPrivateMediaSourceAVFObjC(MediaPlayer& player)
106 : m_player(player)
107 , m_seekTimer(*this, &MediaPlayerPrivateMediaSourceAVFObjC::seekInternal)
108 , m_rendererSeekRequest(NativePromiseRequest::create())
109 , m_networkState(MediaPlayer::NetworkState::Empty)
110 , m_logger(player.mediaPlayerLogger())
111 , m_logIdentifier(player.mediaPlayerLogIdentifier())
112#if HAVE(SPATIAL_TRACKING_LABEL)(defined HAVE_SPATIAL_TRACKING_LABEL && HAVE_SPATIAL_TRACKING_LABEL
)
113 , m_defaultSpatialTrackingLabel(player.defaultSpatialTrackingLabel())
114 , m_spatialTrackingLabel(player.spatialTrackingLabel())
115#endif
116 , m_playerIdentifier(MediaPlayerIdentifier::generate())
117 , m_renderer(createRenderer(*this, player.clientIdentifier(), m_playerIdentifier))
118{
119 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
120}
121
122MediaPlayerPrivateMediaSourceAVFObjC::~MediaPlayerPrivateMediaSourceAVFObjC()
123{
124 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
125
126 cancelPendingSeek();
127 m_seekTimer.stop();
128 m_renderer->pause();
129 m_renderer->flush();
130}
131
132#pragma mark -
133#pragma mark MediaPlayer Factory Methods
134
135class MediaPlayerFactoryMediaSourceAVFObjC final : public MediaPlayerFactory {
136 WTF_MAKE_TZONE_ALLOCATED_INLINE(MediaPlayerFactoryMediaSourceAVFObjC)public: public: using HeapRef = ::bmalloc::api::HeapRef; using
SizeAndAlignment = ::bmalloc::api::SizeAndAlignment; using TZoneMallocFallback
= ::bmalloc::api::TZoneMallocFallback; using CompactAllocationMode
= ::bmalloc::CompactAllocationMode; static constexpr bool usesTZoneHeap
() { return true; } static constexpr unsigned inheritedSizeClass
() { return ::bmalloc::TZone::sizeClass<MediaPlayerFactoryMediaSourceAVFObjC
>(); } static constexpr unsigned inheritedAlignment() { return
::bmalloc::TZone::alignment<MediaPlayerFactoryMediaSourceAVFObjC
>(); } __attribute__((always_inline)) inline void* operator
new(size_t, void* p) { return p; } __attribute__((always_inline
)) inline void* operator new[](size_t, void* p) { return p; }
void* operator new[](size_t size) = delete; void operator delete
[](void* p) = delete; __attribute__((always_inline)) inline void
* operator new(size_t, NotNullTag, void* location) { ((void)0
); return location; } void* operator new(size_t size) { static
HeapRef s_heapRef; static const TZoneSpecification s_heapSpec
= { &s_heapRef, sizeof(MediaPlayerFactoryMediaSourceAVFObjC
), ::bmalloc::api::compactAllocationMode<MediaPlayerFactoryMediaSourceAVFObjC
>(), SizeAndAlignment::encode<MediaPlayerFactoryMediaSourceAVFObjC
>() }; if (!s_heapRef || size != sizeof(MediaPlayerFactoryMediaSourceAVFObjC
)) { [[unlikely]] if constexpr (::bmalloc::api::compactAllocationMode
<MediaPlayerFactoryMediaSourceAVFObjC>() == CompactAllocationMode
::Compact) return ::bmalloc::api::tzoneAllocateCompactSlow(size
, s_heapSpec); return ::bmalloc::api::tzoneAllocateNonCompactSlow
(size, s_heapSpec); } ; if constexpr (::bmalloc::api::compactAllocationMode
<MediaPlayerFactoryMediaSourceAVFObjC>() == CompactAllocationMode
::Compact) return ::bmalloc::api::tzoneAllocateCompact(s_heapRef
); return ::bmalloc::api::tzoneAllocateNonCompact(s_heapRef);
} __attribute__((always_inline)) inline void operator delete
(void* p) { ::bmalloc::api::tzoneFree(p); } __attribute__((always_inline
)) inline static void freeAfterDestruction(void* p) { ::bmalloc
::api::tzoneFree(p); } using WTFIsFastMallocAllocated = int; private
: using __makeBtzoneMallocedInlineMacroSemicolonifier __attribute__
((unused)) = int
;
137 WTF_OVERRIDE_DELETE_FOR_CHECKED_PTR(MediaPlayerFactoryMediaSourceAVFObjC)public: void operator delete(MediaPlayerFactoryMediaSourceAVFObjC
* object, std::destroying_delete_t, size_t size) { ((void)size
); object->setDidBeginCheckedPtrDeletion(); object->MediaPlayerFactoryMediaSourceAVFObjC
::~MediaPlayerFactoryMediaSourceAVFObjC(); if (object->checkedPtrCountWithoutThreadCheck
()) [[unlikely]] { zeroBytes(*object); return; } MediaPlayerFactoryMediaSourceAVFObjC
::operator delete(object); } using WTFDidOverrideDeleteForCheckedPtr
= int; private: using __thisIsHereToForceASemicolonAfterWTFOverrideDelete
__attribute__((unused)) = int
;
138private:
139 MediaPlayerEnums::MediaEngineIdentifier identifier() const final { return MediaPlayerEnums::MediaEngineIdentifier::AVFoundationMSE; };
140
141 Ref<MediaPlayerPrivateInterface> createMediaEnginePlayer(MediaPlayer& player) const final
142 {
143 return adoptRef(*new MediaPlayerPrivateMediaSourceAVFObjC(player));
144 }
145
146 void getSupportedTypes(HashSet<String>& types) const final
147 {
148 return MediaPlayerPrivateMediaSourceAVFObjC::getSupportedTypes(types);
149 }
150
151 MediaPlayer::SupportsType supportsTypeAndCodecs(const MediaEngineSupportParameters& parameters) const final
152 {
153 return MediaPlayerPrivateMediaSourceAVFObjC::supportsTypeAndCodecs(parameters);
154 }
155};
156
157void MediaPlayerPrivateMediaSourceAVFObjC::registerMediaEngine(MediaEngineRegistrar registrar)
158{
159 if (!isAvailable())
160 return;
161
162 ASSERT(AVAssetMIMETypeCache::singleton().isAvailable())((void)0);
163
164 registrar(makeUnique<MediaPlayerFactoryMediaSourceAVFObjC>());
165}
166
167bool MediaPlayerPrivateMediaSourceAVFObjC::isAvailable()
168{
169 return PAL::isAVFoundationFrameworkAvailable()
170 && PAL::isCoreMediaFrameworkAvailable()
171 && PAL::getAVStreamDataParserClassSingleton()
172 && PAL::getAVSampleBufferAudioRendererClassSingleton()
173 && PAL::getAVSampleBufferRenderSynchronizerClassSingleton()
174 && class_getInstanceMethod(PAL::getAVSampleBufferAudioRendererClassSingleton(), @selector(setMuted:));
175}
176
177void MediaPlayerPrivateMediaSourceAVFObjC::getSupportedTypes(HashSet<String>& types)
178{
179 types = AVStreamDataParserMIMETypeCache::singleton().supportedTypes();
180}
181
182MediaPlayer::SupportsType MediaPlayerPrivateMediaSourceAVFObjC::supportsTypeAndCodecs(const MediaEngineSupportParameters& parameters)
183{
184 // This engine does not support non-media-source sources.
185 if (!parameters.isMediaSource)
186 return MediaPlayer::SupportsType::IsNotSupported;
187
188 if (!contentTypeMeetsContainerAndCodecTypeRequirements(parameters.type, parameters.allowedMediaContainerTypes, parameters.allowedMediaCodecTypes))
189 return MediaPlayer::SupportsType::IsNotSupported;
190
191 auto supported = SourceBufferParser::isContentTypeSupported(parameters.type);
192
193 if (supported != MediaPlayer::SupportsType::IsSupported)
194 return supported;
195
196 if (!contentTypeMeetsHardwareDecodeRequirements(parameters.type, parameters.contentTypesRequiringHardwareSupport))
197 return MediaPlayer::SupportsType::IsNotSupported;
198
199 return MediaPlayer::SupportsType::IsSupported;
200}
201
202#pragma mark -
203#pragma mark MediaPlayerPrivateInterface Overrides
204
205void MediaPlayerPrivateMediaSourceAVFObjC::load(const String&)
206{
207 assertIsMainThread();
208 // This media engine only supports MediaSource URLs.
209 m_networkState = MediaPlayer::NetworkState::FormatError;
210 if (RefPtr player = m_player.get())
211 player->networkStateChanged();
212}
213
214void MediaPlayerPrivateMediaSourceAVFObjC::load(const URL&, const LoadOptions& options, MediaSourcePrivateClient& client)
215{
216 assertIsMainThread();
217 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
218
219 m_renderer->notifyWhenErrorOccurs([weakThis = WeakPtr { *this }](PlatformMediaError) {
220 ensureOnMainThread([weakThis] {
221 if (RefPtr protectedThis = weakThis.get()) {
222 protectedThis->setNetworkState(MediaPlayer::NetworkState::DecodeError);
223 protectedThis->setReadyState(MediaPlayer::ReadyState::HaveNothing);
224 }
225 });
226 });
227
228 m_renderer->notifyFirstFrameAvailable([weakThis = WeakPtr { *this }] {
229 ensureOnMainThread([weakThis] {
230 if (RefPtr protectedThis = weakThis.get(); protectedThis && !protectedThis->seeking())
231 protectedThis->setHasAvailableVideoFrame(true);
232 });
233 });
234
235 m_renderer->notifyWhenRequiresFlushToResume([weakThis = WeakPtr { *this }] {
236 ensureOnMainThread([weakThis] {
237 if (RefPtr protectedThis = weakThis.get())
238 protectedThis->setLayerRequiresFlush();
239 });
240 });
241
242 m_renderer->notifyRenderingModeChanged([weakThis = WeakPtr { *this }] {
243 ensureOnMainThread([weakThis] {
244 if (RefPtr protectedThis = weakThis.get()) {
245 if (RefPtr player = protectedThis->m_player.get())
246 player->renderingModeChanged();
247 }
248 });
249 });
250
251 m_renderer->notifySizeChanged([weakThis = WeakPtr { *this }](const MediaTime&, FloatSize size) {
252 ensureOnMainThread([weakThis, size] {
253 if (RefPtr protectedThis = weakThis.get())
254 protectedThis->setNaturalSize(size);
255 });
256 });
257
258 m_renderer->notifyEffectiveRateChanged([weakThis = WeakPtr { *this }](double) {
259 ensureOnMainThread([weakThis] {
260 if (RefPtr protectedThis = weakThis.get())
261 protectedThis->effectiveRateChanged();
262 });
263 });
264
265 m_renderer->notifyVideoLayerSizeChanged([weakThis = WeakPtr { *this }](const MediaTime&, FloatSize size) {
266 ensureOnMainThread([weakThis, size] {
267 if (RefPtr protectedThis = weakThis.get()) {
268 if (RefPtr player = protectedThis->m_player.get())
269 player->videoLayerSizeDidChange(size);
270 }
271 });
272 });
273
274 m_loadOptions = options;
275 m_renderer->setPreferences(options.videoRendererPreferences);
276 if (RefPtr player = m_player.get()) {
277 m_renderer->setPresentationSize(player->presentationSize());
278 m_renderer->renderingCanBeAcceleratedChanged(player->renderingCanBeAccelerated());
279 m_renderer->setVolume(player->volume());
280 m_renderer->setMuted(player->muted());
281 m_renderer->setPreservesPitchAndCorrectionAlgorithm(player->preservesPitch(), player->pitchCorrectionAlgorithm());
282#if HAVE(AUDIO_OUTPUT_DEVICE_UNIQUE_ID)(defined 1 && 1)
283 m_renderer->setOutputDeviceId(player->audioOutputDeviceIdOverride());
284#endif
285#if ENABLE(LINEAR_MEDIA_PLAYER)(defined ENABLE_LINEAR_MEDIA_PLAYER && ENABLE_LINEAR_MEDIA_PLAYER
)
286 if (RetainPtr videoTarget = player->videoTarget())
287 m_renderer->setVideoTarget(videoTarget.get());
288#endif
289 }
290
291 if (RefPtr mediaSourcePrivate = downcast<MediaSourcePrivateAVFObjC>(client.mediaSourcePrivate())) {
292 mediaSourcePrivate->setPlayer(this);
293 m_mediaSourcePrivate = WTF::move(mediaSourcePrivate);
294 client.reOpen();
295 } else
296 m_mediaSourcePrivate = MediaSourcePrivateAVFObjC::create(*this, client);
297}
298
299void MediaPlayerPrivateMediaSourceAVFObjC::setResourceOwner(const ProcessIdentity& resourceOwner)
300{
301 m_renderer->setResourceOwner(resourceOwner);
302}
303
304#if ENABLE(MEDIA_STREAM)(defined 1 && 1)
305void MediaPlayerPrivateMediaSourceAVFObjC::load(MediaStreamPrivate&)
306{
307 setNetworkState(MediaPlayer::NetworkState::FormatError);
308}
309#endif
310
311void MediaPlayerPrivateMediaSourceAVFObjC::cancelLoad()
312{
313}
314
315void MediaPlayerPrivateMediaSourceAVFObjC::prepareToPlay()
316{
317}
318
319PlatformLayer* MediaPlayerPrivateMediaSourceAVFObjC::platformLayer() const
320{
321 return m_renderer->platformVideoLayer();
322}
323
324void MediaPlayerPrivateMediaSourceAVFObjC::play()
325{
326 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
327 playInternal();
328}
329
330void MediaPlayerPrivateMediaSourceAVFObjC::playInternal(std::optional<MonotonicTime>&& hostTime)
331{
332 assertIsMainThread();
333 RefPtr mediaSourcePrivate = m_mediaSourcePrivate;
334 if (!mediaSourcePrivate)
335 return;
336
337 if (currentTime() >= mediaSourcePrivate->duration()) {
338 ALWAYS_LOG(LOGIDENTIFIER, "bailing, current time: ", currentTime(), " greater than duration ", mediaSourcePrivate->duration())Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "bailing, current time: "
, currentTime(), " greater than duration ", mediaSourcePrivate
->duration())
;
339 return;
340 }
341
342 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
343 flushVideoIfNeeded();
344
345 m_renderer->play(hostTime);
346}
347
348void MediaPlayerPrivateMediaSourceAVFObjC::pause()
349{
350 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
351 pauseInternal();
352}
353
354void MediaPlayerPrivateMediaSourceAVFObjC::pauseInternal(std::optional<MonotonicTime>&& hostTime)
355{
356 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
357 m_renderer->pause(hostTime);
358}
359
360bool MediaPlayerPrivateMediaSourceAVFObjC::paused() const
361{
362 return m_renderer->paused();
363}
364
365void MediaPlayerPrivateMediaSourceAVFObjC::setVolume(float volume)
366{
367 ALWAYS_LOG(LOGIDENTIFIER, volume)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), volume)
;
368 m_renderer->setVolume(volume);
369}
370
371bool MediaPlayerPrivateMediaSourceAVFObjC::supportsScanning() const
372{
373 return true;
374}
375
376void MediaPlayerPrivateMediaSourceAVFObjC::setMuted(bool muted)
377{
378 ALWAYS_LOG(LOGIDENTIFIER, muted)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), muted)
;
379 m_renderer->setMuted(muted);
380}
381
382FloatSize MediaPlayerPrivateMediaSourceAVFObjC::naturalSize() const
383{
384 return m_naturalSize;
385}
386
387bool MediaPlayerPrivateMediaSourceAVFObjC::hasVideo() const
388{
389 RefPtr mediaSourcePrivate = m_mediaSourcePrivate;
390 return mediaSourcePrivate && mediaSourcePrivate->hasVideo();
391}
392
393bool MediaPlayerPrivateMediaSourceAVFObjC::hasAudio() const
394{
395 RefPtr mediaSourcePrivate = m_mediaSourcePrivate;
396 return mediaSourcePrivate && mediaSourcePrivate->hasAudio();
397}
398
399void MediaPlayerPrivateMediaSourceAVFObjC::setPageIsVisible(bool visible)
400{
401 assertIsMainThread();
402 if (m_visible == visible)
403 return;
404
405 ALWAYS_LOG(LOGIDENTIFIER, visible)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), visible)
;
406 m_visible = visible;
407 m_renderer->setIsVisible(visible);
408}
409
410MediaTime MediaPlayerPrivateMediaSourceAVFObjC::duration() const
411{
412 assertIsMainThread();
413 RefPtr mediaSourcePrivate = m_mediaSourcePrivate;
414 return mediaSourcePrivate ? mediaSourcePrivate->duration() : MediaTime::zeroTime();
415}
416
417MediaTime MediaPlayerPrivateMediaSourceAVFObjC::currentTime() const
418{
419 return m_renderer->currentTime();
420}
421
422bool MediaPlayerPrivateMediaSourceAVFObjC::timeIsProgressing() const
423{
424 return m_renderer->timeIsProgressing();
425}
426
427MediaTime MediaPlayerPrivateMediaSourceAVFObjC::clampTimeToSensicalValue(const MediaTime& time) const
428{
429 assertIsMainThread();
430 if (m_lastSeekTime.isFinite() && time < m_lastSeekTime)
431 return m_lastSeekTime;
432
433 if (time < MediaTime::zeroTime())
434 return MediaTime::zeroTime();
435 if (time > duration())
436 return duration();
437 return time;
438}
439
440bool MediaPlayerPrivateMediaSourceAVFObjC::setCurrentTimeDidChangeCallback(MediaPlayer::CurrentTimeDidChangeCallback&& callback)
441{
442 assertIsMainThread();
443 m_renderer->setTimeObserver(100_ms, [weakThis = WeakPtr { *this }, callback = WTF::move(callback)](const MediaTime& currentTime) mutable {
444 // This method is only used with the RemoteMediaPlayerProxy and RemoteAudioVideoRendererProxyManager where m_renderer is an AudioVideoRendererAVFObjC that runs on the main thread only (for now).
445 assertIsMainThread();
446 if (RefPtr protectedThis = weakThis.get())
447 callback(protectedThis->clampTimeToSensicalValue(currentTime));
448 });
449
450 return true;
451}
452
453void MediaPlayerPrivateMediaSourceAVFObjC::timeChanged()
454{
455 assertIsMainThread();
456 if (RefPtr player = m_player.get())
457 player->timeChanged();
458}
459
460void MediaPlayerPrivateMediaSourceAVFObjC::stall()
461{
462 assertIsMainThread();
463 m_renderer->stall();
464 if (shouldBePlaying())
465 timeChanged();
466}
467
468bool MediaPlayerPrivateMediaSourceAVFObjC::playAtHostTime(const MonotonicTime& time)
469{
470 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
471 playInternal(time);
472 return true;
473}
474
475bool MediaPlayerPrivateMediaSourceAVFObjC::pauseAtHostTime(const MonotonicTime& time)
476{
477 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
478 pauseInternal(time);
479 return true;
480}
481
482MediaTime MediaPlayerPrivateMediaSourceAVFObjC::startTime() const
483{
484 return MediaTime::zeroTime();
485}
486
487MediaTime MediaPlayerPrivateMediaSourceAVFObjC::initialTime() const
488{
489 return MediaTime::zeroTime();
490}
491
492void MediaPlayerPrivateMediaSourceAVFObjC::seekToTarget(const SeekTarget& target)
493{
494 assertIsMainThread();
495 ALWAYS_LOG(LOGIDENTIFIER, "time = ", target.time, ", negativeThreshold = ", target.negativeThreshold, ", positiveThreshold = ", target.positiveThreshold)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "time = ", target
.time, ", negativeThreshold = ", target.negativeThreshold, ", positiveThreshold = "
, target.positiveThreshold)
;
496
497 m_pendingSeek = target;
498
499 if (m_seekTimer.isActive())
500 m_seekTimer.stop();
501 m_seekTimer.startOneShot(0_s);
502}
503
504void MediaPlayerPrivateMediaSourceAVFObjC::seekInternal()
505{
506 assertIsMainThread();
507 if (!m_pendingSeek)
508 return;
509
510 RefPtr mediaSourcePrivate = m_mediaSourcePrivate;
511 if (!mediaSourcePrivate)
512 return;
513
514 auto pendingSeek = std::exchange(m_pendingSeek, { }).value();
515 m_lastSeekTime = pendingSeek.time;
516
517 m_seeking = true;
518
519 cancelPendingSeek();
520 m_renderer->prepareToSeek();
521
522 mediaSourcePrivate->waitForTarget(pendingSeek)->whenSettled(RunLoop::currentSingleton(), [weakThis = WeakPtr { *this }, seekTime = m_lastSeekTime] (auto&& result) mutable {
523 RefPtr protectedThis = weakThis.get();
524 if (!protectedThis || !result)
525 return; // seek cancelled;
526
527 protectedThis->startSeek(seekTime);
528 });
529}
530
531void MediaPlayerPrivateMediaSourceAVFObjC::startSeek(const MediaTime& seekTime)
532{
533 assertIsMainThread();
534 if (m_rendererSeekRequest->hasCallback()) {
535 ALWAYS_LOG(LOGIDENTIFIER, "Seeking pending, cancel earlier seek")Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "Seeking pending, cancel earlier seek"
)
;
536 cancelPendingSeek();
537 }
538 m_renderer->seekTo(seekTime)->whenSettled(RunLoop::mainSingleton(), [weakThis = WeakPtr { *this }, seekTime](auto&& result) {
539 assertIsMainThread();
540 if (!result && result.error() != PlatformMediaError::RequiresFlushToResume)
541 return; // cancelled.
542
543 RefPtr protectedThis = weakThis.get();
544 if (!protectedThis)
545 return;
546
547 protectedThis->m_rendererSeekRequest->complete();
548
549 if (!result) {
550 ASSERT(result.error() == PlatformMediaError::RequiresFlushToResume)((void)0);
551 protectedThis->flush();
552 protectedThis->reenqueueMediaForTime(seekTime);
553 protectedThis->startSeek(seekTime);
554 return;
555 }
556 protectedThis->completeSeek(*result);
557 })->track(m_rendererSeekRequest.get());
558}
559
560void MediaPlayerPrivateMediaSourceAVFObjC::cancelPendingSeek()
561{
562 assertIsMainThread();
563
564 if (m_rendererSeekRequest->hasCallback())
565 m_rendererSeekRequest->disconnect();
566}
567
568void MediaPlayerPrivateMediaSourceAVFObjC::completeSeek(const MediaTime& seekedTime)
569{
570 assertIsMainThread();
571 ALWAYS_LOG(LOGIDENTIFIER, "")Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "")
;
572
573 m_seeking = false;
574
575 if (RefPtr player = m_player.get()) {
576 player->seeked(seekedTime);
577 player->timeChanged();
578 }
579
580 if (hasVideo())
581 setHasAvailableVideoFrame(true);
582}
583
584bool MediaPlayerPrivateMediaSourceAVFObjC::seeking() const
585{
586 assertIsMainThread();
587 return m_pendingSeek || m_seeking;
588}
589
590void MediaPlayerPrivateMediaSourceAVFObjC::setLoadingProgresssed(bool flag)
591{
592 assertIsMainThread();
593 m_loadingProgressed = flag;
594}
595
596void MediaPlayerPrivateMediaSourceAVFObjC::setRateDouble(double rate)
597{
598 assertIsMainThread();
599 // AVSampleBufferRenderSynchronizer does not support negative rate yet.
600 m_rate = std::max<double>(rate, 0);
601 m_renderer->setRate(m_rate);
602}
603
604double MediaPlayerPrivateMediaSourceAVFObjC::rate() const
605{
606 assertIsMainThread();
607 return m_rate;
608}
609
610double MediaPlayerPrivateMediaSourceAVFObjC::effectiveRate() const
611{
612 assertIsMainThread();
613 return m_renderer->effectiveRate();
614}
615
616void MediaPlayerPrivateMediaSourceAVFObjC::setPreservesPitch(bool preservesPitch)
617{
618 assertIsMainThread();
619 ALWAYS_LOG(LOGIDENTIFIER, preservesPitch)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), preservesPitch)
;
620 if (RefPtr player = m_player.get())
621 m_renderer->setPreservesPitchAndCorrectionAlgorithm(preservesPitch, player->pitchCorrectionAlgorithm());
622}
623
624MediaPlayer::NetworkState MediaPlayerPrivateMediaSourceAVFObjC::networkState() const
625{
626 assertIsMainThread();
627 return m_networkState;
628}
629
630MediaPlayer::ReadyState MediaPlayerPrivateMediaSourceAVFObjC::readyState() const
631{
632 if (RefPtr mediaSourcePrivate = m_mediaSourcePrivate)
633 return mediaSourcePrivate->mediaPlayerReadyState();
634 assertIsMainThread();
635 return m_readyState;
636}
637
638void MediaPlayerPrivateMediaSourceAVFObjC::readyStateFromMediaSourceChanged()
639{
640 assertIsMainThread();
641 updateStateFromReadyState();
642}
643
644MediaTime MediaPlayerPrivateMediaSourceAVFObjC::maxTimeSeekable() const
645{
646 return duration();
647}
648
649MediaTime MediaPlayerPrivateMediaSourceAVFObjC::minTimeSeekable() const
650{
651 return startTime();
652}
653
654const PlatformTimeRanges& MediaPlayerPrivateMediaSourceAVFObjC::buffered() const
655{
656 return PlatformTimeRanges::emptyRanges();
657}
658
659RefPtr<MediaSourcePrivateAVFObjC> MediaPlayerPrivateMediaSourceAVFObjC::protectedMediaSourcePrivate() const
660{
661 return m_mediaSourcePrivate;
662}
663
664void MediaPlayerPrivateMediaSourceAVFObjC::bufferedChanged()
665{
666 assertIsMainThread();
667 m_renderer->cancelTimeReachedAction();
668
669 auto ranges = protectedMediaSourcePrivate()->buffered();
670 auto currentTime = this->currentTime();
671 if (!protectedMediaSourcePrivate()->hasFutureTime(currentTime) && shouldBePlaying()) {
672 ALWAYS_LOG(LOGIDENTIFIER, "Not having data to play at currentTime: ", currentTime, " stalling")Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "Not having data to play at currentTime: "
, currentTime, " stalling")
;
673 stall();
674 }
675
676 auto stallAtTime = duration();
677 size_t index = ranges.find(currentTime);
678 if (index != notFound) {
679 // Find the next gap (or end of media)
680 for (; index < ranges.length(); index++) {
681 if ((index < ranges.length() - 1 && ranges.start(index + 1) - ranges.end(index) > m_mediaSourcePrivate->timeFudgeFactor())
682 || (index == ranges.length() - 1 && ranges.end(index) > currentTime)) {
683 stallAtTime = ranges.end(index);
684 break;
685 }
686 }
687 }
688
689 ALWAYS_LOG(LOGIDENTIFIER, "will stall playback at time: ", stallAtTime)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "will stall playback at time: "
, stallAtTime)
;
690 auto logSiteIdentifier = LOGIDENTIFIERWTF::Logger::LogSiteIdentifier(logClassName(), __func__, logIdentifier
())
;
691 UNUSED_PARAM(logSiteIdentifier)(void)logSiteIdentifier;
692 m_renderer->notifyTimeReachedAndStall(stallAtTime, [weakThis = WeakPtr { *this }, logSiteIdentifier](const MediaTime& stallTime) {
693 ensureOnMainThread([weakThis, logSiteIdentifier, stallTime] {
694 RefPtr protectedThis = weakThis.get();
695 if (!protectedThis)
696 return;
697 if (protectedThis->protectedMediaSourcePrivate()->hasFutureTime(stallTime) && protectedThis->shouldBePlaying()) {
698 ALWAYS_LOG_WITH_THIS(protectedThis, logSiteIdentifier, "Data now available at ", stallTime, " resuming")Ref { (protectedThis)->logger() }->logAlways((protectedThis
)->logChannel(), logSiteIdentifier, "Data now available at "
, stallTime, " resuming")
;
699 protectedThis->m_renderer->play(); // New data was added, resume. Can't happen in practice, action would have been cancelled once buffered changed.
700 return;
701 }
702 MediaTime now = protectedThis->currentTime();
703 ALWAYS_LOG_WITH_THIS(protectedThis, logSiteIdentifier, "boundary time observer called, now = ", now)Ref { (protectedThis)->logger() }->logAlways((protectedThis
)->logChannel(), logSiteIdentifier, "boundary time observer called, now = "
, now)
;
704
705 if (stallTime == protectedThis->duration())
706 protectedThis->pause();
707 protectedThis->timeChanged();
708 });
709 });
710}
711
712void MediaPlayerPrivateMediaSourceAVFObjC::setLayerRequiresFlush()
713{
714 assertIsMainThread();
715 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
716 m_layerRequiresFlush = true;
717#if PLATFORM(IOS_FAMILY)(defined WTF_PLATFORM_IOS_FAMILY && WTF_PLATFORM_IOS_FAMILY
)
718 if (m_applicationIsActive)
719 flushVideoIfNeeded();
720#else
721 flushVideoIfNeeded();
722#endif
723}
724
725void MediaPlayerPrivateMediaSourceAVFObjC::flushVideoIfNeeded()
726{
727 assertIsMainThread();
728 ALWAYS_LOG(LOGIDENTIFIER, "layerRequiresFlush: ", m_layerRequiresFlush)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "layerRequiresFlush: "
, m_layerRequiresFlush)
;
729 if (!m_layerRequiresFlush)
730 return;
731
732 m_layerRequiresFlush = false;
733
734 // Rendering may have been interrupted while the page was in a non-visible
735 // state, which would require a flush to resume decoding.
736 if (RefPtr mediaSourcePrivate = m_mediaSourcePrivate) {
737 setHasAvailableVideoFrame(false);
738 mediaSourcePrivate->flushAndReenqueueActiveVideoSourceBuffers();
739 }
740}
741
742void MediaPlayerPrivateMediaSourceAVFObjC::flush()
743{
744 assertIsMainThread();
745 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
746 m_renderer->flush();
747 setHasAvailableVideoFrame(false);
748}
749
750void MediaPlayerPrivateMediaSourceAVFObjC::reenqueueMediaForTime(const MediaTime& seekTime)
751{
752 if (RefPtr mediaSourcePrivate = m_mediaSourcePrivate)
753 mediaSourcePrivate->seekToTime(seekTime);
754}
755
756bool MediaPlayerPrivateMediaSourceAVFObjC::didLoadingProgress() const
757{
758 assertIsMainThread();
759 bool loadingProgressed = m_loadingProgressed;
760 m_loadingProgressed = false;
761 return loadingProgressed;
762}
763
764RefPtr<NativeImage> MediaPlayerPrivateMediaSourceAVFObjC::nativeImageForCurrentTime()
765{
766 assertIsMainThread();
767 updateLastImage();
768 return m_lastImage;
769}
770
771bool MediaPlayerPrivateMediaSourceAVFObjC::updateLastVideoFrame()
772{
773 assertIsMainThread();
774 RefPtr videoFrame = m_renderer->currentVideoFrame();
775 if (!videoFrame)
776 return false;
777
778 INFO_LOG(LOGIDENTIFIER, "displayed pixelbuffer copied for time ", videoFrame->presentationTime())Ref { logger() }->info(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "displayed pixelbuffer copied for time "
, videoFrame->presentationTime())
;
779 m_lastVideoFrame = WTF::move(videoFrame);
780 return true;
781}
782
783bool MediaPlayerPrivateMediaSourceAVFObjC::updateLastImage()
784{
785 assertIsMainThread();
786 if (m_isGatheringVideoFrameMetadata) {
787 if (!m_videoFrameMetadata)
788 return false;
789 if (m_videoFrameMetadata->presentedFrames == m_lastConvertedSampleCount)
790 return false;
791 m_lastConvertedSampleCount = m_videoFrameMetadata->presentedFrames;
792 }
793
794 m_lastImage = m_renderer->currentNativeImage();
795 return !!m_lastImage;
796}
797
798void MediaPlayerPrivateMediaSourceAVFObjC::maybePurgeLastImage()
799{
800 assertIsMainThread();
801 // If we are in the middle of a rVFC operation, do not purge anything:
802 if (m_isGatheringVideoFrameMetadata)
803 return;
804
805 m_lastImage = nullptr;
806 m_lastVideoFrame = nullptr;
807}
808
809Ref<MediaPlayer::BitmapImagePromise> MediaPlayerPrivateMediaSourceAVFObjC::bitmapImageForCurrentTime()
810{
811 return m_renderer->currentNativeImageAsync()->whenSettled(RunLoop::mainSingleton(), [weakThis = WeakPtr { *this }](auto&& result) {
812 RefPtr protectedThis = weakThis.get();
813 if (!protectedThis || !result)
814 return BitmapImagePromise::createAndReject();
815 if (RefPtr bitmap = bitmapFromImage(*result))
Call argument is uncounted and unsafe
816 return BitmapImagePromise::createAndResolve(bitmap.releaseNonNull());
817 return BitmapImagePromise::createAndReject();
818 });
819}
820
821void MediaPlayerPrivateMediaSourceAVFObjC::paint(GraphicsContext& context, const FloatRect& rect)
822{
823 paintCurrentFrameInContext(context, rect);
824}
825
826void MediaPlayerPrivateMediaSourceAVFObjC::paintCurrentFrameInContext(GraphicsContext& context, const FloatRect& outputRect)
827{
828 m_renderer->paintCurrentVideoFrameInContext(context, outputRect);
829}
830
831RefPtr<VideoFrame> MediaPlayerPrivateMediaSourceAVFObjC::videoFrameForCurrentTime()
832{
833 assertIsMainThread();
834 if (!m_isGatheringVideoFrameMetadata)
835 updateLastVideoFrame();
836 return m_lastVideoFrame;
837}
838
839DestinationColorSpace MediaPlayerPrivateMediaSourceAVFObjC::colorSpace()
840{
841 assertIsMainThread();
842 updateLastImage();
843 RefPtr lastImage = m_lastImage;
844 return lastImage ? lastImage->colorSpace() : DestinationColorSpace::SRGB();
845}
846
847bool MediaPlayerPrivateMediaSourceAVFObjC::hasAvailableVideoFrame() const
848{
849 assertIsMainThread();
850 return m_hasAvailableVideoFrame;
851}
852
853bool MediaPlayerPrivateMediaSourceAVFObjC::supportsAcceleratedRendering() const
854{
855 return true;
856}
857
858void MediaPlayerPrivateMediaSourceAVFObjC::setPresentationSize(const IntSize& newSize)
859{
860 m_renderer->setPresentationSize(newSize);
861}
862
863Ref<AudioVideoRenderer> MediaPlayerPrivateMediaSourceAVFObjC::audioVideoRenderer() const
864{
865 return m_renderer;
866}
867
868void MediaPlayerPrivateMediaSourceAVFObjC::acceleratedRenderingStateChanged()
869{
870 RefPtr player = m_player.get();
871 m_renderer->renderingCanBeAcceleratedChanged(player ? player->renderingCanBeAccelerated() : false);
872}
873
874void MediaPlayerPrivateMediaSourceAVFObjC::notifyActiveSourceBuffersChanged()
875{
876 assertIsMainThread();
877 if (RefPtr player = m_player.get())
878 player->activeSourceBuffersChanged();
879}
880
881MediaPlayer::MovieLoadType MediaPlayerPrivateMediaSourceAVFObjC::movieLoadType() const
882{
883 return MediaPlayer::MovieLoadType::StoredStream;
884}
885
886String MediaPlayerPrivateMediaSourceAVFObjC::engineDescription() const
887{
888 static NeverDestroyed<String> description(MAKE_STATIC_STRING_IMPL("AVFoundation MediaSource Engine")([] { static StaticStringImpl impl("AVFoundation MediaSource Engine"
); return &impl; }())
);
889 return description;
890}
891
892String MediaPlayerPrivateMediaSourceAVFObjC::languageOfPrimaryAudioTrack() const
893{
894 // FIXME(125158): implement languageOfPrimaryAudioTrack()
895 return emptyString();
896}
897
898size_t MediaPlayerPrivateMediaSourceAVFObjC::extraMemoryCost() const
899{
900 return 0;
901}
902
903std::optional<VideoPlaybackQualityMetrics> MediaPlayerPrivateMediaSourceAVFObjC::videoPlaybackQualityMetrics()
904{
905 return m_renderer->videoPlaybackQualityMetrics();
906}
907
908#pragma mark -
909#pragma mark Utility Methods
910
911bool MediaPlayerPrivateMediaSourceAVFObjC::shouldBePlaying() const
912{
913 assertIsMainThread();
914 return !m_renderer->paused() && !seeking() && readyState() >= MediaPlayer::ReadyState::HaveFutureData;
915}
916
917void MediaPlayerPrivateMediaSourceAVFObjC::setHasAvailableVideoFrame(bool flag)
918{
919 assertIsMainThread();
920 if (m_hasAvailableVideoFrame == flag)
921 return;
922
923 ALWAYS_LOG(LOGIDENTIFIER, flag)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), flag)
;
924 m_hasAvailableVideoFrame = flag;
925
926 if (!m_hasAvailableVideoFrame)
927 return;
928
929 RefPtr player = m_player.get();
930 if (player)
931 player->firstVideoFrameAvailable();
932
933 if (m_readyStateIsWaitingForAvailableFrame) {
934 m_readyStateIsWaitingForAvailableFrame = false;
935 if (player)
936 player->readyStateChanged();
937 }
938}
939
940void MediaPlayerPrivateMediaSourceAVFObjC::durationChanged()
941{
942 assertIsMainThread();
943 RefPtr mediaSourcePrivate = m_mediaSourcePrivate;
944 if (!mediaSourcePrivate)
945 return;
946
947 MediaTime duration = mediaSourcePrivate->duration();
948 // Avoid emiting durationchanged in the case where the previous duration was unknown as that case is already handled
949 // by the HTMLMediaElement.
950 if (m_duration != duration && m_duration.isValid()) {
951 if (RefPtr player = m_player.get())
952 player->durationChanged();
953 }
954 m_duration = duration;
955 bufferedChanged();
956}
957
958void MediaPlayerPrivateMediaSourceAVFObjC::effectiveRateChanged()
959{
960 assertIsMainThread();
961 ALWAYS_LOG(LOGIDENTIFIER, effectiveRate())Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), effectiveRate())
;
962 if (RefPtr player = m_player.get())
963 player->rateChanged();
964}
965
966void MediaPlayerPrivateMediaSourceAVFObjC::setNaturalSize(const FloatSize& size)
967{
968 assertIsMainThread();
969 if (size == m_naturalSize)
970 return;
971
972 ALWAYS_LOG(LOGIDENTIFIER, size)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), size)
;
973
974 m_naturalSize = size;
975 if (RefPtr player = m_player.get())
976 player->sizeChanged();
977}
978
979#if ENABLE(LEGACY_ENCRYPTED_MEDIA)(defined 1 && 1)
980RefPtr<CDMSessionAVContentKeySession> MediaPlayerPrivateMediaSourceAVFObjC::cdmSession() const
981{
982 assertIsMainThread();
983 return m_session.get();
984}
985
986void MediaPlayerPrivateMediaSourceAVFObjC::setCDMSession(LegacyCDMSession* session)
987{
988 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
989
990 m_renderer->setCDMSession(session);
991}
992
993void MediaPlayerPrivateMediaSourceAVFObjC::keyAdded()
994{
995 m_renderer->attemptToDecrypt();
996}
997
998#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA)
999
1000#if ENABLE(LEGACY_ENCRYPTED_MEDIA)(defined 1 && 1) || ENABLE(ENCRYPTED_MEDIA)(defined 1 && 1)
1001void MediaPlayerPrivateMediaSourceAVFObjC::keyNeeded(const SharedBuffer& initData)
1002{
1003 if (RefPtr player = m_player.get())
1004 player->keyNeeded(initData);
1005}
1006#endif
1007
1008#if ENABLE(ENCRYPTED_MEDIA)(defined 1 && 1)
1009void MediaPlayerPrivateMediaSourceAVFObjC::cdmInstanceAttached(CDMInstance& instance)
1010{
1011 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
1012 m_renderer->setCDMInstance(&instance);
1013
1014 needsVideoLayerChanged();
1015}
1016
1017void MediaPlayerPrivateMediaSourceAVFObjC::cdmInstanceDetached(CDMInstance&)
1018{
1019 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
1020 m_renderer->setCDMInstance(nullptr);
1021
1022 needsVideoLayerChanged();
1023}
1024
1025void MediaPlayerPrivateMediaSourceAVFObjC::attemptToDecryptWithInstance(CDMInstance&)
1026{
1027 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
1028 m_renderer->attemptToDecrypt();
1029}
1030
1031bool MediaPlayerPrivateMediaSourceAVFObjC::waitingForKey() const
1032{
1033 RefPtr mediaSourcePrivate = m_mediaSourcePrivate;
1034 return mediaSourcePrivate && mediaSourcePrivate->waitingForKey();
1035}
1036
1037void MediaPlayerPrivateMediaSourceAVFObjC::waitingForKeyChanged()
1038{
1039 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
1040 if (RefPtr player = m_player.get())
1041 player->waitingForKeyChanged();
1042}
1043
1044void MediaPlayerPrivateMediaSourceAVFObjC::initializationDataEncountered(const String& initDataType, RefPtr<ArrayBuffer>&& initData)
1045{
1046 ALWAYS_LOG(LOGIDENTIFIER, initDataType)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), initDataType)
;
1047 if (RefPtr player = m_player.get())
1048 player->initializationDataEncountered(initDataType, WTF::move(initData));
1049}
1050#endif
1051
1052const Vector<ContentType>& MediaPlayerPrivateMediaSourceAVFObjC::mediaContentTypesRequiringHardwareSupport() const
1053{
1054 return m_player.get()->mediaContentTypesRequiringHardwareSupport();
1055}
1056
1057void MediaPlayerPrivateMediaSourceAVFObjC::needsVideoLayerChanged()
1058{
1059 if (RefPtr mediaSourcePrivate = m_mediaSourcePrivate)
1060 m_renderer->setHasProtectedVideoContent(mediaSourcePrivate->needsVideoLayer());
1061}
1062
1063void MediaPlayerPrivateMediaSourceAVFObjC::setReadyState(MediaPlayer::ReadyState readyState)
1064{
1065 assertIsMainThread();
1066 if (m_readyState == readyState)
1067 return;
1068
1069 if (m_readyState > MediaPlayer::ReadyState::HaveCurrentData && readyState == MediaPlayer::ReadyState::HaveCurrentData)
1070 ALWAYS_LOG(LOGIDENTIFIER, "stall detected currentTime:", currentTime())Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "stall detected currentTime:"
, currentTime())
;
1071
1072 m_readyState = readyState;
1073 updateStateFromReadyState();
1074}
1075
1076void MediaPlayerPrivateMediaSourceAVFObjC::updateStateFromReadyState()
1077{
1078 assertIsMainThread();
1079 if (shouldBePlaying()) {
1080 m_renderer->play();
1081 timeChanged();
1082 } else
1083 stall();
1084
1085 if (readyState() >= MediaPlayer::ReadyState::HaveCurrentData && hasVideo() && !m_hasAvailableVideoFrame) {
1086 m_readyStateIsWaitingForAvailableFrame = true;
1087 return;
1088 }
1089
1090 if (RefPtr player = m_player.get())
1091 player->readyStateChanged();
1092}
1093
1094void MediaPlayerPrivateMediaSourceAVFObjC::setNetworkState(MediaPlayer::NetworkState networkState)
1095{
1096 assertIsMainThread();
1097 if (m_networkState == networkState)
1098 return;
1099
1100 ALWAYS_LOG(LOGIDENTIFIER, networkState)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), networkState)
;
1101 m_networkState = networkState;
1102 if (RefPtr player = m_player.get())
1103 player->networkStateChanged();
1104}
1105
1106void MediaPlayerPrivateMediaSourceAVFObjC::mediaSourceHasRetrievedAllData()
1107{
1108 assertIsMainThread();
1109 setNetworkState(MediaPlayer::NetworkState::Loaded);
1110}
1111
1112ALLOW_NEW_API_WITHOUT_GUARDS_BEGINclang diagnostic push clang diagnostic ignored "-W" "unguarded-availability-new"
1113void MediaPlayerPrivateMediaSourceAVFObjC::addAudioTrack(TrackIdentifier audioTrack)
1114ALLOW_NEW_API_WITHOUT_GUARDS_ENDclang diagnostic pop
1115{
1116 assertIsMainThread();
1117 if (!m_audioTracksMap.add(audioTrack, AudioTrackProperties()).isNewEntry)
1118 return;
1119
1120 if (RefPtr player = m_player.get())
1121 player->characteristicChanged();
1122}
1123
1124ALLOW_NEW_API_WITHOUT_GUARDS_BEGINclang diagnostic push clang diagnostic ignored "-W" "unguarded-availability-new"
1125void MediaPlayerPrivateMediaSourceAVFObjC::removeAudioTrack(TrackIdentifier audioTrack)
1126ALLOW_NEW_API_WITHOUT_GUARDS_ENDclang diagnostic pop
1127{
1128 assertIsMainThread();
1129 if (auto iter = m_audioTracksMap.find(audioTrack); iter != m_audioTracksMap.end())
1130 m_audioTracksMap.remove(iter);
1131}
1132
1133void MediaPlayerPrivateMediaSourceAVFObjC::removeAudioTrack(AudioTrackPrivate& track)
1134{
1135 assertIsMainThread();
1136 if (RefPtr player = m_player.get())
1137 player->removeAudioTrack(track);
1138}
1139
1140void MediaPlayerPrivateMediaSourceAVFObjC::removeVideoTrack(VideoTrackPrivate& track)
1141{
1142 assertIsMainThread();
1143 if (RefPtr player = m_player.get())
1144 player->removeVideoTrack(track);
1145}
1146
1147void MediaPlayerPrivateMediaSourceAVFObjC::removeTextTrack(InbandTextTrackPrivate& track)
1148{
1149 assertIsMainThread();
1150 if (RefPtr player = m_player.get())
1151 player->removeTextTrack(track);
1152}
1153
1154void MediaPlayerPrivateMediaSourceAVFObjC::characteristicsFromMediaSourceChanged()
1155{
1156 assertIsMainThread();
1157 if (RefPtr player = m_player.get())
1158 player->characteristicChanged();
1159}
1160
1161RetainPtr<PlatformLayer> MediaPlayerPrivateMediaSourceAVFObjC::createVideoFullscreenLayer()
1162{
1163 return adoptNS([[CALayer alloc] init]);
1164}
1165
1166void MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, WTF::Function<void()>&& completionHandler)
1167{
1168 m_renderer->setVideoFullscreenLayer(videoFullscreenLayer, WTF::move(completionHandler));
1169}
1170
1171void MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenFrame(const FloatRect& frame)
1172{
1173 m_renderer->setVideoFullscreenFrame(frame);
1174}
1175
1176void MediaPlayerPrivateMediaSourceAVFObjC::syncTextTrackBounds()
1177{
1178 m_renderer->syncTextTrackBounds();
1179}
1180
1181void MediaPlayerPrivateMediaSourceAVFObjC::setTextTrackRepresentation(TextTrackRepresentation* representation)
1182{
1183 m_renderer->setTextTrackRepresentation(representation);
1184}
1185
1186#if ENABLE(WIRELESS_PLAYBACK_TARGET)(defined 1 && 1)
1187void MediaPlayerPrivateMediaSourceAVFObjC::setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&& target)
1188{
1189 assertIsMainThread();
1190 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
1191 m_playbackTarget = WTF::move(target);
1192}
1193
1194void MediaPlayerPrivateMediaSourceAVFObjC::setShouldPlayToPlaybackTarget(bool shouldPlayToTarget)
1195{
1196 assertIsMainThread();
1197 if (shouldPlayToTarget == m_shouldPlayToTarget)
1198 return;
1199
1200 ALWAYS_LOG(LOGIDENTIFIER, shouldPlayToTarget)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), shouldPlayToTarget
)
;
1201 m_shouldPlayToTarget = shouldPlayToTarget;
1202
1203 if (RefPtr player = m_player.get())
1204 player->currentPlaybackTargetIsWirelessChanged(isCurrentPlaybackTargetWireless());
1205}
1206
1207bool MediaPlayerPrivateMediaSourceAVFObjC::isCurrentPlaybackTargetWireless() const
1208{
1209 assertIsMainThread();
1210 RefPtr playbackTarget = m_playbackTarget;
1211 if (!playbackTarget)
1212 return false;
1213
1214 auto hasTarget = m_shouldPlayToTarget && playbackTarget->hasActiveRoute();
1215 INFO_LOG(LOGIDENTIFIER, hasTarget)Ref { logger() }->info(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), hasTarget)
;
1216 return hasTarget;
1217}
1218#endif
1219
1220bool MediaPlayerPrivateMediaSourceAVFObjC::performTaskAtTime(WTF::Function<void(const MediaTime&)>&& task, const MediaTime& time)
1221{
1222 m_renderer->performTaskAtTime(time, [task = WTF::move(task)](const MediaTime& time) mutable {
1223 ensureOnMainThread([time, task = WTF::move(task)] {
1224 task(time);
1225 });
1226 });
1227 return true;
1228}
1229
1230void MediaPlayerPrivateMediaSourceAVFObjC::audioOutputDeviceChanged()
1231{
1232#if HAVE(AUDIO_OUTPUT_DEVICE_UNIQUE_ID)(defined 1 && 1)
1233 RefPtr player = m_player.get();
1234 if (!player)
1235 return;
1236 auto deviceId = player->audioOutputDeviceId();
1237 m_renderer->setOutputDeviceId(deviceId);
1238#endif
1239}
1240
1241void MediaPlayerPrivateMediaSourceAVFObjC::startVideoFrameMetadataGathering()
1242{
1243 assertIsMainThread();
1244 if (m_isGatheringVideoFrameMetadata)
1245 return;
1246
1247 m_isGatheringVideoFrameMetadata = true;
1248 m_renderer->notifyWhenHasAvailableVideoFrame([weakThis = WeakPtr { *this }](const MediaTime& presentationTime, double displayTime) {
1249 ensureOnMainThread([weakThis, presentationTime, displayTime] {
1250 if (RefPtr protectedThis = weakThis.get())
1251 protectedThis->checkNewVideoFrameMetadata(presentationTime, displayTime);
1252 });
1253 });
1254}
1255
1256void MediaPlayerPrivateMediaSourceAVFObjC::checkNewVideoFrameMetadata(MediaTime presentationTime, double displayTime)
1257{
1258 assertIsMainThread();
1259 RefPtr player = m_player.get();
1260 if (!player)
1261 return;
1262
1263 if (!updateLastVideoFrame())
1264 return;
1265
1266 RefPtr lastVideoFrame = m_lastVideoFrame;
1267#ifndef NDEBUG1
1268 if (m_lastVideoFrame->presentationTime() != presentationTime)
1269 ALWAYS_LOG(LOGIDENTIFIER, "notification of new frame delayed retrieved:", lastVideoFrame->presentationTime(), " expected:", presentationTime)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), "notification of new frame delayed retrieved:"
, lastVideoFrame->presentationTime(), " expected:", presentationTime
)
;
1270#else
1271 UNUSED_PARAM(presentationTime)(void)presentationTime;
1272#endif
1273 VideoFrameMetadata metadata;
1274 metadata.width = m_naturalSize.width();
1275 metadata.height = m_naturalSize.height();
1276 auto metrics = m_renderer->videoPlaybackQualityMetrics();
1277 ASSERT(metrics)((void)0);
1278 metadata.presentedFrames = metrics ? metrics->displayCompositedVideoFrames : 0;
1279 metadata.presentationTime = displayTime;
1280 metadata.expectedDisplayTime = displayTime;
1281 metadata.mediaTime = lastVideoFrame->presentationTime().toDouble();
1282
1283 m_videoFrameMetadata = metadata;
1284 player->onNewVideoFrameMetadata(WTF::move(metadata), lastVideoFrame->pixelBuffer());
1285}
1286
1287void MediaPlayerPrivateMediaSourceAVFObjC::stopVideoFrameMetadataGathering()
1288{
1289 assertIsMainThread();
1290 m_isGatheringVideoFrameMetadata = false;
1291 m_videoFrameMetadata = { };
1292 m_renderer->notifyWhenHasAvailableVideoFrame(nullptr);
1293}
1294
1295std::optional<VideoFrameMetadata> MediaPlayerPrivateMediaSourceAVFObjC::videoFrameMetadata()
1296{
1297 assertIsMainThread();
1298 return std::exchange(m_videoFrameMetadata, { });
1299}
1300
1301void MediaPlayerPrivateMediaSourceAVFObjC::setShouldDisableHDR(bool shouldDisable)
1302{
1303 m_renderer->setShouldDisableHDR(shouldDisable);
1304}
1305
1306void MediaPlayerPrivateMediaSourceAVFObjC::setPlatformDynamicRangeLimit(PlatformDynamicRangeLimit platformDynamicRangeLimit)
1307{
1308 m_renderer->setPlatformDynamicRangeLimit(platformDynamicRangeLimit);
1309}
1310
1311void MediaPlayerPrivateMediaSourceAVFObjC::playerContentBoxRectChanged(const LayoutRect& newRect)
1312{
1313 m_renderer->contentBoxRectChanged(newRect);
1314}
1315
1316WTFLogChannel& MediaPlayerPrivateMediaSourceAVFObjC::logChannel() const
1317{
1318 return LogMediaSource;
1319}
1320
1321void MediaPlayerPrivateMediaSourceAVFObjC::setShouldMaintainAspectRatio(bool shouldMaintainAspectRatio)
1322{
1323 m_renderer->setShouldMaintainAspectRatio(shouldMaintainAspectRatio);
1324}
1325
1326#if HAVE(SPATIAL_TRACKING_LABEL)(defined HAVE_SPATIAL_TRACKING_LABEL && HAVE_SPATIAL_TRACKING_LABEL
)
1327String MediaPlayerPrivateMediaSourceAVFObjC::defaultSpatialTrackingLabel() const
1328{
1329 assertIsMainThread();
1330 return m_defaultSpatialTrackingLabel;
1331}
1332
1333void MediaPlayerPrivateMediaSourceAVFObjC::setDefaultSpatialTrackingLabel(const String& defaultSpatialTrackingLabel)
1334{
1335 assertIsMainThread();
1336 if (m_defaultSpatialTrackingLabel == defaultSpatialTrackingLabel)
1337 return;
1338 m_defaultSpatialTrackingLabel = defaultSpatialTrackingLabel;
1339 updateSpatialTrackingLabel();
1340}
1341
1342String MediaPlayerPrivateMediaSourceAVFObjC::spatialTrackingLabel() const
1343{
1344 assertIsMainThread();
1345 return m_spatialTrackingLabel;
1346}
1347
1348void MediaPlayerPrivateMediaSourceAVFObjC::setSpatialTrackingLabel(const String& spatialTrackingLabel)
1349{
1350 assertIsMainThread();
1351 if (m_spatialTrackingLabel == spatialTrackingLabel)
1352 return;
1353 m_spatialTrackingLabel = spatialTrackingLabel;
1354 updateSpatialTrackingLabel();
1355}
1356
1357void MediaPlayerPrivateMediaSourceAVFObjC::updateSpatialTrackingLabel()
1358{
1359 assertIsMainThread();
1360#if HAVE(SPATIAL_AUDIO_EXPERIENCE)(defined HAVE_SPATIAL_AUDIO_EXPERIENCE && HAVE_SPATIAL_AUDIO_EXPERIENCE
)
1361 RefPtr player = m_player.get();
1362 m_renderer->setSpatialTrackingInfo(player && player->prefersSpatialAudioExperience(), player ? player->soundStageSize() : MediaPlayer::SoundStageSize::Auto, player ? player->sceneIdentifier() : emptyString(), m_defaultSpatialTrackingLabel, m_spatialTrackingLabel);
1363#else
1364 m_renderer->setSpatialTrackingInfo(false, MediaPlayer::SoundStageSize::Auto, { }, m_defaultSpatialTrackingLabel, m_spatialTrackingLabel);
1365#endif
1366}
1367#endif
1368
1369#if ENABLE(LINEAR_MEDIA_PLAYER)(defined ENABLE_LINEAR_MEDIA_PLAYER && ENABLE_LINEAR_MEDIA_PLAYER
)
1370void MediaPlayerPrivateMediaSourceAVFObjC::setVideoTarget(const PlatformVideoTarget& videoTarget)
1371{
1372 ALWAYS_LOG(LOGIDENTIFIER, !!videoTarget)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()), !!videoTarget)
;
1373 m_renderer->setVideoTarget(videoTarget);
1374}
1375#endif
1376
1377#if PLATFORM(IOS_FAMILY)(defined WTF_PLATFORM_IOS_FAMILY && WTF_PLATFORM_IOS_FAMILY
)
1378void MediaPlayerPrivateMediaSourceAVFObjC::sceneIdentifierDidChange()
1379{
1380#if HAVE(SPATIAL_TRACKING_LABEL)(defined HAVE_SPATIAL_TRACKING_LABEL && HAVE_SPATIAL_TRACKING_LABEL
)
1381 updateSpatialTrackingLabel();
1382#endif
1383}
1384
1385void MediaPlayerPrivateMediaSourceAVFObjC::applicationWillResignActive()
1386{
1387 assertIsMainThread();
1388 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
1389 m_renderer->applicationWillResignActive();
1390 m_applicationIsActive = false;
1391}
1392
1393void MediaPlayerPrivateMediaSourceAVFObjC::applicationDidBecomeActive()
1394{
1395 assertIsMainThread();
1396 ALWAYS_LOG(LOGIDENTIFIER)Ref { logger() }->logAlways(logChannel(), WTF::Logger::LogSiteIdentifier
(logClassName(), __func__, logIdentifier()))
;
1397 m_applicationIsActive = true;
1398 flushVideoIfNeeded();
1399}
1400#endif
1401
1402bool MediaPlayerPrivateMediaSourceAVFObjC::supportsLimitedMatroska() const
1403{
1404 assertIsMainThread();
1405 return m_loadOptions.supportsLimitedMatroska;
1406}
1407
1408void MediaPlayerPrivateMediaSourceAVFObjC::isInFullscreenOrPictureInPictureChanged(bool isInFullscreenOrPictureInPicture)
1409{
1410 m_renderer->isInFullscreenOrPictureInPictureChanged(isInFullscreenOrPictureInPicture);
1411}
1412
1413WebCore::HostingContext MediaPlayerPrivateMediaSourceAVFObjC::hostingContext() const
1414{
1415 return m_renderer->hostingContext();
1416}
1417
1418void MediaPlayerPrivateMediaSourceAVFObjC::setVideoLayerSizeFenced(const WebCore::FloatSize& size, WTF::MachSendRightAnnotated&& sendRightAnnotated)
1419{
1420 m_renderer->setVideoLayerSizeFenced(size, WTF::move(sendRightAnnotated));
1421}
1422
1423} // namespace WebCore
1424
1425#endif