Skip to content
Permalink
Browse files
Fix canPlayType for WebM VP8 on older Macs without VP9
https://bugs.webkit.org/show_bug.cgi?id=241920

Reviewed by Eric Carlson and Jean-Yves Avenard.
Original patch by: Brion Vibber <brion@pobox.com>
Patch amended by: Youssef Soliman <y_soliman@apple.com>

SourceBufferParserWebM::isContentTypeSupported called
isVP9DecoderAvailable for both VP9 and VP8 codecs, which caused
some older Macs to misreport a failure of VP8 support in
HTMLMediaElement.canPlayType, MediaSource.isTypeSupported, and
the filtering of video sources based on codec lists.

Example of failing hardware is an early-2015 13" MacBook Pro,
whose integrated GPU supports VP8 but not VP9. A test case
is not included as I was unable to replicate the failing
conditions at runtime by adding disable-for-testing options
successfully.

* platform/graphics/cocoa/SourceBufferParserWebM.cpp:
(SourceBufferParserWebM::isContentTypeSupported): Included
calls to isVP8DecoderAvailable as appropriate.
* LayoutTests/media/media-source/media-source-istypesupported-vp8-without-vp9-expected.txt: Added.
* LayoutTests/media/media-source/media-source-istypesupported-vp8-without-vp9.html: Added.
* Source/WebCore/platform/graphics/cocoa/VP9UtilitiesCocoa.h:
* Source/WebCore/platform/graphics/cocoa/VP9UtilitiesCocoa.mm:
(WebCore::VP9TestingOverrides::setVP9DecoderDisabled):
(WebCore::isVP9DecoderAvailable):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::Internals):
(WebCore::Internals::setVP9DecoderDisabledForTesting):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp:
(WebKit::GPUConnectionToWebProcess::setMediaOverridesForTesting):
* Source/WebKit/WebProcess/GPU/GPUProcessConnection.cpp:
(WebKit::GPUProcessConnection::updateMediaConfiguration):
* Source/WebKit/WebProcess/GPU/media/MediaOverridesForTesting.h:
(WebKit::MediaOverridesForTesting::encode const):
(WebKit::MediaOverridesForTesting::decode):

Canonical link: https://commits.webkit.org/254013@main
  • Loading branch information
brion authored and youssefsoli committed Aug 31, 2022
1 parent 44e0bb9 commit 5706f1c79429a78d8dadf72c0a9293cf8bb0fa29
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 9 deletions.
@@ -0,0 +1,11 @@

Test that WebM VP8 is supported when the VP9 decoder is not available.

These tests may be expected to fail if the WebKit port does not support the format.

Forcing VP9 decoder to be enabled.
EXPECTED (MediaSource.isTypeSupported('video/webm; codecs=vp8') == 'true') OK
Forcing VP9 decoder to be disabled.
EXPECTED (MediaSource.isTypeSupported('video/webm; codecs=vp8.0') == 'true') OK
END OF TEST

