MediaRecorder: measure frequencies for codec requests.
This change starts measuring codecs for codec requests to
isTypeSupported and the MediaRecorder ctor.
The should not change anything w.r.t functionality.
Bug: 450757339
Change-Id: I17eceb7fa708951a224645157ba67468c395dccd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7036832
Reviewed-by: Henrik Boström <hbos@chromium.org>
Reviewed-by: Johannes Kron <kron@chromium.org>
Commit-Queue: Markus Handell <handellm@google.com>
Cr-Commit-Position: refs/heads/main@{#1529417}
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
index e12d2305..687386d 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/mediarecorder/blob_event.h"
+#include "third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h"
#include "third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -402,8 +403,9 @@
// not available to support the concrete media encoding.
// https://w3c.github.io/mediacapture-record/#dom-mediarecorder-istypesupported
ContentType content_type(type);
- bool result = handler->CanSupportMimeType(content_type.GetType(),
- content_type.Parameter("codecs"));
+ bool result = handler->CanSupportMimeType(
+ content_type.GetType(), content_type.Parameter("codecs"),
+ MediaRecorderHandler::CanSupportMimeTypeCaller::kIsTypeSupported);
if (IdentifiabilityStudySettings::Get()->ShouldSampleType(
blink::IdentifiableSurface::Type::kMediaRecorder_IsTypeSupported)) {
blink::IdentifiabilityMetricBuilder(context->UkmSourceID())
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc
index 3d0944a4..b274ada 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc
@@ -24,6 +24,7 @@
#include "media/base/audio_codecs.h"
#include "media/base/audio_parameters.h"
#include "media/base/decoder_buffer.h"
+#include "media/base/media_serializers_base.h"
#include "media/base/media_switches.h"
#include "media/base/mime_util.h"
#include "media/base/supported_types.h"
@@ -283,7 +284,8 @@
media_stream_observer_(std::make_unique<MediaStreamObserver>(this)) {}
bool MediaRecorderHandler::CanSupportMimeType(const String& type,
- const String& web_codecs) {
+ const String& web_codecs,
+ CanSupportMimeTypeCaller caller) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
// An empty |type| means MediaRecorderHandler can choose its preferred codecs.
if (type.empty())
@@ -294,6 +296,49 @@
if (!video && !audio)
return false;
+ std::vector<std::string> codecs_list;
+ media::SplitCodecs(web_codecs.Utf8(), &codecs_list);
+
+ for (const auto& codec : codecs_list) {
+ const auto profile = VideoStringToCodecProfile(String(codec));
+ const bool can_support = CanSupportMimeTypeForCodec(type, codec);
+
+ Vector<String> uma_key_vector;
+ uma_key_vector.push_back("Media.MediaRecorder.Codec");
+ uma_key_vector.push_back(StringFromCanSupportMimeTypeCaller(caller));
+ uma_key_vector.push_back(can_support ? "Supported" : "Unsupported");
+ StringBuilder builder;
+ builder.AppendRange(uma_key_vector, ".");
+ String uma_handle = builder.ReleaseString();
+ base::UmaHistogramEnumeration(
+ uma_handle.Ascii().c_str(),
+ VideoTrackRecorder::CodecHistogramFromCodecId(profile.codec_id));
+
+ if (!can_support) {
+ return false;
+ }
+ }
+ return true;
+}
+
+const char* MediaRecorderHandler::StringFromCanSupportMimeTypeCaller(
+ CanSupportMimeTypeCaller caller) {
+ switch (caller) {
+ case CanSupportMimeTypeCaller::kMediaRecorderCtor:
+ return "MediaRecorderCtor";
+ case CanSupportMimeTypeCaller::kIsTypeSupported:
+ return "IsTypeSupported";
+ case CanSupportMimeTypeCaller::kEncodingInfo:
+ return "EncodingInfo";
+ default:
+ return "Test";
+ }
+}
+
+bool MediaRecorderHandler::CanSupportMimeTypeForCodec(const String& type,
+ std::string_view codec) {
+ const bool video = CanSupportVideoType(type);
+
// Both |video| and |audio| support empty |codecs|; |type| == "video" supports
// vp8, vp9, h264, avc1, avc3, av01, av1, hvc1, hev1, opus, or pcm; |type| =
// "audio", supports opus or pcm (little-endian 32-bit float).
@@ -313,14 +358,14 @@
"opus", "pcm"};
static const char* const kAudioCodecs[] = {"opus", "pcm"};
- auto* const* relevant_codecs_begin =
- video ? std::begin(kVideoCodecs) : std::begin(kAudioCodecs);
- auto* const* relevant_codecs_end =
- video ? std::end(kVideoCodecs) : std::end(kAudioCodecs);
+ base::span<const char* const> relevant_codecs;
+ if (video) {
+ relevant_codecs = kVideoCodecs;
+ } else {
+ relevant_codecs = kAudioCodecs;
+ }
- bool mp4_mime_type = false;
-
- mp4_mime_type = IsAllowedMp4Type(type);
+ const bool mp4_mime_type = IsAllowedMp4Type(type);
if (mp4_mime_type) {
static const char* const kVideoCodecsForMP4[] = {
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -337,152 +382,148 @@
#endif
"opus"};
- relevant_codecs_begin =
- video ? std::begin(kVideoCodecsForMP4) : std::begin(kAudioCodecsForMp4);
- relevant_codecs_end =
- video ? std::end(kVideoCodecsForMP4) : std::end(kAudioCodecsForMp4);
+ if (video) {
+ relevant_codecs = kVideoCodecsForMP4;
+ } else {
+ relevant_codecs = kAudioCodecsForMp4;
+ }
}
- std::vector<std::string> codecs_list;
- media::SplitCodecs(web_codecs.Utf8(), &codecs_list);
+ // For `video/x-matroska`, `video/webm`, and `audio/webm`, trim the content
+ // after first '.' to do the case insensitive match based on historical
+ // logic. For `video/mp4`, and `audio/mp4`, preserve the whole string to do
+ // the case sensitive match.
+ String codec_string = String::FromUTF8(codec);
+ if (!mp4_mime_type) {
+ auto str_index = codec.find_first_of('.');
+ if (str_index != std::string::npos) {
+ codec_string = String::FromUTF8(codec.substr(0, str_index));
+ }
+ }
- for (const auto& codec : codecs_list) {
- // For `video/x-matroska`, `video/webm`, and `audio/webm`, trim the content
- // after first '.' to do the case insensitive match based on historical
- // logic. For `video/mp4`, and `audio/mp4`, preserve the whole string to do
- // the case sensitive match.
- String codec_string = String::FromUTF8(codec);
- if (!mp4_mime_type) {
- auto str_index = codec.find_first_of('.');
- if (str_index != std::string::npos) {
- codec_string = String::FromUTF8(codec.substr(0, str_index));
+ bool match =
+ std::any_of(relevant_codecs.begin(), relevant_codecs.end(),
+ [&codec_string, &mp4_mime_type](const char* name) {
+ if (mp4_mime_type) {
+ return EqualStringView(codec_string, name);
+ } else {
+ return EqualIgnoringASCIICase(codec_string, name);
+ }
+ });
+
+ if (video) {
+ // Currently `video/x-matroska` is not supported by mime util, replace to
+ // `video/mp4` instead.
+ //
+ // TODO(crbug.com/40276507): rework MimeUtil such that clients can inject
+ // their own supported mime+codec types.
+ std::string mime_type = EqualIgnoringASCIICase(type, "video/x-matroska")
+ ? "video/mp4"
+ : type.Ascii();
+ // It supports full qualified string for `avc1`, `avc3`, `hvc1`, `hev1`,
+ // and `av01` codecs, e.g.
+ // `avc1.<profile>.<level>`,
+ // `avc3.<profile>.<level>`,
+ // `hvc1.<profile>.<profile_compatibility>.<tier and level>.*`,
+ // `hev1.<profile>.<profile_compatibility>.<tier and level>.*`,
+ // `av01.<profile>.<level>.<color depth>.*`.
+ auto parsed_result =
+ media::ParseVideoCodecString(mime_type, codec,
+ /*allow_ambiguous_matches=*/false);
+ if (!match && mp4_mime_type) {
+ match =
+ parsed_result && (parsed_result->codec == media::VideoCodec::kH264 ||
+ parsed_result->codec == media::VideoCodec::kAV1);
+ }
+
+ if (codec_string.StartsWith("h264", kTextCaseASCIIInsensitive) ||
+ codec_string.StartsWith("avc1", kTextCaseASCIIInsensitive) ||
+ codec_string.StartsWith("avc3", kTextCaseASCIIInsensitive)) {
+ // In the case of the `video/mp4` mimetype, when the profile can be
+ // parsed, make use of the parsed profile.
+ const media::VideoCodecProfile profile =
+ (mp4_mime_type && parsed_result)
+ ? parsed_result->profile
+ : media::VideoCodecProfile::H264PROFILE_BASELINE;
+
+ // If the profile is not any of the H.264 baseline, main, extended, and
+ // high profiles, reject it.
+ if (profile != media::VideoCodecProfile::H264PROFILE_BASELINE &&
+ profile != media::VideoCodecProfile::H264PROFILE_MAIN &&
+ profile != media::VideoCodecProfile::H264PROFILE_EXTENDED &&
+ profile != media::VideoCodecProfile::H264PROFILE_HIGH) {
+ match = false;
+ }
+
+ // If the profile is not supported by either the HW or the SW encoder,
+ // reject it.
+ if (!media::IsEncoderSupportedVideoType(
+ {media::VideoCodec::kH264, profile})) {
+ match = false;
}
}
- bool match =
- std::any_of(relevant_codecs_begin, relevant_codecs_end,
- [&codec_string, &mp4_mime_type](const char* name) {
- if (mp4_mime_type) {
- return EqualStringView(codec_string, name);
- } else {
- return EqualIgnoringASCIICase(codec_string, name);
- }
- });
+ if (codec_string.StartsWith("av1", kTextCaseASCIIInsensitive) ||
+ codec_string.StartsWith("av01", kTextCaseASCIIInsensitive)) {
+ // In the case of the `video/mp4` mimetype, when the profile can be
+ // parsed, make use of the parsed profile.
+ const media::VideoCodecProfile profile =
+ (mp4_mime_type && parsed_result)
+ ? parsed_result->profile
+ : media::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN;
- if (video) {
- // Currently `video/x-matroska` is not supported by mime util, replace to
- // `video/mp4` instead.
- //
- // TODO(crbug.com/40276507): rework MimeUtil such that clients can inject
- // their own supported mime+codec types.
- std::string mime_type = EqualIgnoringASCIICase(type, "video/x-matroska")
- ? "video/mp4"
- : type.Ascii();
- // It supports full qualified string for `avc1`, `avc3`, `hvc1`, `hev1`,
- // and `av01` codecs, e.g.
- // `avc1.<profile>.<level>`,
- // `avc3.<profile>.<level>`,
- // `hvc1.<profile>.<profile_compatibility>.<tier and level>.*`,
- // `hev1.<profile>.<profile_compatibility>.<tier and level>.*`,
- // `av01.<profile>.<level>.<color depth>.*`.
- auto parsed_result =
- media::ParseVideoCodecString(mime_type, codec,
- /*allow_ambiguous_matches=*/false);
- if (!match && mp4_mime_type) {
- match = parsed_result &&
- (parsed_result->codec == media::VideoCodec::kH264 ||
- parsed_result->codec == media::VideoCodec::kAV1);
+ // If the profile does not match the AV1 main profile, reject it.
+ if (profile != media::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN) {
+ match = false;
}
- if (codec_string.StartsWith("h264", kTextCaseASCIIInsensitive) ||
- codec_string.StartsWith("avc1", kTextCaseASCIIInsensitive) ||
- codec_string.StartsWith("avc3", kTextCaseASCIIInsensitive)) {
- // In the case of the `video/mp4` mimetype, when the profile can be
- // parsed, make use of the parsed profile.
- const media::VideoCodecProfile profile =
- (mp4_mime_type && parsed_result)
- ? parsed_result->profile
- : media::VideoCodecProfile::H264PROFILE_BASELINE;
-
- // If the profile is not any of the H.264 baseline, main, extended, and
- // high profiles, reject it.
- if (profile != media::VideoCodecProfile::H264PROFILE_BASELINE &&
- profile != media::VideoCodecProfile::H264PROFILE_MAIN &&
- profile != media::VideoCodecProfile::H264PROFILE_EXTENDED &&
- profile != media::VideoCodecProfile::H264PROFILE_HIGH) {
- match = false;
- }
-
- // If the profile is not supported by either the HW or the SW encoder,
- // reject it.
- if (!media::IsEncoderSupportedVideoType(
- {media::VideoCodec::kH264, profile})) {
- match = false;
- }
+ if (match) {
+ base::UmaHistogramBoolean(
+ "Media.MediaRecorder.HasCorrectAV1CodecString",
+ codec_string.StartsWith("av01", kTextCaseASCIIInsensitive));
}
- if (codec_string.StartsWith("av1", kTextCaseASCIIInsensitive) ||
- codec_string.StartsWith("av01", kTextCaseASCIIInsensitive)) {
- // In the case of the `video/mp4` mimetype, when the profile can be
- // parsed, make use of the parsed profile.
- const media::VideoCodecProfile profile =
- (mp4_mime_type && parsed_result)
- ? parsed_result->profile
- : media::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN;
-
- // If the profile does not match the AV1 main profile, reject it.
- if (profile != media::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN) {
- match = false;
- }
-
- if (match) {
- base::UmaHistogramBoolean(
- "Media.MediaRecorder.HasCorrectAV1CodecString",
- codec_string.StartsWith("av01", kTextCaseASCIIInsensitive));
- }
-
- // If the profile is not supported by either the HW or the SW encoder,
- // reject it.
- if (!media::IsEncoderSupportedVideoType(
- {media::VideoCodec::kAV1, profile})) {
- match = false;
- }
+ // If the profile is not supported by either the HW or the SW encoder,
+ // reject it.
+ if (!media::IsEncoderSupportedVideoType(
+ {media::VideoCodec::kAV1, profile})) {
+ match = false;
}
+ }
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
- // Support `hev1` tag as it allow parameter sets write into the bitstream,
- // which is the only option if the MediaStream has dynamically changing
- // resolution. Also support `hvc1` tag for better compatibility given the
- // fact that QuickTime and Safari only support playing `hvc1` tag mp4
- // videos, and Apple only recommend using `hvc1` for HLS.
- // https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices#2969487
- if (codec_string.StartsWith("hvc1", kTextCaseASCIIInsensitive) ||
- codec_string.StartsWith("hev1", kTextCaseASCIIInsensitive)) {
- match =
- // If the profile can be parsed, ensure it must be HEVC main
- // profile.
- (parsed_result && parsed_result->profile ==
- media::VideoCodecProfile::HEVCPROFILE_MAIN) &&
- // Only if the feature is enabled.
- base::FeatureList::IsEnabled(media::kMediaRecorderHEVCSupport) &&
- // Only `mkv` and `mp4` are supported, `webm` is not supported.
- !EqualIgnoringASCIICase(type, "video/webm") &&
- // Only if there are platform HEVC main profile support.
- media::IsEncoderSupportedVideoType(
- {media::VideoCodec::kHEVC,
- media::VideoCodecProfile::HEVCPROFILE_MAIN});
- }
+ // Support `hev1` tag as it allow parameter sets write into the bitstream,
+ // which is the only option if the MediaStream has dynamically changing
+ // resolution. Also support `hvc1` tag for better compatibility given the
+ // fact that QuickTime and Safari only support playing `hvc1` tag mp4
+ // videos, and Apple only recommend using `hvc1` for HLS.
+ // https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices#2969487
+ if (codec_string.StartsWith("hvc1", kTextCaseASCIIInsensitive) ||
+ codec_string.StartsWith("hev1", kTextCaseASCIIInsensitive)) {
+ match =
+ // If the profile can be parsed, ensure it must be HEVC main
+ // profile.
+ (parsed_result && parsed_result->profile ==
+ media::VideoCodecProfile::HEVCPROFILE_MAIN) &&
+ // Only if the feature is enabled.
+ base::FeatureList::IsEnabled(media::kMediaRecorderHEVCSupport) &&
+ // Only `mkv` and `mp4` are supported, `webm` is not supported.
+ !EqualIgnoringASCIICase(type, "video/webm") &&
+ // Only if there are platform HEVC main profile support.
+ media::IsEncoderSupportedVideoType(
+ {media::VideoCodec::kHEVC,
+ media::VideoCodecProfile::HEVCPROFILE_MAIN});
+ }
#endif
- }
+ }
- if (!match) {
- return false;
- }
+ if (!match) {
+ return false;
+ }
- if (codec_string == "mp4a.40.2" &&
- !media::MojoAudioEncoder::IsSupported(media::AudioCodec::kAAC)) {
- return false;
- }
+ if (codec_string == "mp4a.40.2" &&
+ !media::MojoAudioEncoder::IsSupported(media::AudioCodec::kAAC)) {
+ return false;
}
return true;
}
@@ -500,7 +541,8 @@
type_ = type;
- if (!CanSupportMimeType(type_, codecs)) {
+ if (!CanSupportMimeType(type_, codecs,
+ CanSupportMimeTypeCaller::kMediaRecorderCtor)) {
DLOG(ERROR) << "Unsupported " << type.Utf8() << ";codecs=" << codecs.Utf8();
return false;
}
@@ -786,7 +828,8 @@
codec = configuration.audio_configuration->codec;
}
- info->supported = CanSupportMimeType(mime_type, codec);
+ info->supported = CanSupportMimeType(mime_type, codec,
+ CanSupportMimeTypeCaller::kEncodingInfo);
if (configuration.video_configuration && info->supported) {
VideoTrackRecorder::CodecProfile codec_profile =
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
index 30fb95e..4fb1e4c 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
@@ -71,6 +71,14 @@
public VideoTrackRecorder::CallbackInterface,
public AudioTrackRecorder::CallbackInterface {
public:
+ // Caller for CanSupportMimeType. Influences emitted UMA histograms.
+ enum class CanSupportMimeTypeCaller {
+ kIsTypeSupported,
+ kMediaRecorderCtor,
+ kEncodingInfo,
+ kTest,
+ };
+
MediaRecorderHandler(
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
KeyFrameRequestProcessor::Configuration key_frame_config);
@@ -84,7 +92,12 @@
// sufficient resources are not available to support the concrete media
// encoding."
// [1] https://w3c.github.io/mediacapture-record/MediaRecorder.html#methods
- bool CanSupportMimeType(const String& type, const String& web_codecs);
+ bool CanSupportMimeType(const String& type,
+ const String& web_codecs,
+ CanSupportMimeTypeCaller caller);
+ bool CanSupportMimeTypeForCodec(const String& type, std::string_view codec);
+ static const char* StringFromCanSupportMimeTypeCaller(
+ CanSupportMimeTypeCaller);
bool Initialize(MediaRecorder* client,
MediaStreamDescriptor* media_stream,
const String& type,
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler_unittest.cc b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler_unittest.cc
index eaa5b2d..f0a9c6cc 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler_unittest.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler_unittest.cc
@@ -353,6 +353,12 @@
}
#endif
+ bool CanSupportMimeType(const String& mime_type, const String& codecs) {
+ return media_recorder_handler_->CanSupportMimeType(
+ mime_type, codecs,
+ MediaRecorderHandler::CanSupportMimeTypeCaller::kTest);
+ }
+
test::TaskEnvironment task_environment_;
ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
MockMediaStreamRegistry registry_;
@@ -428,71 +434,55 @@
// combinations and unsupported ones.
TEST_P(MediaRecorderHandlerTest, CanSupportMimeType) {
const String unsupported_mime_type("video/mpeg");
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(
- unsupported_mime_type, String()));
+ EXPECT_FALSE(CanSupportMimeType(unsupported_mime_type, String()));
const String mime_type_video("video/webm");
- EXPECT_TRUE(
- media_recorder_handler_->CanSupportMimeType(mime_type_video, String()));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_video, String()));
const String mime_type_video_uppercase("video/WEBM");
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(
- mime_type_video_uppercase, String()));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_video_uppercase, String()));
const String example_good_codecs_1("vp8");
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(
- mime_type_video, example_good_codecs_1));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_video, example_good_codecs_1));
const String example_good_codecs_2("vp9,opus");
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(
- mime_type_video, example_good_codecs_2));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_video, example_good_codecs_2));
const String example_good_codecs_3("VP9,opus");
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(
- mime_type_video, example_good_codecs_3));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_video, example_good_codecs_3));
const String example_good_codecs_4("H264");
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(mime_type_video,
- example_good_codecs_4),
+ EXPECT_EQ(CanSupportMimeType(mime_type_video, example_good_codecs_4),
BUILDFLAG(ENABLE_OPENH264));
const String example_unsupported_codecs_1("daala");
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(
- mime_type_video, example_unsupported_codecs_1));
+ EXPECT_FALSE(
+ CanSupportMimeType(mime_type_video, example_unsupported_codecs_1));
const String mime_type_audio("audio/webm");
- EXPECT_TRUE(
- media_recorder_handler_->CanSupportMimeType(mime_type_audio, String()));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_audio, String()));
const String example_good_codecs_5("opus");
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(
- mime_type_audio, example_good_codecs_5));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_audio, example_good_codecs_5));
const String example_good_codecs_6("OpUs");
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(
- mime_type_audio, example_good_codecs_6));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_audio, example_good_codecs_6));
const String example_good_codecs_7("pcm");
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(
- mime_type_audio, example_good_codecs_7));
+ EXPECT_TRUE(CanSupportMimeType(mime_type_audio, example_good_codecs_7));
const String example_good_codecs_8("AV01,opus");
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(mime_type_video,
- example_good_codecs_8),
+ EXPECT_EQ(CanSupportMimeType(mime_type_video, example_good_codecs_8),
BUILDFLAG(ENABLE_LIBAOM));
const String example_good_codecs_9("avc1");
const String example_good_codecs_10("avc3");
const String example_good_codecs_11("avc1.42E01E");
const String example_good_codecs_12("avc3.42E01E");
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(mime_type_video,
- example_good_codecs_9),
+ EXPECT_EQ(CanSupportMimeType(mime_type_video, example_good_codecs_9),
BUILDFLAG(ENABLE_OPENH264));
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(mime_type_video,
- example_good_codecs_10),
+ EXPECT_EQ(CanSupportMimeType(mime_type_video, example_good_codecs_10),
BUILDFLAG(ENABLE_OPENH264));
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(mime_type_video,
- example_good_codecs_11),
+ EXPECT_EQ(CanSupportMimeType(mime_type_video, example_good_codecs_11),
BUILDFLAG(ENABLE_OPENH264));
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(mime_type_video,
- example_good_codecs_12),
+ EXPECT_EQ(CanSupportMimeType(mime_type_video, example_good_codecs_12),
BUILDFLAG(ENABLE_OPENH264));
const String example_unsupported_codecs_2("vorbis");
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(
- mime_type_audio, example_unsupported_codecs_2));
+ EXPECT_FALSE(
+ CanSupportMimeType(mime_type_audio, example_unsupported_codecs_2));
// HEVC only supports hardware encoding, and whether hardware encoding is
// supported depends on the supported profiles retrieved by the
@@ -500,12 +490,12 @@
// unable to know if HEVC is supported or not, so it should always return
// false here.
const String example_good_codecs_with_supported_tag("hev1.1.6.L93.B0");
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(
- mime_type_video, example_good_codecs_with_supported_tag));
+ EXPECT_FALSE(CanSupportMimeType(mime_type_video,
+ example_good_codecs_with_supported_tag));
const String example_good_codecs_with_supported_tag_2("hvc1.1.6.L93.B0");
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(
- mime_type_video, example_good_codecs_with_supported_tag_2));
+ EXPECT_FALSE(CanSupportMimeType(mime_type_video,
+ example_good_codecs_with_supported_tag_2));
}
// Checks that it uses the specified bitrate mode.
@@ -1076,14 +1066,13 @@
// success cases.
for (const auto& type : good_mp4_video_mime_types) {
for (const auto& codec : good_mp4_video_codecs) {
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codec),
- IsVideoCodecSupported(codec));
+ EXPECT_EQ(CanSupportMimeType(type, codec), IsVideoCodecSupported(codec));
}
}
for (const auto& type : good_mp4_video_mime_types) {
for (const auto& codec : good_mp4_audio_codecs) {
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codec),
+ EXPECT_EQ(CanSupportMimeType(type, codec),
IsTargetAudioCodecSupported(codec));
}
}
@@ -1094,12 +1083,10 @@
const bool supported = IsVideoCodecSupported(video_codec) &&
IsTargetAudioCodecSupported(audio_codec);
String codecs = video_codec + "," + audio_codec;
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codecs),
- supported);
+ EXPECT_EQ(CanSupportMimeType(type, codecs), supported);
String codecs2 = audio_codec + "," + video_codec;
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codecs2),
- supported);
+ EXPECT_EQ(CanSupportMimeType(type, codecs2), supported);
}
}
}
@@ -1107,27 +1094,26 @@
// failure cases.
for (const auto& type : bad_mp4_video_mime_types) {
for (const auto& codec : good_mp4_video_codecs) {
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_FALSE(CanSupportMimeType(type, codec));
}
}
for (const auto& type : good_mp4_video_mime_types) {
for (const auto& codec : bad_mp4_video_codecs) {
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_FALSE(CanSupportMimeType(type, codec));
}
}
#else
// success cases.
for (const auto& type : good_mp4_video_mime_types) {
for (const auto& codec : good_mp4_video_codecs_non_proprietary) {
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codec),
- IsVideoCodecSupported(codec));
+ EXPECT_EQ(CanSupportMimeType(type, codec), IsVideoCodecSupported(codec));
}
}
for (const auto& type : good_mp4_video_mime_types) {
for (const auto& codec : good_mp4_audio_codecs_non_proprietary) {
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_TRUE(CanSupportMimeType(type, codec));
}
}
@@ -1135,11 +1121,11 @@
for (const auto& video_codec : good_mp4_video_codecs_non_proprietary) {
for (const auto& audio_codec : good_mp4_audio_codecs_non_proprietary) {
String codecs = video_codec + "," + audio_codec;
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codecs),
+ EXPECT_EQ(CanSupportMimeType(type, codecs),
IsVideoCodecSupported(video_codec));
String codecs2 = audio_codec + "," + video_codec;
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codecs2),
+ EXPECT_EQ(CanSupportMimeType(type, codecs2),
IsVideoCodecSupported(video_codec));
}
}
@@ -1148,7 +1134,7 @@
// failure cases.
for (const auto& type : good_mp4_video_mime_types) {
for (const auto& codec : bad_mp4_video_codecs) {
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_FALSE(CanSupportMimeType(type, codec));
}
}
#endif
@@ -1158,7 +1144,7 @@
// success cases.
for (const auto& type : good_mp4_audio_mime_types) {
for (const auto& codec : good_mp4_audio_codecs) {
- EXPECT_EQ(media_recorder_handler_->CanSupportMimeType(type, codec),
+ EXPECT_EQ(CanSupportMimeType(type, codec),
IsTargetAudioCodecSupported(codec));
}
}
@@ -1166,19 +1152,19 @@
// failure cases.
for (const auto& type : bad_mp4_audio_mime_types) {
for (const auto& codec : good_mp4_audio_codecs) {
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_FALSE(CanSupportMimeType(type, codec));
}
}
for (const auto& type : good_mp4_audio_mime_types) {
for (const auto& codec : bad_mp4_audio_codecs) {
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_FALSE(CanSupportMimeType(type, codec));
}
}
for (const auto& type : good_mp4_audio_mime_types) {
for (const auto& codec : good_mp4_video_codecs) {
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_FALSE(CanSupportMimeType(type, codec));
}
}
@@ -1186,11 +1172,10 @@
for (const auto& video_codec : good_mp4_video_codecs) {
for (const auto& audio_codec : good_mp4_audio_codecs) {
String codecs = video_codec + "," + audio_codec;
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codecs));
+ EXPECT_FALSE(CanSupportMimeType(type, codecs));
String codecs2 = audio_codec + "," + video_codec;
- EXPECT_FALSE(
- media_recorder_handler_->CanSupportMimeType(type, codecs2));
+ EXPECT_FALSE(CanSupportMimeType(type, codecs2));
}
}
}
@@ -1198,14 +1183,14 @@
// success cases.
for (const auto& type : good_mp4_audio_mime_types) {
for (const auto& codec : good_mp4_audio_codecs_non_proprietary) {
- EXPECT_TRUE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_TRUE(CanSupportMimeType(type, codec));
}
}
// failure cases.
for (const auto& type : good_mp4_audio_mime_types) {
for (const auto& codec : bad_mp4_audio_codecs) {
- EXPECT_FALSE(media_recorder_handler_->CanSupportMimeType(type, codec));
+ EXPECT_FALSE(CanSupportMimeType(type, codec));
}
}
#endif
@@ -1221,15 +1206,13 @@
{
base::test::ScopedOSInfoOverride scoped_os_info_override(
base::test::ScopedOSInfoOverride::Type::kWin11Home);
- EXPECT_TRUE(
- media_recorder_handler_->CanSupportMimeType("audio/mp4", "mp4a.40.2"));
+ EXPECT_TRUE(CanSupportMimeType("audio/mp4", "mp4a.40.2"));
}
{
base::test::ScopedOSInfoOverride scoped_os_info_override(
base::test::ScopedOSInfoOverride::Type::kWin11HomeN);
- EXPECT_FALSE(
- media_recorder_handler_->CanSupportMimeType("audio/mp4", "mp4a.40.2"));
+ EXPECT_FALSE(CanSupportMimeType("audio/mp4", "mp4a.40.2"));
}
}
#endif // BUILDFLAG(IS_WIN) && BUILDFLAG(USE_PROPRIETARY_CODECS)
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
index 9231f243..1a2502c5 100644
--- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
@@ -230,12 +230,12 @@
media::VideoEncodeAccelerator::SupportedProfiles());
}
-void UmaHistogramForCodec(bool uses_acceleration, CodecId codec_id) {
+void UmaHistogramForCodecImpl(bool uses_acceleration, CodecId codec_id) {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// (kMaxValue being the only exception, as it does not map to a logged value,
// and should be renumbered as new values are inserted.)
- enum class VideoTrackRecorderCodecHistogram : uint8_t {
+ enum class VideoTrackRecorderCodecImplHistogram : uint8_t {
kUnknown = 0,
kVp8Sw = 1,
kVp8Hw = 2,
@@ -248,26 +248,26 @@
kHevcHw = 9,
kMaxValue = kHevcHw,
};
- auto histogram = VideoTrackRecorderCodecHistogram::kUnknown;
+ auto histogram = VideoTrackRecorderCodecImplHistogram::kUnknown;
if (uses_acceleration) {
switch (codec_id) {
case CodecId::kVp8:
- histogram = VideoTrackRecorderCodecHistogram::kVp8Hw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kVp8Hw;
break;
case CodecId::kVp9:
- histogram = VideoTrackRecorderCodecHistogram::kVp9Hw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kVp9Hw;
break;
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
case CodecId::kH264:
- histogram = VideoTrackRecorderCodecHistogram::kH264Hw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kH264Hw;
break;
#endif
case CodecId::kAv1:
- histogram = VideoTrackRecorderCodecHistogram::kAv1Hw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kAv1Hw;
break;
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
case CodecId::kHevc:
- histogram = VideoTrackRecorderCodecHistogram::kHevcHw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kHevcHw;
break;
#endif
case CodecId::kLast:
@@ -276,18 +276,18 @@
} else {
switch (codec_id) {
case CodecId::kVp8:
- histogram = VideoTrackRecorderCodecHistogram::kVp8Sw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kVp8Sw;
break;
case CodecId::kVp9:
- histogram = VideoTrackRecorderCodecHistogram::kVp9Sw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kVp9Sw;
break;
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
case CodecId::kH264:
- histogram = VideoTrackRecorderCodecHistogram::kH264Sw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kH264Sw;
break;
#endif
case CodecId::kAv1:
- histogram = VideoTrackRecorderCodecHistogram::kAv1Sw;
+ histogram = VideoTrackRecorderCodecImplHistogram::kAv1Sw;
break;
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
case CodecId::kHevc:
@@ -412,6 +412,29 @@
}
} // anonymous namespace
+// static
+VideoTrackRecorder::CodecHistogram
+VideoTrackRecorder::CodecHistogramFromCodecId(CodecId codec_id) {
+ switch (codec_id) {
+ case CodecId::kVp8:
+ return CodecHistogram::kVp8;
+ case CodecId::kVp9:
+ return CodecHistogram::kVp9;
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+ case CodecId::kH264:
+ return CodecHistogram::kH264;
+#endif
+ case CodecId::kAv1:
+ return CodecHistogram::kAv1;
+#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
+ case CodecId::kHevc:
+ return CodecHistogram::kHevc;
+#endif
+ default:
+ return CodecHistogram::kUnknown;
+ }
+}
+
VideoTrackRecorder::VideoTrackRecorder(
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
WeakCell<CallbackInterface>* callback_interface)
@@ -1033,7 +1056,7 @@
auto encoding_task_runner =
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
CHECK(encoding_task_runner);
- UmaHistogramForCodec(create_vea_encoder, codec_profile.codec_id);
+ UmaHistogramForCodecImpl(create_vea_encoder, codec_profile.codec_id);
CreateMediaVideoEncoder(encoding_task_runner, codec_profile, is_screencast,
create_vea_encoder);
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h
index 5c8e30cc..21ac73012 100644
--- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h
+++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h
@@ -82,6 +82,25 @@
kLast
};
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ // (kMaxValue being the only exception, as it does not map to a logged value,
+ // and should be renumbered as new values are inserted.)
+ //
+ // LINT.IfChange(CodecHistogram)
+ enum class CodecHistogram : uint8_t {
+ kUnknown = 0,
+ kVp8 = 1,
+ kVp9 = 2,
+ kH264 = 3,
+ kAv1 = 4,
+ kHevc = 5,
+ kMaxValue = kHevc,
+ };
+ // LINT.ThenChange(//tools/metrics/histograms/metadata/media/enums.xml:MediaRecorderVideoCodec)
+
+ static CodecHistogram CodecHistogramFromCodecId(CodecId);
+
// Callback interface for VideoTrackRecorders. The methods here need to all be
// called on the main thread.
class CallbackInterface : public GarbageCollectedMixin {
diff --git a/tools/metrics/histograms/metadata/media/enums.xml b/tools/metrics/histograms/metadata/media/enums.xml
index 375e478..e32c397 100644
--- a/tools/metrics/histograms/metadata/media/enums.xml
+++ b/tools/metrics/histograms/metadata/media/enums.xml
@@ -1464,7 +1464,20 @@
<int value="2" label="User opened the combobox and chose a different device"/>
</enum>
-<enum name="MediaRecorderCodec">
+<!-- LINT.IfChange(MediaRecorderVideoCodec) -->
+
+<enum name="MediaRecorderVideoCodec">
+ <int value="0" label="UnknownOrAudio"/>
+ <int value="1" label="VP8"/>
+ <int value="2" label="VP9"/>
+ <int value="3" label="H264"/>
+ <int value="4" label="AV1"/>
+ <int value="5" label="H265"/>
+</enum>
+
+<!-- LINT.ThenChange(//third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h:CodecHistogram) -->
+
+<enum name="MediaRecorderVideoCodecImpl">
<int value="0" label="Unknown"/>
<int value="1" label="VP8_sw"/>
<int value="2" label="VP8_hw"/>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index 27d2f6f..bdecbf59 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -5040,7 +5040,7 @@
</summary>
</histogram>
-<histogram name="Media.MediaRecorder.Codec" enum="MediaRecorderCodec"
+<histogram name="Media.MediaRecorder.Codec" enum="MediaRecorderVideoCodecImpl"
expires_after="2026-02-22">
<owner>clarissagarvey@chromium.org</owner>
<owner>chromeos-gfx-video@chromium.org</owner>
@@ -5050,6 +5050,26 @@
</summary>
</histogram>
+<histogram name="Media.MediaRecorder.Codec.{Query}.{Result}"
+ enum="MediaRecorderVideoCodec" expires_after="2026-05-01">
+ <owner>handellm@google.com</owner>
+ <owner>guidou@google.com</owner>
+ <summary>
+ Codec queried through MediaRecorder{Query} where the result is {Result}.
+ Logged when the call is made.
+ </summary>
+ <token key="Query">
+ <variant name="EncodingInfo" summary="EncodingInfo"/>
+ <variant name="IsTypeSupported" summary=".isTypeSupported"/>
+ <variant name="MediaRecorderCtor" summary="ctor"/>
+ <variant name="Test" summary="Test"/>
+ </token>
+ <token key="Result">
+ <variant name="Supported" summary="supported"/>
+ <variant name="Unsupported" summary="unsupported"/>
+ </token>
+</histogram>
+
<histogram name="Media.MediaRecorder.HasCorrectAV1CodecString"
enum="BooleanCorrect" expires_after="2024-06-30">
<owner>hiroh@chromium.org</owner>