Changeset 265167 in webkit
- Timestamp:
- Jul 31, 2020 4:40:06 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r265164 r265167 1 2020-07-31 Jer Noble <jer.noble@apple.com> 2 3 [Mac] YouTube does not offer HDR variants to devices which support HDR 4 https://bugs.webkit.org/show_bug.cgi?id=215022 5 6 Reviewed by Eric Carlson. 7 8 * platform/mac/media/media-source/is-type-supported-vp9-codec-check-expected.txt: Added. 9 * platform/mac/media/media-source/is-type-supported-vp9-codec-check.html: Added. 10 * platform/mac/media/mediacapabilities/vp9-decodingInfo-sw-expected.txt: 11 * platform/mac/media/mediacapabilities/vp9-decodingInfo-sw.html: 12 1 13 2020-07-31 Hector Lopez <hector_i_lopez@apple.com> 2 14 -
trunk/LayoutTests/platform/mac/TestExpectations
r265164 r265167 1915 1915 [ Catalina Mojave ] media/media-source/media-source-webm.html [ Skip ] 1916 1916 [ Catalina Mojave ] platform/mac/media/mediacapabilities/vp9-decodingInfo-sw.html [ Skip ] 1917 [ Catalina Mojave ] platform/mac/media/media-source/is-type-supported-vp9-codec-check.html [ Skip ] 1917 1918 1918 1919 webkit.org/b/214422 imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiocontext-interface/suspend-after-construct.html [ Pass Failure ] -
trunk/LayoutTests/platform/mac/media/mediacapabilities/vp9-decodingInfo-sw-expected.txt
r264476 r265167 7 7 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.00.41.08"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});) 8 8 Promise resolved OK 9 EXPECTED (info.supported == 'true') OK 10 EXPECTED (info.powerEfficient == 'false') OK 11 EXPECTED (info.smooth == 'true') OK 9 EXPECTED (info === '{ supported: true, powerEfficient: false, smooth: true }') OK 12 10 13 11 Test that 4k @ 60fps is supported, but not smooth or powerEfficient 14 12 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.00.41.08"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});) 15 13 Promise resolved OK 16 EXPECTED (info.supported == 'true') OK 17 EXPECTED (info.powerEfficient == 'false') OK 18 EXPECTED (info.smooth == 'false') OK 14 EXPECTED (info === '{ supported: true, powerEfficient: false, smooth: false }') OK 15 16 Test unsupported codec configurations. 17 Profiles 1 and 3 should be unsupported. 18 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.01.41.08"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});) 19 Promise resolved OK 20 EXPECTED (info === '{ supported: false, powerEfficient: false, smooth: false }') OK 21 22 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.03.41.08"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});) 23 Promise resolved OK 24 EXPECTED (info === '{ supported: false, powerEfficient: false, smooth: false }') OK 25 26 Pixel depths above 10 are unsupported. 27 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.00.41.12"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});) 28 Promise resolved OK 29 EXPECTED (info === '{ supported: false, powerEfficient: false, smooth: false }') OK 30 31 Chroma subsampling 422 or 444 are unsupported. 32 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.00.41.08.02.01.01.01.01"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});) 33 Promise resolved OK 34 EXPECTED (info === '{ supported: false, powerEfficient: false, smooth: false }') OK 35 36 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.00.41.08.03.01.01.01.01"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});) 37 Promise resolved OK 38 EXPECTED (info === '{ supported: false, powerEfficient: false, smooth: false }') OK 19 39 20 40 Test that SW VP9 decoder is not supported on battery power when screen is not 4k resolution … … 22 42 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.00.41.08"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});) 23 43 Promise resolved OK 24 EXPECTED (info.supported == 'false') OK 25 EXPECTED (info.powerEfficient == 'false') OK 26 EXPECTED (info.smooth == 'false') OK 44 EXPECTED (info === '{ supported: false, powerEfficient: false, smooth: false }') OK 27 45 28 46 Test that SW VP9 decoder is supported on battery power when screen is at least 4k resolution … … 30 48 RUN(promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs="vp09.00.41.08"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});) 31 49 Promise resolved OK 32 EXPECTED (info.supported == 'true') OK 33 EXPECTED (info.powerEfficient == 'false') OK 34 EXPECTED (info.smooth == 'true') OK 50 EXPECTED (info === '{ supported: true, powerEfficient: false, smooth: true }') OK 35 51 END OF TEST 36 52 -
trunk/LayoutTests/platform/mac/media/mediacapabilities/vp9-decodingInfo-sw.html
r264476 r265167 6 6 var promise; 7 7 var info; 8 9 function MediaCapabilitiesInfoToString(info) { 10 try { 11 return `{ supported: ${ info.supported }, powerEfficient: ${ info.powerEfficient }, smooth: ${ info.smooth } }`; 12 } catch(e) { 13 return `{ ${set} }`; 14 } 15 } 16 17 function isEqualMediaCapabilitiesInfo(infoA, infoB) { 18 try { 19 return infoA.supported === infoB.supported 20 && infoA.powerEfficient === infoB.powerEfficient 21 && infoA.smooth === infoB.smooth; 22 } catch(e) { 23 return false; 24 } 25 } 26 27 function testExpectedMediaCapabilitiesInfo(testFuncString, expected) 28 { 29 let observed = eval(testFuncString); 30 let success = isEqualMediaCapabilitiesInfo(observed, expected); 31 reportExpected(success, testFuncString, '===', MediaCapabilitiesInfoToString(expected), MediaCapabilitiesInfoToString(observed)); 32 } 8 33 9 34 async function doTest() … … 23 48 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.00.41.08\"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});"); 24 49 info = await shouldResolve(promise); 25 testExpected('info.supported', true); 26 testExpected('info.powerEfficient', false); 27 testExpected('info.smooth', true); 50 testExpectedMediaCapabilitiesInfo('info', {supported: true, powerEfficient: false, smooth: true}); 28 51 29 52 consoleWrite(''); … … 32 55 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.00.41.08\"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});"); 33 56 info = await shouldResolve(promise); 34 testExpected('info.supported', true); 35 testExpected('info.powerEfficient', false); 36 testExpected('info.smooth', false); 57 testExpectedMediaCapabilitiesInfo('info', {supported: true, powerEfficient: false, smooth: false}); 58 59 consoleWrite(''); 60 consoleWrite('Test unsupported codec configurations.'); 61 consoleWrite('Profiles 1 and 3 should be unsupported.'); 62 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.01.41.08\"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});"); 63 info = await shouldResolve(promise); 64 testExpectedMediaCapabilitiesInfo('info', {supported: false, powerEfficient: false, smooth: false}); 65 66 consoleWrite(''); 67 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.03.41.08\"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});"); 68 info = await shouldResolve(promise); 69 testExpectedMediaCapabilitiesInfo('info', {supported: false, powerEfficient: false, smooth: false}); 70 71 consoleWrite(''); 72 consoleWrite('Pixel depths above 10 are unsupported.'); 73 74 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.00.41.12\"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});"); 75 info = await shouldResolve(promise); 76 testExpectedMediaCapabilitiesInfo('info', {supported: false, powerEfficient: false, smooth: false}); 77 78 consoleWrite(''); 79 consoleWrite('Chroma subsampling 422 or 444 are unsupported.'); 80 81 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.00.41.08.02.01.01.01.01\"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});"); 82 info = await shouldResolve(promise); 83 testExpectedMediaCapabilitiesInfo('info', {supported: false, powerEfficient: false, smooth: false}); 84 85 consoleWrite(''); 86 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.00.41.08.03.01.01.01.01\"', height: 1080, bitrate: 800000, width: 3180, framerate: 60 }});"); 87 info = await shouldResolve(promise); 88 testExpectedMediaCapabilitiesInfo('info', {supported: false, powerEfficient: false, smooth: false}); 37 89 38 90 consoleWrite(''); … … 41 93 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.00.41.08\"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});"); 42 94 info = await shouldResolve(promise); 43 testExpected('info.supported', false); 44 testExpected('info.powerEfficient', false); 45 testExpected('info.smooth', false); 95 testExpectedMediaCapabilitiesInfo('info', {supported: false, powerEfficient: false, smooth: false}); 46 96 47 97 consoleWrite(''); … … 50 100 run("promise = navigator.mediaCapabilities.decodingInfo({ type: 'media-source', video: { contentType: 'video/mp4; codecs=\"vp09.00.41.08\"', height: 1080, bitrate: 800000, width: 3180, framerate: 30 }});"); 51 101 info = await shouldResolve(promise); 52 testExpected('info.supported', true); 53 testExpected('info.powerEfficient', false); 54 testExpected('info.smooth', true); 102 testExpectedMediaCapabilitiesInfo('info', {supported: true, powerEfficient: false, smooth: true}); 55 103 56 104 endTest(); -
trunk/Source/WebCore/ChangeLog
r265165 r265167 1 2020-07-31 Jer Noble <jer.noble@apple.com> 2 3 [Mac] YouTube does not offer HDR variants to devices which support HDR 4 https://bugs.webkit.org/show_bug.cgi?id=215022 5 6 Reviewed by Eric Carlson. 7 8 Test: platform/mac/media/media-source/is-type-supported-vp9-codec-check.html 9 10 There are three separate issues which block YouTube from offering HDR: 11 12 1) YouTube checks both valid and invalid VP9 strings through MediaSource.isTypeSupported(), and UAs 13 which answer `true` to even invalid VP9 strings are blocked from HDR. To solve this, we will now 14 send isTypeSupported() through the same code path as Media Capabilities. 15 16 2) YouTube's standard valid and invalid VP9 strings do not include the fullRangeVideoFlag field, which 17 would normally be tossed as invalid. We shouldn't relax our requirements globally, so we will 18 add a Quirk which relaxes the requriement that VP9 strings contain a fullRangeVideoFlag. 19 20 3) YouTube's HDR query checks that window.screen.pixelDepth is > 24. We obviously don't want to change 21 the value of this field globally, so we will add separate Quirk which sets window.screen.pixelDepth 22 to 25 (a totally nonsensical value) when HDR is available. 23 24 Each of these Quirks has a path towards removal for YouTube. The fullRangeVideoFlag field involves 25 YouTube updating their compatibility check to inculde the fullRangeVideoFlag. The pixelDepth check 26 can be replaced by the `dynamic-range:high` Media Query. 27 28 * Modules/mediasource/MediaSource.cpp: 29 (WebCore::addVP9FullRangeVideoFlagToContentType): 30 (WebCore::MediaSource::addSourceBuffer): 31 (WebCore::MediaSource::removeSourceBuffer): 32 (WebCore::MediaSource::isTypeSupported): 33 (WebCore::MediaSource::onReadyStateChange): 34 (WebCore::MediaSource::activeRanges const): 35 * Modules/mediasource/MediaSource.h: 36 * page/Quirks.cpp: 37 (WebCore::Quirks::needsVP9FullRangeFlagQuirk const): 38 (WebCore::Quirks::needsHDRPixelDepthQuirk const): 39 * page/Quirks.h: 40 * page/Screen.cpp: 41 (WebCore::Screen::pixelDepth const): 42 * platform/graphics/cocoa/SourceBufferParserWebM.cpp: 43 (WebCore::SourceBufferParserWebM::isContentTypeSupported): 44 * platform/graphics/cocoa/VP9UtilitiesCocoa.h: 45 * platform/graphics/cocoa/VP9UtilitiesCocoa.mm: 46 (WebCore::isVPCodecConfigurationRecordSupported): 47 (WebCore::validateVPParameters): 48 1 49 2020-07-31 Chris Dumez <cdumez@apple.com> 2 50 -
trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp
r264164 r265167 43 43 #include "MediaSourcePrivate.h" 44 44 #include "MediaSourceRegistry.h" 45 #include "Quirks.h" 45 46 #include "Settings.h" 46 47 #include "SourceBuffer.h" … … 660 661 } 661 662 663 static ContentType addVP9FullRangeVideoFlagToContentType(const ContentType& type) 664 { 665 auto countPeriods = [] (const String& codec) { 666 unsigned count = 0; 667 unsigned position = 0; 668 669 while (codec.find('.', position) != notFound) { 670 ++count; 671 ++position; 672 } 673 674 return count; 675 }; 676 677 for (auto codec : type.codecs()) { 678 if (!codec.startsWith("vp09") || countPeriods(codec) != 7) 679 continue; 680 681 auto rawType = type.raw(); 682 auto position = rawType.find(codec); 683 ASSERT(position != notFound); 684 if (position == notFound) 685 continue; 686 687 rawType.insert(".00", position + codec.length()); 688 return ContentType(rawType); 689 } 690 return type; 691 } 692 662 693 ExceptionOr<Ref<SourceBuffer>> MediaSource::addSourceBuffer(const String& type) 663 694 { … … 677 708 mediaContentTypesRequiringHardwareSupport.appendVector(m_mediaElement->document().settings().mediaContentTypesRequiringHardwareSupport()); 678 709 679 if (!isTypeSupported(type, WTFMove(mediaContentTypesRequiringHardwareSupport))) 710 auto context = scriptExecutionContext(); 711 if (!context) 712 return Exception { NotAllowedError }; 713 714 if (!isTypeSupported(*context, type, WTFMove(mediaContentTypesRequiringHardwareSupport))) 680 715 return Exception { NotSupportedError }; 681 716 … … 687 722 // 5. Create a new SourceBuffer object and associated resources. 688 723 ContentType contentType(type); 724 if (context->isDocument() && downcast<Document>(context)->quirks().needsVP9FullRangeFlagQuirk()) 725 contentType = addVP9FullRangeVideoFlagToContentType(contentType); 726 689 727 auto sourceBufferPrivate = createSourceBufferPrivate(contentType); 690 728 … … 877 915 } 878 916 879 return isTypeSupported( type, WTFMove(mediaContentTypesRequiringHardwareSupport));880 } 881 882 bool MediaSource::isTypeSupported( const String& type, Vector<ContentType>&& contentTypesRequiringHardwareSupport)917 return isTypeSupported(context, type, WTFMove(mediaContentTypesRequiringHardwareSupport)); 918 } 919 920 bool MediaSource::isTypeSupported(ScriptExecutionContext& context, const String& type, Vector<ContentType>&& contentTypesRequiringHardwareSupport) 883 921 { 884 922 // Section 2.2 isTypeSupported() method steps. … … 889 927 890 928 ContentType contentType(type); 929 if (context.isDocument() && downcast<Document>(context).quirks().needsVP9FullRangeFlagQuirk()) 930 contentType = addVP9FullRangeVideoFlagToContentType(contentType); 931 891 932 String codecs = contentType.parameter("codecs"); 892 933 … … 1033 1074 } 1034 1075 1035 ExceptionOr<Ref<SourceBufferPrivate>> MediaSource::createSourceBufferPrivate(const ContentType& type) 1036 { 1076 ExceptionOr<Ref<SourceBufferPrivate>> MediaSource::createSourceBufferPrivate(const ContentType& incomingType) 1077 { 1078 ContentType type { incomingType }; 1079 1080 auto context = scriptExecutionContext(); 1081 if (context && context->isDocument() && downcast<Document>(context)->quirks().needsVP9FullRangeFlagQuirk()) 1082 type = addVP9FullRangeVideoFlagToContentType(incomingType); 1083 1037 1084 RefPtr<SourceBufferPrivate> sourceBufferPrivate; 1038 1085 switch (m_private->addSourceBuffer(type, sourceBufferPrivate)) { -
trunk/Source/WebCore/Modules/mediasource/MediaSource.h
r264164 r265167 131 131 const char* activeDOMObjectName() const final; 132 132 bool virtualHasPendingActivity() const final; 133 static bool isTypeSupported( const String& type, Vector<ContentType>&& contentTypesRequiringHardwareSupport);133 static bool isTypeSupported(ScriptExecutionContext&, const String& type, Vector<ContentType>&& contentTypesRequiringHardwareSupport); 134 134 135 135 void setPrivateAndOpen(Ref<MediaSourcePrivate>&&) final; -
trunk/Source/WebCore/page/Quirks.cpp
r265067 r265167 962 962 } 963 963 964 } 964 bool Quirks::needsVP9FullRangeFlagQuirk() const 965 { 966 if (!needsQuirks()) 967 return false; 968 969 if (!m_needsVP9FullRangeFlagQuirk) 970 m_needsVP9FullRangeFlagQuirk = equalLettersIgnoringASCIICase(m_document->url().host(), "www.youtube.com"); 971 972 return *m_needsVP9FullRangeFlagQuirk; 973 } 974 975 bool Quirks::needsHDRPixelDepthQuirk() const 976 { 977 if (!needsQuirks()) 978 return false; 979 980 if (!m_needsHDRPixelDepthQuirk) 981 m_needsHDRPixelDepthQuirk = equalLettersIgnoringASCIICase(m_document->url().host(), "www.youtube.com"); 982 983 return *m_needsHDRPixelDepthQuirk; 984 } 985 986 987 } -
trunk/Source/WebCore/page/Quirks.h
r264001 r265167 109 109 StorageAccessResult triggerOptionalStorageAccessQuirk(const Element&, const AtomString& eventType) const; 110 110 111 bool needsVP9FullRangeFlagQuirk() const; 112 bool needsHDRPixelDepthQuirk() const; 113 111 114 private: 112 115 bool needsQuirks() const; … … 134 137 mutable Optional<bool> m_needsCanPlayAfterSeekedQuirk; 135 138 mutable Optional<bool> m_shouldBypassAsyncScriptDeferring; 139 mutable Optional<bool> m_needsVP9FullRangeFlagQuirk; 140 mutable Optional<bool> m_needsHDRPixelDepthQuirk; 136 141 }; 137 142 -
trunk/Source/WebCore/page/Screen.cpp
r243887 r265167 34 34 #include "FrameView.h" 35 35 #include "PlatformScreen.h" 36 #include "Quirks.h" 36 37 #include "ResourceLoadObserver.h" 37 38 #include "RuntimeEnabledFeatures.h" … … 86 87 if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) 87 88 ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::PixelDepth); 88 return static_cast<unsigned>(screenDepth(frame->view())); 89 90 auto* document = window()->document(); 91 if (!document || !document->quirks().needsHDRPixelDepthQuirk() || !screenSupportsHighDynamicRange(frame->view())) 92 return static_cast<unsigned>(screenDepth(frame->view())); 93 94 return static_cast<unsigned>(screenDepth(frame->view())) + 1; 89 95 } 90 96 -
trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp
r265079 r265167 244 244 for (auto split : splitResults) { 245 245 if (split.startsWith("vp09")) { 246 if (!isVP9DecoderAvailable()) 246 auto codecParameters = parseVPCodecParameters(split); 247 if (!codecParameters) 247 248 return MediaPlayerEnums::SupportsType::IsNotSupported; 249 250 if (!isVPCodecConfigurationRecordSupported(*codecParameters)) 251 return MediaPlayerEnums::SupportsType::IsNotSupported; 252 248 253 continue; 249 254 } -
trunk/Source/WebCore/platform/graphics/cocoa/VP9UtilitiesCocoa.h
r265095 r265167 42 42 WEBCORE_EXPORT extern void registerSupplementalVP9Decoder(); 43 43 extern bool isVP9DecoderAvailable(); 44 extern bool isVPCodecConfigurationRecordSupported(VPCodecConfigurationRecord&); 44 45 extern bool validateVPParameters(VPCodecConfigurationRecord&, MediaCapabilitiesInfo&, const VideoConfiguration&); 45 46 -
trunk/Source/WebCore/platform/graphics/cocoa/VP9UtilitiesCocoa.mm
r265095 r265167 119 119 } 120 120 121 bool validateVPParameters(VPCodecConfigurationRecord& codecConfiguration, MediaCapabilitiesInfo& info, const VideoConfiguration& videoConfiguration)121 bool isVPCodecConfigurationRecordSupported(VPCodecConfigurationRecord& codecConfiguration) 122 122 { 123 123 if (!isVP9DecoderAvailable()) 124 124 return false; 125 125 126 // VideoConfiguration and VPCodecConfigurationRecord can have conflicting values for HDR properties. If so, reject. 127 if (videoConfiguration.transferFunction) { 128 // Note: Transfer Characteristics are defined by ISO/IEC 23091-2:2019. 129 if (*videoConfiguration.transferFunction == TransferFunction::SRGB && codecConfiguration.transferCharacteristics > 15) 130 return false; 131 if (*videoConfiguration.transferFunction == TransferFunction::PQ && codecConfiguration.transferCharacteristics != 16) 132 return false; 133 if (*videoConfiguration.transferFunction == TransferFunction::HLG && codecConfiguration.transferCharacteristics != 18) 134 return false; 135 } 136 137 if (videoConfiguration.colorGamut) { 138 if (*videoConfiguration.colorGamut == ColorGamut::Rec2020 && codecConfiguration.colorPrimaries != 9) 139 return false; 140 } 141 142 if (canLoad_VideoToolbox_VTIsHardwareDecodeSupported() && VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9) && !hardwareVP9DecoderDisabledForTesting) { 143 info.powerEfficient = true; 144 145 // HW VP9 Decoder supports Profile 0 & 2: 146 if (codecConfiguration.profile && codecConfiguration.profile != 2) 147 return false; 148 149 // HW VP9 Decoder supports up to Level 6: 150 if (codecConfiguration.level > VPConfigurationLevel::Level_6) 151 return false; 152 153 // HW VP9 Decoder supports 8 or 10 bit color: 154 if (codecConfiguration.bitDepth > 10) 155 return false; 156 157 // HW VP9 Decoder suports only 420 chroma subsampling: 158 if (codecConfiguration.chromaSubsampling > VPConfigurationChromaSubsampling::Subsampling_420_Colocated) 159 return false; 160 161 // HW VP9 Decoder does not support alpha channel: 162 if (videoConfiguration.alphaChannel && *videoConfiguration.alphaChannel) 163 return false; 164 165 // HW VP9 Decoder can support up to 4K @ 120 or 8K @ 30 166 auto resolution = resolutionCategory({ (float)videoConfiguration.width, (float)videoConfiguration.height }); 167 if (resolution > ResolutionCategory::R_8K) 168 return false; 169 if (resolution == ResolutionCategory::R_8K && videoConfiguration.framerate > 30) 170 info.smooth = false; 171 else if (resolution <= ResolutionCategory::R_4K && videoConfiguration.framerate > 120) 172 info.smooth = false; 173 else 174 info.smooth = true; 175 176 return true; 177 } 178 179 // SW VP9 Decoder has much more variable capabilities depending on CPU characteristics. 180 // FIXME: Add a lookup table for device-to-capabilities. For now, assume that the SW VP9 181 // decoder can support 4K @ 30. 182 if (videoConfiguration.height <= 1080 && videoConfiguration.framerate > 60) 183 info.smooth = false; 184 if (videoConfiguration.height <= 2160 && videoConfiguration.framerate > 30) 185 info.smooth = false; 186 else 187 info.smooth = true; 126 // HW & SW VP9 Decoders support Profile 0 & 2: 127 if (codecConfiguration.profile && codecConfiguration.profile != 2) 128 return false; 129 130 // HW & SW VP9 Decoders support only 420 chroma subsampling: 131 if (codecConfiguration.chromaSubsampling > VPConfigurationChromaSubsampling::Subsampling_420_Colocated) 132 return false; 133 134 // HW & SW VP9 Decoders support 8 or 10 bit color: 135 if (codecConfiguration.bitDepth > 10) 136 return false; 137 138 // HW & SW VP9 Decoders support up to Level 6: 139 if (codecConfiguration.level > VPConfigurationLevel::Level_6) 140 return false; 141 142 // Hardware decoders are always available. 143 if (canLoad_VideoToolbox_VTIsHardwareDecodeSupported() && VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9) && !hardwareVP9DecoderDisabledForTesting) 144 return true; 188 145 189 146 // For wall-powered devices, always report VP9 as supported, even if not powerEfficient. 190 if (!systemHasBattery()) { 191 info.supported = true; 192 return true; 193 } 147 if (!systemHasBattery()) 148 return true; 194 149 195 150 // For battery-powered devices, always report VP9 as supported when running on AC power, 196 151 // but only on battery when there is an attached screen whose resolution is large enough 197 152 // to support 4K video. 198 if (systemHasAC()) { 199 info.supported = true; 200 return true; 201 } 153 if (systemHasAC()) 154 return true; 202 155 203 156 bool has4kScreen = false; … … 215 168 } 216 169 217 if (!has4kScreen) { 218 info.supported = false; 219 return false; 220 } 221 170 return has4kScreen; 171 } 172 173 bool validateVPParameters(VPCodecConfigurationRecord& codecConfiguration, MediaCapabilitiesInfo& info, const VideoConfiguration& videoConfiguration) 174 { 175 if (!isVPCodecConfigurationRecordSupported(codecConfiguration)) 176 return false; 177 178 // VideoConfiguration and VPCodecConfigurationRecord can have conflicting values for HDR properties. If so, reject. 179 if (videoConfiguration.transferFunction) { 180 // Note: Transfer Characteristics are defined by ISO/IEC 23091-2:2019. 181 if (*videoConfiguration.transferFunction == TransferFunction::SRGB && codecConfiguration.transferCharacteristics > 15) 182 return false; 183 if (*videoConfiguration.transferFunction == TransferFunction::PQ && codecConfiguration.transferCharacteristics != 16) 184 return false; 185 if (*videoConfiguration.transferFunction == TransferFunction::HLG && codecConfiguration.transferCharacteristics != 18) 186 return false; 187 } 188 189 if (videoConfiguration.colorGamut) { 190 if (*videoConfiguration.colorGamut == ColorGamut::Rec2020 && codecConfiguration.colorPrimaries != 9) 191 return false; 192 } 193 194 if (canLoad_VideoToolbox_VTIsHardwareDecodeSupported() && VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9) && !hardwareVP9DecoderDisabledForTesting) { 195 // HW VP9 Decoder does not support alpha channel: 196 if (videoConfiguration.alphaChannel && *videoConfiguration.alphaChannel) 197 return false; 198 199 // HW VP9 Decoder can support up to 4K @ 120 or 8K @ 30 200 auto resolution = resolutionCategory({ (float)videoConfiguration.width, (float)videoConfiguration.height }); 201 if (resolution > ResolutionCategory::R_8K) 202 return false; 203 if (resolution == ResolutionCategory::R_8K && videoConfiguration.framerate > 30) 204 info.smooth = false; 205 else if (resolution <= ResolutionCategory::R_4K && videoConfiguration.framerate > 120) 206 info.smooth = false; 207 else 208 info.smooth = true; 209 210 info.powerEfficient = true; 211 info.supported = true; 212 return true; 213 } 214 215 info.powerEfficient = false; 216 217 // SW VP9 Decoder has much more variable capabilities depending on CPU characteristics. 218 // FIXME: Add a lookup table for device-to-capabilities. For now, assume that the SW VP9 219 // decoder can support 4K @ 30. 220 if (videoConfiguration.height <= 1080 && videoConfiguration.framerate > 60) 221 info.smooth = false; 222 if (videoConfiguration.height <= 2160 && videoConfiguration.framerate > 30) 223 info.smooth = false; 224 else 225 info.smooth = true; 226 227 // For wall-powered devices, always report VP9 as supported, even if not powerEfficient. 228 if (!systemHasBattery()) { 229 info.supported = true; 230 return true; 231 } 232 233 // For battery-powered devices, always report VP9 as supported when running on AC power, 234 // but only on battery when there is an attached screen whose resolution is large enough 235 // to support 4K video. 236 if (systemHasAC()) { 237 info.supported = true; 238 return true; 239 } 240 241 bool has4kScreen = false; 242 243 if (screenSizeAndScaleForTesting) { 244 auto screenSize = FloatSize(screenSizeAndScaleForTesting->width, screenSizeAndScaleForTesting->height).scaled(screenSizeAndScaleForTesting->scale); 245 has4kScreen = resolutionCategory(screenSize) >= ResolutionCategory::R_4K; 246 } else { 247 for (auto& screenData : getScreenProperties().screenDataMap.values()) { 248 if (resolutionCategory(screenData.screenRect.size().scaled(screenData.scaleFactor)) >= ResolutionCategory::R_4K) { 249 has4kScreen = true; 250 break; 251 } 252 } 253 } 254 255 if (!has4kScreen) 256 return false; 257 258 info.supported = true; 222 259 return true; 223 260 }
Note: See TracChangeset
for help on using the changeset viewer.