0

HDR MediaCapabilities: Add flag to report smpteSt2086 as supported

This CL adds a feature ("SupportSmpteSt2086HdrMetadata") which
enables the MediaCapabilities.decodingInfo API to treat 'smpteSt2086' as
a supported value for the `video.hdrMetadataType` field. It also updates
the relevant test cases to cover this value, as well as known
unsupported values.

Bug: 1048045
Change-Id: I8bd3fe0ca73e72310b329d19e86a072da3de7a00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4123310
Reviewed-by: Yuchen Liu <yucliu@chromium.org>
Commit-Queue: Will Cassella <cassew@chromium.org>
Reviewed-by: Johannes Kron <kron@chromium.org>
Reviewed-by: Xiaohan Wang <xhwang@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1096509}
This commit is contained in:
Will Cassella
2023-01-25 00:13:21 +00:00
committed by Chromium LUCI CQ
parent 5a06d0e0eb
commit c93cdf07bc
4 changed files with 128 additions and 114 deletions

@ -8,6 +8,7 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h" #include "content/public/test/browser_test.h"
@ -20,20 +21,22 @@
namespace { namespace {
const char kDecodeTestFile[] = "decode_capabilities_test.html"; constexpr base::StringPiece kDecodeTestFile = "decode_capabilities_test.html";
const char kSupported[] = "SUPPORTED"; constexpr base::StringPiece kSupported = "SUPPORTED";
const char16_t kSupported16[] = u"SUPPORTED"; constexpr base::StringPiece16 kSupported16 = u"SUPPORTED";
const char kUnsupported[] = "UNSUPPORTED"; constexpr base::StringPiece kUnsupported = "UNSUPPORTED";
const char16_t kUnsupported16[] = u"UNSUPPORTED"; constexpr base::StringPiece16 kUnsupported16 = u"UNSUPPORTED";
const char16_t kError[] = u"ERROR"; constexpr base::StringPiece kError = "ERROR";
const char kFileString[] = "file"; constexpr base::StringPiece16 kError16 = u"ERROR";
const char kMediaSourceString[] = "media-source"; constexpr base::StringPiece kFileString = "file";
const char kWebRtcString[] = "webrtc"; constexpr base::StringPiece kMediaSourceString = "media-source";
constexpr base::StringPiece kWebRtcString = "webrtc";
constexpr base::StringPiece kInvalid = "INVALID";
#if BUILDFLAG(USE_PROPRIETARY_CODECS) #if BUILDFLAG(USE_PROPRIETARY_CODECS)
const char* kPropSupported = kSupported; constexpr base::StringPiece kPropSupported = kSupported;
#else #else
const char* kPropSupported = kUnsupported; constexpr base::StringPiece kPropSupported = kUnsupported;
#endif // USE_PROPRIETARY_CODECS #endif // USE_PROPRIETARY_CODECS
enum StreamType { enum StreamType {
@ -52,7 +55,8 @@ namespace content {
class MediaCapabilitiesTest : public ContentBrowserTest { class MediaCapabilitiesTest : public ContentBrowserTest {
public: public:
MediaCapabilitiesTest() = default; MediaCapabilitiesTest()
: scoped_feature_list_(media::kSupportSmpteSt2086HdrMetadata) {}
MediaCapabilitiesTest(const MediaCapabilitiesTest&) = delete; MediaCapabilitiesTest(const MediaCapabilitiesTest&) = delete;
MediaCapabilitiesTest& operator=(const MediaCapabilitiesTest&) = delete; MediaCapabilitiesTest& operator=(const MediaCapabilitiesTest&) = delete;
@ -64,30 +68,29 @@ class MediaCapabilitiesTest : public ContentBrowserTest {
"MediaCapabilitiesDynamicRange"); "MediaCapabilitiesDynamicRange");
} }
std::string CanDecodeAudio(const std::string& config_type, std::string CanDecodeAudio(base::StringPiece config_type,
const std::string& content_type) { base::StringPiece content_type) {
return CanDecode(config_type, content_type, StreamType::kAudio); return CanDecode(config_type, content_type, StreamType::kAudio);
} }
std::string CanDecodeVideo(const std::string& config_type, std::string CanDecodeVideo(base::StringPiece config_type,
const std::string& content_type) { base::StringPiece content_type) {
return CanDecode(config_type, content_type, StreamType::kVideo); return CanDecode(config_type, content_type, StreamType::kVideo);
} }
std::string CanDecodeAudioWithSpatialRendering( std::string CanDecodeAudioWithSpatialRendering(base::StringPiece config_type,
const std::string& config_type, base::StringPiece content_type,
const std::string& content_type, bool spatial_rendering) {
bool spatial_rendering) {
return CanDecode(config_type, content_type, return CanDecode(config_type, content_type,
StreamType::kAudioWithSpatialRendering, spatial_rendering); StreamType::kAudioWithSpatialRendering, spatial_rendering);
} }
std::string CanDecodeVideoWithHdrMetadata( std::string CanDecodeVideoWithHdrMetadata(
const std::string& config_type, base::StringPiece config_type,
const std::string& content_type, base::StringPiece content_type,
const std::string& color_gamut, base::StringPiece color_gamut,
const std::string& transfer_function, base::StringPiece transfer_function,
const std::string& hdr_metadata_type = "") { base::StringPiece hdr_metadata_type = "") {
StreamType stream_type = StreamType::kVideoWithHdrMetadata; StreamType stream_type = StreamType::kVideoWithHdrMetadata;
if (hdr_metadata_type == "") if (hdr_metadata_type == "")
stream_type = StreamType::kVideoWithoutHdrMetadata; stream_type = StreamType::kVideoWithoutHdrMetadata;
@ -97,61 +100,55 @@ class MediaCapabilitiesTest : public ContentBrowserTest {
color_gamut, transfer_function); color_gamut, transfer_function);
} }
std::string CanDecode(const std::string& config_type, std::string CanDecode(base::StringPiece config_type,
const std::string& content_type, base::StringPiece content_type,
StreamType stream_type, StreamType stream_type,
const bool& spatial_rendering = false, bool spatial_rendering = false,
const std::string& hdr_metadata_type = "", base::StringPiece hdr_metadata_type = "",
const std::string& color_gamut = "", base::StringPiece color_gamut = "",
const std::string& transfer_function = "") { base::StringPiece transfer_function = "") {
std::string command; std::string command;
if (stream_type == StreamType::kAudio) { if (stream_type == StreamType::kAudio) {
command.append("testAudioConfig("); base::StringAppendF(&command, "testAudioConfig(");
} else if (stream_type == StreamType::kAudioWithSpatialRendering) { } else if (stream_type == StreamType::kAudioWithSpatialRendering) {
command.append("testAudioConfigWithSpatialRendering("); base::StringAppendF(&command, "testAudioConfigWithSpatialRendering(%s,",
command.append(spatial_rendering ? "true, " : "false, "); spatial_rendering ? "true" : "false");
} else if (stream_type == StreamType::kVideoWithHdrMetadata) { } else if (stream_type == StreamType::kVideoWithHdrMetadata) {
command.append("testVideoConfigWithHdrMetadata("); command.append("testVideoConfigWithHdrMetadata(");
DCHECK(!hdr_metadata_type.empty()); for (auto x : {hdr_metadata_type, color_gamut, transfer_function}) {
DCHECK(!color_gamut.empty()); DCHECK(!x.empty());
DCHECK(!transfer_function.empty()); base::StringAppendF(&command, "\"%.*s\",", static_cast<int>(x.size()),
command.append("\""); x.data());
command.append(hdr_metadata_type); }
command.append("\", ");
command.append("\"");
command.append(color_gamut);
command.append("\", ");
command.append("\"");
command.append(transfer_function);
command.append("\", ");
} else if (stream_type == StreamType::kVideoWithoutHdrMetadata) { } else if (stream_type == StreamType::kVideoWithoutHdrMetadata) {
command.append("testVideoConfigWithoutHdrMetadata("); command.append("testVideoConfigWithoutHdrMetadata(");
DCHECK(!color_gamut.empty()); for (auto x : {color_gamut, transfer_function}) {
DCHECK(!transfer_function.empty()); DCHECK(!x.empty());
command.append("\""); base::StringAppendF(&command, "\"%.*s\",", static_cast<int>(x.size()),
command.append(color_gamut); x.data());
command.append("\", "); }
command.append("\"");
command.append(transfer_function);
command.append("\", ");
} else { } else {
command.append("testVideoConfig("); command.append("testVideoConfig(");
} }
command.append("\""); base::StringAppendF(&command, "\"%.*s\",",
command.append(config_type); static_cast<int>(config_type.size()),
command.append("\""); config_type.data());
command.append(", "); base::StringAppendF(&command, "%.*s);",
command.append(content_type); static_cast<int>(content_type.size()),
command.append(");"); content_type.data());
EXPECT_TRUE(ExecJs(shell(), command)); EXPECT_TRUE(ExecJs(shell(), command));
TitleWatcher title_watcher(shell()->web_contents(), kSupported16); TitleWatcher title_watcher(shell()->web_contents(),
title_watcher.AlsoWaitForTitle(kUnsupported16); std::u16string(kSupported16));
title_watcher.AlsoWaitForTitle(kError); title_watcher.AlsoWaitForTitle(std::u16string(kUnsupported16));
title_watcher.AlsoWaitForTitle(std::u16string(kError16));
return base::UTF16ToASCII(title_watcher.WaitAndGetTitle()); return base::UTF16ToASCII(title_watcher.WaitAndGetTitle());
} }
private:
base::test::ScopedFeatureList scoped_feature_list_;
}; };
// Adds param for query type (file vs media-source) to // Adds param for query type (file vs media-source) to
@ -159,7 +156,7 @@ class MediaCapabilitiesTestWithConfigType
: public MediaCapabilitiesTest, : public MediaCapabilitiesTest,
public testing::WithParamInterface<ConfigType> { public testing::WithParamInterface<ConfigType> {
public: public:
std::string GetTypeString() const { base::StringPiece GetTypeString() const {
switch (GetParam()) { switch (GetParam()) {
case ConfigType::kFile: case ConfigType::kFile:
return kFileString; return kFileString;
@ -179,9 +176,10 @@ class MediaCapabilitiesTestWithConfigType
// for more exhaustive codec string testing. // for more exhaustive codec string testing.
IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType, IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
CommonVideoDecodeTypes) { CommonVideoDecodeTypes) {
base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile); base::FilePath file_path =
media::GetTestDataFilePath(std::string(kDecodeTestFile));
const std::string& config_type = GetTypeString(); const auto config_type = GetTypeString();
// Content types below are not supported for WebRtc. // Content types below are not supported for WebRtc.
const base::StringPiece type_supported = const base::StringPiece type_supported =
@ -234,9 +232,10 @@ IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
// exhaustive codec string testing. // exhaustive codec string testing.
IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType, IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
CommonAudioDecodeTypes) { CommonAudioDecodeTypes) {
base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile); base::FilePath file_path =
media::GetTestDataFilePath(std::string(kDecodeTestFile));
const std::string& config_type = GetTypeString(); const auto config_type = GetTypeString();
// Content types below are not supported for WebRtc. // Content types below are not supported for WebRtc.
const base::StringPiece type_supported = const base::StringPiece type_supported =
@ -269,9 +268,10 @@ IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType, IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
NonMediaSourceDecodeTypes) { NonMediaSourceDecodeTypes) {
base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile); base::FilePath file_path =
media::GetTestDataFilePath(std::string(kDecodeTestFile));
const std::string& config_type = GetTypeString(); const auto config_type = GetTypeString();
// Content types below are supported for src=, but not MediaSource or WebRtc. // Content types below are supported for src=, but not MediaSource or WebRtc.
const base::StringPiece type_supported = const base::StringPiece type_supported =
@ -306,9 +306,10 @@ IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
// Cover basic spatial rendering support. // Cover basic spatial rendering support.
IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType, IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
AudioTypesWithSpatialRendering) { AudioTypesWithSpatialRendering) {
base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile); base::FilePath file_path =
media::GetTestDataFilePath(std::string(kDecodeTestFile));
const std::string& config_type = GetTypeString(); const auto config_type = GetTypeString();
// Content types below are not supported for WebRtc. // Content types below are not supported for WebRtc.
const base::StringPiece type_supported = const base::StringPiece type_supported =
@ -385,11 +386,21 @@ IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
// Cover basic HDR support. // Cover basic HDR support.
IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType, IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
VideoTypesWithDynamicRange) { VideoTypesWithDynamicRange) {
base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile); constexpr base::StringPiece kSrgb = "srgb";
constexpr base::StringPiece kP3 = "p3";
constexpr base::StringPiece kRec2020 = "rec2020";
constexpr base::StringPiece kPq = "pq";
constexpr base::StringPiece kHlg = "hlg";
constexpr base::StringPiece kSmpteSt2086 = "smpteSt2086";
constexpr base::StringPiece kSmpteSt2094_10 = "smpteSt2094-10";
constexpr base::StringPiece kSmpteSt2094_40 = "smpteSt2094-40";
const std::string& config_type = GetTypeString(); base::FilePath file_path =
media::GetTestDataFilePath(std::string(kDecodeTestFile));
// Content types below are not supported for WebRtc. const auto config_type = GetTypeString();
// None of the content types below are supported for WebRtc.
const base::StringPiece type_supported = const base::StringPiece type_supported =
GetParam() != kWebRtc ? kSupported : kUnsupported; GetParam() != kWebRtc ? kSupported : kUnsupported;
const base::StringPiece prop_type_supported = const base::StringPiece prop_type_supported =
@ -398,54 +409,47 @@ IN_PROC_BROWSER_TEST_P(MediaCapabilitiesTestWithConfigType,
EXPECT_TRUE( EXPECT_TRUE(
NavigateToURL(shell(), content::GetFileUrlWithQuery(file_path, ""))); NavigateToURL(shell(), content::GetFileUrlWithQuery(file_path, "")));
// All color gamuts and transfer functions should be supported. for (auto color_gamut : {kSrgb, kP3, kRec2020, kInvalid}) {
EXPECT_EQ(type_supported, CanDecodeVideoWithHdrMetadata( for (auto transfer_function : {kSrgb, kPq, kHlg, kInvalid}) {
config_type, "'video/webm; codecs=\"vp8\"'", // All valid color gamuts and transfer functions without HDR metadata
/* colorGamut */ "srgb", // should be supported.
/* transferFunction */ "srgb")); auto is_invalid =
EXPECT_EQ(type_supported, CanDecodeVideoWithHdrMetadata( color_gamut == kInvalid || transfer_function == kInvalid;
config_type, "'video/webm; codecs=\"vp8\"'", EXPECT_EQ(is_invalid ? kError : type_supported,
/* colorGamut */ "p3", CanDecodeVideoWithHdrMetadata(config_type,
/* transferFunction */ "pq")); "'video/webm; codecs=\"vp8\"'",
EXPECT_EQ(type_supported, CanDecodeVideoWithHdrMetadata( color_gamut, transfer_function));
config_type, "'video/webm; codecs=\"vp8\"'",
/* colorGamut */ "rec2020",
/* transferFunction */ "hlg"));
// No HdrMetadataType is currently supported. // HdrMetadataType smpteSt2086 is supported
EXPECT_EQ(kUnsupported, CanDecodeVideoWithHdrMetadata( EXPECT_EQ(is_invalid ? kError : type_supported,
config_type, "'video/webm; codecs=\"vp8\"'", CanDecodeVideoWithHdrMetadata(
/* colorGamut */ "srgb", config_type, "'video/webm; codecs=\"vp8\"'", color_gamut,
/* transferFunction */ "srgb", transfer_function,
/* hdrMetadataType */ "smpteSt2086")); /* hdrMetadataType */ kSmpteSt2086));
EXPECT_EQ(kUnsupported, CanDecodeVideoWithHdrMetadata(
config_type, "'video/webm; codecs=\"vp8\"'", // No other HdrMetadataType is currently supported.
/* colorGamut */ "srgb", for (auto hdr_metadata_type :
/* transferFunction */ "srgb", {kSmpteSt2094_10, kSmpteSt2094_40, kInvalid}) {
/* hdrMetadataType */ "smpteSt2094-10")); EXPECT_EQ(
EXPECT_EQ(kUnsupported, CanDecodeVideoWithHdrMetadata( is_invalid || hdr_metadata_type == kInvalid ? kError : kUnsupported,
config_type, "'video/webm; codecs=\"vp8\"'", CanDecodeVideoWithHdrMetadata(
/* colorGamut */ "srgb", config_type, "'video/webm; codecs=\"vp8\"'", color_gamut,
/* transferFunction */ "srgb", transfer_function, hdr_metadata_type));
/* hdrMetadataType */ "smpteSt2094-40")); }
}
}
// Make sure results are expected with some USE_PROPRIETARY_CODECS // Make sure results are expected with some USE_PROPRIETARY_CODECS
EXPECT_EQ(prop_type_supported, EXPECT_EQ(prop_type_supported,
CanDecodeVideoWithHdrMetadata(config_type, CanDecodeVideoWithHdrMetadata(config_type,
"'video/mp4; codecs=\"avc1.42E01E\"'", "'video/mp4; codecs=\"avc1.42E01E\"'",
/* colorGamut */ "p3", /* colorGamut */ kP3,
/* transferFunction */ "pq")); /* transferFunction */ kPq));
EXPECT_EQ(prop_type_supported, EXPECT_EQ(prop_type_supported,
CanDecodeVideoWithHdrMetadata(config_type, CanDecodeVideoWithHdrMetadata(config_type,
"'video/mp4; codecs=\"avc1.42101E\"'", "'video/mp4; codecs=\"avc1.42101E\"'",
/* colorGamut */ "srgb", /* colorGamut */ kSrgb,
/* transferFunction */ "srgb")); /* transferFunction */ kSrgb));
EXPECT_EQ(kUnsupported,
CanDecodeVideoWithHdrMetadata(config_type,
"'video/mp4; codecs=\"avc1.42701E\"'",
/* colorGamut */ "srgb",
/* transferFunction */ "srgb",
/* hdrMetadataType */ "smpteSt2086"));
} }
INSTANTIATE_TEST_SUITE_P(File, INSTANTIATE_TEST_SUITE_P(File,

@ -1221,6 +1221,12 @@ BASE_FEATURE(kRecordWebAudioEngagement,
"RecordWebAudioEngagement", "RecordWebAudioEngagement",
base::FEATURE_ENABLED_BY_DEFAULT); base::FEATURE_ENABLED_BY_DEFAULT);
// Enables reporting "smpteSt2086" HDR Metadata as supported in the
// MediaCapabilities API.
BASE_FEATURE(kSupportSmpteSt2086HdrMetadata,
"SupportSmpteSt2086HdrMetadata",
base::FEATURE_DISABLED_BY_DEFAULT);
// The following Media Engagement flags are not enabled on mobile platforms: // The following Media Engagement flags are not enabled on mobile platforms:
// - MediaEngagementBypassAutoplayPolicies: enables the Media Engagement Index // - MediaEngagementBypassAutoplayPolicies: enables the Media Engagement Index
// data to be esude to override autoplay policies. An origin with a high MEI // data to be esude to override autoplay policies. An origin with a high MEI

@ -255,6 +255,7 @@ MEDIA_EXPORT BASE_DECLARE_FEATURE(kPreloadMetadataLazyLoad);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kPreloadMetadataSuspend); MEDIA_EXPORT BASE_DECLARE_FEATURE(kPreloadMetadataSuspend);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kRecordMediaEngagementScores); MEDIA_EXPORT BASE_DECLARE_FEATURE(kRecordMediaEngagementScores);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kRecordWebAudioEngagement); MEDIA_EXPORT BASE_DECLARE_FEATURE(kRecordWebAudioEngagement);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kSupportSmpteSt2086HdrMetadata);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kResumeBackgroundVideo); MEDIA_EXPORT BASE_DECLARE_FEATURE(kResumeBackgroundVideo);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kRevokeMediaSourceObjectURLOnAttach); MEDIA_EXPORT BASE_DECLARE_FEATURE(kRevokeMediaSourceObjectURLOnAttach);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kShareThisTabInsteadButtonGetDisplayMedia); MEDIA_EXPORT BASE_DECLARE_FEATURE(kShareThisTabInsteadButtonGetDisplayMedia);

@ -16,6 +16,7 @@
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
#include "ui/display/display_switches.h" #include "ui/display/display_switches.h"
#include "ui/gfx/hdr_metadata.h"
#if BUILDFLAG(ENABLE_LIBVPX) #if BUILDFLAG(ENABLE_LIBVPX)
// TODO(dalecurtis): This technically should not be allowed in media/base. See // TODO(dalecurtis): This technically should not be allowed in media/base. See
@ -64,6 +65,8 @@ bool IsSupportedHdrMetadata(const gfx::HdrMetadataType& hdr_metadata_type) {
return true; return true;
case gfx::HdrMetadataType::kSmpteSt2086: case gfx::HdrMetadataType::kSmpteSt2086:
return base::FeatureList::IsEnabled(kSupportSmpteSt2086HdrMetadata);
case gfx::HdrMetadataType::kSmpteSt2094_10: case gfx::HdrMetadataType::kSmpteSt2094_10:
case gfx::HdrMetadataType::kSmpteSt2094_40: case gfx::HdrMetadataType::kSmpteSt2094_40:
return false; return false;