@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<script src="../video-test.js"></script>
<script>
function start() {
if (!window.internals) {
failTest('This test requires window.internals.');
return;
}

consoleWrite('Forcing VP9 decoder to be enabled.')
internals.setVP9DecoderDisabledForTesting(false);
testExpected("MediaSource.isTypeSupported('video/webm; codecs=vp8')", true);

consoleWrite('Forcing VP9 decoder to be disabled.')
internals.setVP9DecoderDisabledForTesting(true);
// vp8.0 is used since isTypeSupported caches results
testExpected("MediaSource.isTypeSupported('video/webm; codecs=vp8.0')", true);

endTest();
}
</script>
</head>
<body onload="start()">
<video controls></video>
<p>Test that WebM VP8 is supported when the VP9 decoder is not available.</p>
<p>These tests may be expected to fail if the WebKit port does not support the format.</p>
</body>
</html>
@@ -1310,6 +1310,7 @@ MediaPlayerEnums::SupportsType SourceBufferParserWebM::isContentTypeSupported(co
bool isAnyCodecAvailable = isAnyAudioCodecAvailable;
#if ENABLE(VP9)
isAnyCodecAvailable |= isVP9DecoderAvailable();
isAnyCodecAvailable |= isVP8DecoderAvailable();
#endif

if (!isAnyCodecAvailable)
@@ -1321,14 +1322,13 @@ MediaPlayerEnums::SupportsType SourceBufferParserWebM::isContentTypeSupported(co

for (auto& codec : codecs) {
#if ENABLE(VP9)
if (codec.startsWith("vp09"_s)
|| codec.startsWith("vp08"_s)
|| equal(codec, "vp8"_s)
|| equal(codec, "vp9"_s)
|| equal(codec, "vp8.0"_s)
|| equal(codec, "vp9.0"_s)) {

if (!isVP9DecoderAvailable())
bool isVP9 = codec.startsWith("vp09"_s) || equal(codec, "vp9"_s) || equal(codec, "vp9.0"_s);
bool isVP8 = codec.startsWith("vp08"_s) || equal(codec, "vp8"_s) || equal(codec, "vp8.0"_s);
if (isVP9 || isVP8) {

if (isVP9 && !isVP9DecoderAvailable())
return MediaPlayerEnums::SupportsType::IsNotSupported;
if (isVP8 && !isVP8DecoderAvailable())
return MediaPlayerEnums::SupportsType::IsNotSupported;

auto codecParameters = parseVPCodecParameters(codec);
@@ -75,6 +75,9 @@ class WEBCORE_EXPORT VP9TestingOverrides {

void setHardwareDecoderDisabled(std::optional<bool>&&);
std::optional<bool> hardwareDecoderDisabled() { return m_hardwareDecoderDisabled; }

void setVP9DecoderDisabled(std::optional<bool>&&);
std::optional<bool> vp9DecoderDisabled() { return m_vp9DecoderDisabled; }

void setVP9ScreenSizeAndScale(std::optional<ScreenDataOverrides>&&);
std::optional<ScreenDataOverrides> vp9ScreenSizeAndScale() { return m_screenSizeAndScale; }
@@ -83,6 +86,7 @@ class WEBCORE_EXPORT VP9TestingOverrides {

private:
std::optional<bool> m_hardwareDecoderDisabled;
std::optional<bool> m_vp9DecoderDisabled;
std::optional<ScreenDataOverrides> m_screenSizeAndScale;
Function<void()> m_configurationChangedCallback;
};
@@ -63,6 +63,13 @@
m_configurationChangedCallback();
}

void VP9TestingOverrides::setVP9DecoderDisabled(std::optional<bool>&& disabled)
{
m_vp9DecoderDisabled = WTFMove(disabled);
if (m_configurationChangedCallback)
m_configurationChangedCallback();
}

void VP9TestingOverrides::setVP9ScreenSizeAndScale(std::optional<ScreenDataOverrides>&& overrides)
{
m_screenSizeAndScale = WTFMove(overrides);
@@ -124,6 +131,9 @@ void registerSupplementalVP9Decoder()

bool isVP9DecoderAvailable()
{
if (auto disabledForTesting = VP9TestingOverrides::singleton().vp9DecoderDisabled())
return !*disabledForTesting;

#if PLATFORM(IOS)
return canLoad_VideoToolbox_VTIsHardwareDecodeSupported() && VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9);
#else
@@ -706,6 +706,7 @@ Internals::Internals(Document& document)

#if ENABLE(VP9) && PLATFORM(COCOA)
VP9TestingOverrides::singleton().setHardwareDecoderDisabled(std::nullopt);
VP9TestingOverrides::singleton().setVP9DecoderDisabled(std::nullopt);
VP9TestingOverrides::singleton().setVP9ScreenSizeAndScale(std::nullopt);
#endif
}
@@ -6418,6 +6419,15 @@ void Internals::setHardwareVP9DecoderDisabledForTesting(bool disabled)
#endif
}

void Internals::setVP9DecoderDisabledForTesting(bool disabled)
{
#if ENABLE(VP9) && PLATFORM(COCOA)
VP9TestingOverrides::singleton().setVP9DecoderDisabled(disabled);
#else
UNUSED_PARAM(disabled);
#endif
}

void Internals::setVP9ScreenSizeAndScaleForTesting(double width, double height, double scale)
{
#if ENABLE(VP9) && PLATFORM(COCOA)
@@ -1237,6 +1237,7 @@ class Internals final : public RefCounted<Internals>, private ContextDestruction
void setSystemHasACForTesting(bool);

void setHardwareVP9DecoderDisabledForTesting(bool);
void setVP9DecoderDisabledForTesting(bool);
void setVP9ScreenSizeAndScaleForTesting(double, double, double);

int readPreferenceInteger(const String& domain, const String& key);
@@ -1107,6 +1107,7 @@ typedef (FetchRequest or FetchResponse) FetchObject;
undefined setSystemHasACForTesting(boolean hasAC);

undefined setHardwareVP9DecoderDisabledForTesting(boolean disabled);
undefined setVP9DecoderDisabledForTesting(boolean disabled);
undefined setVP9ScreenSizeAndScaleForTesting(double width, double height, double scale);

long readPreferenceInteger(DOMString domain, DOMString key);
@@ -710,6 +710,7 @@ void GPUConnectionToWebProcess::setMediaOverridesForTesting(MediaOverridesForTes
{
#if ENABLE(VP9) && PLATFORM(COCOA)
VP9TestingOverrides::singleton().setHardwareDecoderDisabled(WTFMove(overrides.vp9HardwareDecoderDisabled));
VP9TestingOverrides::singleton().setVP9DecoderDisabled(WTFMove(overrides.vp9DecoderDisabled));
VP9TestingOverrides::singleton().setVP9ScreenSizeAndScale(WTFMove(overrides.vp9ScreenSizeAndScale));
#endif

@@ -400,7 +400,9 @@ void GPUProcessConnection::updateMediaConfiguration()
settingsChanged = true;

#if ENABLE(VP9)
if (m_mediaOverridesForTesting.vp9HardwareDecoderDisabled != VP9TestingOverrides::singleton().hardwareDecoderDisabled() || m_mediaOverridesForTesting.vp9ScreenSizeAndScale != VP9TestingOverrides::singleton().vp9ScreenSizeAndScale())
if (m_mediaOverridesForTesting.vp9HardwareDecoderDisabled != VP9TestingOverrides::singleton().hardwareDecoderDisabled()
|| m_mediaOverridesForTesting.vp9DecoderDisabled != VP9TestingOverrides::singleton().vp9DecoderDisabled()
|| m_mediaOverridesForTesting.vp9ScreenSizeAndScale != VP9TestingOverrides::singleton().vp9ScreenSizeAndScale())
settingsChanged = true;
#endif

@@ -413,6 +415,7 @@ void GPUProcessConnection::updateMediaConfiguration()

#if ENABLE(VP9)
.vp9HardwareDecoderDisabled = VP9TestingOverrides::singleton().hardwareDecoderDisabled(),
.vp9DecoderDisabled = VP9TestingOverrides::singleton().vp9DecoderDisabled(),
.vp9ScreenSizeAndScale = VP9TestingOverrides::singleton().vp9ScreenSizeAndScale(),
#endif
};
@@ -36,6 +36,7 @@ struct MediaOverridesForTesting {
std::optional<bool> systemHasBattery;

std::optional<bool> vp9HardwareDecoderDisabled;
std::optional<bool> vp9DecoderDisabled;
std::optional<WebCore::ScreenDataOverrides> vp9ScreenSizeAndScale;

template<class Encoder>
@@ -44,6 +45,7 @@ struct MediaOverridesForTesting {
encoder << systemHasAC;
encoder << systemHasBattery;
encoder << vp9HardwareDecoderDisabled;
encoder << vp9DecoderDisabled;
encoder << vp9ScreenSizeAndScale;
}

@@ -64,6 +66,11 @@ struct MediaOverridesForTesting {
decoder >> vp9HardwareDecoderDisabled;
if (!vp9HardwareDecoderDisabled)
return std::nullopt;

std::optional<std::optional<bool>> vp9DecoderDisabled;
decoder >> vp9DecoderDisabled;
if (!vp9DecoderDisabled)
return std::nullopt;

std::optional<std::optional<WebCore::ScreenDataOverrides>> vp9ScreenSizeAndScale;
decoder >> vp9ScreenSizeAndScale;
@@ -74,6 +81,7 @@ struct MediaOverridesForTesting {
*systemHasAC,
*systemHasBattery,
*vp9HardwareDecoderDisabled,
*vp9DecoderDisabled,
*vp9ScreenSizeAndScale,
}};
}

0 comments on commit 5706f1c

Please sign in to comment.