1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include "media/mojo/services/mojo_video_encoder_metrics_provider_service.h"
10 #include "base/run_loop.h"
11 #include "base/test/metrics/histogram_tester.h"
12 #include "base/test/test_message_loop.h"
13 #include "components/ukm/test_ukm_recorder.h"
14 #include "mojo/public/cpp/bindings/remote.h"
15 #include "services/metrics/public/cpp/ukm_builders.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
20 using UkmEntry = ukm::builders::Media_VideoEncoderMetrics;
22 using ::testing::TestWithParam;
23 using ::testing::ValuesIn;
27 constexpr char kTestURL[] = "https://test.google.com/";
29 std::tuple<std::unique_ptr<ukm::TestAutoSetUkmRecorder>,
30 mojo::Remote<mojom::VideoEncoderMetricsProvider>>
31 Create(const std::string& url) {
32 auto test_recorder = std::make_unique<ukm::TestAutoSetUkmRecorder>();
33 ukm::SourceId source_id = test_recorder->GetNewSourceID();
34 test_recorder->UpdateSourceURL(source_id, GURL(url));
35 mojo::Remote<mojom::VideoEncoderMetricsProvider> provider;
36 MojoVideoEncoderMetricsProviderService::Create(
37 source_id, provider.BindNewPipeAndPassReceiver());
38 return {std::move(test_recorder), std::move(provider)};
42 class MojoVideoEncoderMetricsProviderServiceTest
43 : public TestWithParam<testing::tuple<uint64_t,
44 mojom::VideoEncoderUseCase,
49 EncoderStatus::Codes>> {
51 MojoVideoEncoderMetricsProviderServiceTest() = default;
52 ~MojoVideoEncoderMetricsProviderServiceTest() override = default;
55 base::TestMessageLoop message_loop_;
58 TEST_F(MojoVideoEncoderMetricsProviderServiceTest, Create_NoUKMReport) {
59 auto [test_recorder, provider] = Create(kTestURL);
61 base::RunLoop().RunUntilIdle();
62 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
63 EXPECT_TRUE(entries.empty());
66 #define EXPECT_UKM(name, value) \
67 test_recorder->ExpectEntryMetric(entry, name, value)
69 TEST_F(MojoVideoEncoderMetricsProviderServiceTest,
70 CreateAndInitialize_ReportUKM) {
71 auto [test_recorder, provider] = Create(kTestURL);
72 constexpr uint64_t kEncoderId = 0;
73 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
74 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
75 constexpr gfx::Size kEncodeSize(1200, 700);
76 constexpr bool kIsHardwareEncoder = true;
77 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
78 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile, kEncodeSize,
79 kIsHardwareEncoder, kSVCMode);
81 base::RunLoop().RunUntilIdle();
83 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
84 ASSERT_EQ(1u, entries.size());
85 const auto* entry = entries[0];
86 EXPECT_UKM(UkmEntry::kHeightName, kEncodeSize.height());
87 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
88 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 0);
89 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
90 EXPECT_UKM(UkmEntry::kStatusName,
91 static_cast<int64_t>(EncoderStatus::Codes::kOk));
92 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
93 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
94 EXPECT_UKM(UkmEntry::kWidthName, kEncodeSize.width());
97 TEST_F(MojoVideoEncoderMetricsProviderServiceTest,
98 CreateAndInitializeAndComplete_ReportUKM) {
99 auto [test_recorder, provider] = Create(kTestURL);
100 constexpr uint64_t kEncoderId = 0;
101 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
102 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
103 constexpr gfx::Size kEncodeSize(1200, 700);
104 constexpr bool kIsHardwareEncoder = true;
105 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
106 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile, kEncodeSize,
107 kIsHardwareEncoder, kSVCMode);
108 provider->Complete(kEncoderId);
109 base::RunLoop().RunUntilIdle();
111 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
112 ASSERT_EQ(1u, entries.size());
113 const auto* entry = entries[0];
114 EXPECT_UKM(UkmEntry::kHeightName, kEncodeSize.height());
115 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
116 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 0);
117 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
118 EXPECT_UKM(UkmEntry::kStatusName,
119 static_cast<int64_t>(EncoderStatus::Codes::kOk));
120 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
121 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
122 EXPECT_UKM(UkmEntry::kWidthName, kEncodeSize.width());
127 MojoVideoEncoderMetricsProviderServiceTest,
128 CreateAndInitializeAndSetSmallNumberEncodedFrameCount_ReportUKMWithOneBucket) {
129 auto [test_recorder, provider] = Create(kTestURL);
130 constexpr uint64_t kEncoderId = 0;
131 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
132 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
133 constexpr gfx::Size kEncodeSize(1200, 700);
134 constexpr bool kIsHardwareEncoder = true;
135 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
136 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile, kEncodeSize,
137 kIsHardwareEncoder, kSVCMode);
138 provider->SetEncodedFrameCount(kEncoderId, 10);
140 base::RunLoop().RunUntilIdle();
142 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
143 ASSERT_EQ(1u, entries.size());
144 const auto* entry = entries[0];
145 EXPECT_UKM(UkmEntry::kHeightName, kEncodeSize.height());
146 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
147 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 1u);
148 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
149 EXPECT_UKM(UkmEntry::kStatusName,
150 static_cast<int64_t>(EncoderStatus::Codes::kOk));
151 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
152 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
153 EXPECT_UKM(UkmEntry::kWidthName, kEncodeSize.width());
156 TEST_P(MojoVideoEncoderMetricsProviderServiceTest,
157 CreateAndInitializeAndSetEncodedFrameCount_ReportUKM) {
158 auto [test_recorder, provider] = Create(kTestURL);
159 auto encoder_id = std::get<0>(GetParam());
160 auto encoder_use_case = std::get<1>(GetParam());
161 auto codec_profile = std::get<2>(GetParam());
162 auto encode_size = std::get<3>(GetParam());
163 auto is_hardware_encoder = std::get<4>(GetParam());
164 auto svc_mode = std::get<5>(GetParam());
165 media::EncoderStatus encoder_status(std::get<6>(GetParam()));
166 constexpr uint64_t kNumEncodedFrames = 100;
167 provider->Initialize(encoder_id, encoder_use_case, codec_profile, encode_size,
168 is_hardware_encoder, svc_mode);
169 provider->SetEncodedFrameCount(encoder_id, kNumEncodedFrames);
170 if (!encoder_status.is_ok()) {
171 provider->SetError(encoder_id, encoder_status);
174 base::RunLoop().RunUntilIdle();
176 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
177 ASSERT_EQ(1u, entries.size());
178 const auto* entry = entries[0];
179 const uint64_t expected_height = encode_size.height() / 100 * 100;
180 const uint64_t expected_width = encode_size.width() / 100 * 100;
181 EXPECT_UKM(UkmEntry::kHeightName, expected_height);
182 EXPECT_UKM(UkmEntry::kIsHardwareName, is_hardware_encoder);
183 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, kNumEncodedFrames);
184 EXPECT_UKM(UkmEntry::kProfileName, codec_profile);
185 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(svc_mode));
186 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(encoder_use_case));
187 EXPECT_UKM(UkmEntry::kWidthName, expected_width);
188 EXPECT_UKM(UkmEntry::kStatusName,
189 static_cast<int64_t>(encoder_status.code()));
192 TEST_P(MojoVideoEncoderMetricsProviderServiceTest,
193 CreateAndInitializeAndSetEncodedFrameCount_ReportUMA) {
194 base::HistogramTester histogram_tester;
195 auto [test_recorder, provider] = Create(kTestURL);
196 auto encoder_id = std::get<0>(GetParam());
197 auto encoder_use_case = std::get<1>(GetParam());
198 auto codec_profile = std::get<2>(GetParam());
199 auto encode_size = std::get<3>(GetParam());
200 auto is_hardware_encoder = std::get<4>(GetParam());
201 auto svc_mode = std::get<5>(GetParam());
202 media::EncoderStatus encoder_status(std::get<6>(GetParam()));
203 constexpr uint64_t kNumEncodedFrames = 100;
204 provider->Initialize(encoder_id, encoder_use_case, codec_profile, encode_size,
205 is_hardware_encoder, svc_mode);
206 provider->SetEncodedFrameCount(encoder_id, kNumEncodedFrames);
207 if (!encoder_status.is_ok()) {
208 provider->SetError(encoder_id, encoder_status);
211 base::RunLoop().RunUntilIdle();
213 std::string uma_prefix = "Media.VideoEncoder.";
214 switch (encoder_use_case) {
215 case mojom::VideoEncoderUseCase::kCastMirroring:
216 uma_prefix += "CastMirroring.";
218 case mojom::VideoEncoderUseCase::kMediaRecorder:
219 uma_prefix += "MediaRecorder.";
221 case mojom::VideoEncoderUseCase::kWebCodecs:
222 uma_prefix += "WebCodecs.";
224 case mojom::VideoEncoderUseCase::kWebRTC:
225 uma_prefix += "WebRTC.";
229 #define EXPECT_UMA(name, value) \
231 histogram_tester.ExpectUniqueSample(base::StrCat({uma_prefix, name}), \
235 EXPECT_UMA("Profile", codec_profile);
236 EXPECT_UMA("SVC", svc_mode);
237 EXPECT_UMA("HW", is_hardware_encoder);
238 EXPECT_UMA("Width", encode_size.width());
239 EXPECT_UMA("Height", encode_size.height());
240 EXPECT_UMA("Area", encode_size.GetArea() / 100);
241 EXPECT_UMA("Status", encoder_status.code());
246 INSTANTIATE_TEST_SUITE_P(
248 MojoVideoEncoderMetricsProviderServiceTest,
249 ::testing::Combine(ValuesIn(std::vector<uint64_t>{12ul, 100ul}),
251 mojom::VideoEncoderUseCase::kCastMirroring,
252 mojom::VideoEncoderUseCase::kMediaRecorder,
253 mojom::VideoEncoderUseCase::kWebCodecs,
254 mojom::VideoEncoderUseCase::kWebRTC,
260 AV1PROFILE_PROFILE_HIGH,
264 gfx::Size(1280, 720),
268 SVCScalabilityMode::kL1T1,
269 SVCScalabilityMode::kL3T3Key,
272 EncoderStatus::Codes::kOk,
273 EncoderStatus::Codes::kEncoderFailedEncode,
276 TEST_F(MojoVideoEncoderMetricsProviderServiceTest,
277 InitializeWithVerfiyLargeResoloution_ReportCappedResolutionUKM) {
278 auto [test_recorder, provider] = Create(kTestURL);
279 constexpr uint64_t kEncoderId = 0;
280 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
281 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
282 constexpr gfx::Size k16kEncodeSize(15360, 8640);
283 constexpr bool kIsHardwareEncoder = true;
284 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
285 constexpr uint64_t kNumEncodedFrames = 100;
286 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile,
287 k16kEncodeSize, kIsHardwareEncoder, kSVCMode);
288 provider->SetEncodedFrameCount(kEncoderId, kNumEncodedFrames);
290 base::RunLoop().RunUntilIdle();
292 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
293 ASSERT_EQ(1u, entries.size());
294 const auto* entry = entries[0];
295 constexpr uint64_t kHeight = 8200;
296 constexpr uint64_t kWidth = 8200;
297 EXPECT_UKM(UkmEntry::kHeightName, kHeight);
298 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
299 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, kNumEncodedFrames);
300 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
301 EXPECT_UKM(UkmEntry::kStatusName,
302 static_cast<int64_t>(EncoderStatus::Codes::kOk));
303 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
304 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
305 EXPECT_UKM(UkmEntry::kWidthName, kWidth);
308 TEST_F(MojoVideoEncoderMetricsProviderServiceTest,
309 CallSetEncodedFrameCounts_ReportUKMWithTheLastEncodedFrameCount) {
310 auto [test_recorder, provider] = Create(kTestURL);
311 constexpr uint64_t kEncoderId = 0;
312 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
313 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
314 constexpr gfx::Size kEncodeSize(1920, 1080);
315 constexpr bool kIsHardwareEncoder = true;
316 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
317 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile, kEncodeSize,
318 kIsHardwareEncoder, kSVCMode);
319 provider->SetEncodedFrameCount(kEncoderId, 100);
320 provider->SetEncodedFrameCount(kEncoderId, 200);
321 provider->SetEncodedFrameCount(kEncoderId, 300);
323 base::RunLoop().RunUntilIdle();
325 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
326 ASSERT_EQ(1u, entries.size());
327 const auto* entry = entries[0];
328 constexpr uint64_t kHeight = kEncodeSize.height() / 100 * 100;
329 constexpr uint64_t kWidth = kEncodeSize.width() / 100 * 100;
330 EXPECT_UKM(UkmEntry::kHeightName, kHeight);
331 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
332 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 300);
333 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
334 EXPECT_UKM(UkmEntry::kStatusName,
335 static_cast<int64_t>(EncoderStatus::Codes::kOk));
336 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
337 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
338 EXPECT_UKM(UkmEntry::kWidthName, kWidth);
341 TEST_F(MojoVideoEncoderMetricsProviderServiceTest,
342 CreateAndInitializeAndCallSetErrors_ReportUKMWithTheFirstError) {
343 auto [test_recorder, provider] = Create(kTestURL);
344 constexpr uint64_t kEncoderId = 0;
345 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
346 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
347 constexpr gfx::Size kEncodeSize(1920, 1080);
348 constexpr bool kIsHardwareEncoder = true;
349 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
350 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile, kEncodeSize,
351 kIsHardwareEncoder, kSVCMode);
352 provider->SetError(kEncoderId,
353 {EncoderStatus::Codes::kEncoderMojoConnectionError,
354 "mojo connection is disclosed"});
355 provider->SetError(kEncoderId, {EncoderStatus::Codes::kEncoderFailedEncode,
358 base::RunLoop().RunUntilIdle();
360 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
361 ASSERT_EQ(1u, entries.size());
362 const auto* entry = entries[0];
363 constexpr uint64_t kHeight = kEncodeSize.height() / 100 * 100;
364 constexpr uint64_t kWidth = kEncodeSize.width() / 100 * 100;
365 EXPECT_UKM(UkmEntry::kHeightName, kHeight);
366 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
367 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 0u);
368 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
370 UkmEntry::kStatusName,
371 static_cast<int64_t>(EncoderStatus::Codes::kEncoderMojoConnectionError));
372 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
373 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
374 EXPECT_UKM(UkmEntry::kWidthName, kWidth);
377 TEST_F(MojoVideoEncoderMetricsProviderServiceTest,
378 CallErrorAndNoCallSetEncodedFramesCount_ReportUKMWithTheFirstError) {
379 auto [test_recorder, provider] = Create(kTestURL);
380 constexpr uint64_t kEncoderId = 0;
381 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
382 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
383 constexpr gfx::Size kEncodeSize(1920, 1080);
384 constexpr bool kIsHardwareEncoder = true;
385 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
386 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile, kEncodeSize,
387 kIsHardwareEncoder, kSVCMode);
388 provider->SetError(kEncoderId,
389 {EncoderStatus::Codes::kEncoderMojoConnectionError,
390 "mojo connection is disclosed"});
391 provider->SetError(kEncoderId, {EncoderStatus::Codes::kEncoderFailedEncode,
394 base::RunLoop().RunUntilIdle();
396 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
397 ASSERT_EQ(1u, entries.size());
398 const auto* entry = entries[0];
399 constexpr uint64_t kHeight = kEncodeSize.height() / 100 * 100;
400 constexpr uint64_t kWidth = kEncodeSize.width() / 100 * 100;
401 EXPECT_UKM(UkmEntry::kHeightName, kHeight);
402 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
403 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 0);
404 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
406 UkmEntry::kStatusName,
407 static_cast<int64_t>(EncoderStatus::Codes::kEncoderMojoConnectionError));
408 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
409 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
410 EXPECT_UKM(UkmEntry::kWidthName, kWidth);
414 MojoVideoEncoderMetricsProviderServiceTest,
415 CallSetEncodedFrameCountsAndSetError_ReportUKMWithTheFirstErrorAndTheLastEncodedFrameCount) {
416 auto [test_recorder, provider] = Create(kTestURL);
417 constexpr uint64_t kEncoderId = 0;
418 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
419 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
420 constexpr gfx::Size kEncodeSize(1920, 1080);
421 constexpr bool kIsHardwareEncoder = true;
422 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
423 provider->Initialize(kEncoderId, kEncoderUseCase, kCodecProfile, kEncodeSize,
424 kIsHardwareEncoder, kSVCMode);
425 provider->SetEncodedFrameCount(kEncoderId, 100);
426 provider->SetEncodedFrameCount(kEncoderId, 200);
427 provider->SetEncodedFrameCount(kEncoderId, 300);
428 provider->SetError(kEncoderId, {EncoderStatus::Codes::kEncoderFailedEncode,
430 provider->SetError(kEncoderId, {EncoderStatus::Codes::kEncoderIllegalState,
431 "Encoder illegal state"});
432 provider->SetEncodedFrameCount(kEncoderId, 400);
434 base::RunLoop().RunUntilIdle();
436 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
437 ASSERT_EQ(1u, entries.size());
438 const auto* entry = entries[0];
439 constexpr uint64_t kHeight = kEncodeSize.height() / 100 * 100;
440 constexpr uint64_t kWidth = kEncodeSize.width() / 100 * 100;
441 EXPECT_UKM(UkmEntry::kHeightName, kHeight);
442 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
443 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 400);
444 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
445 EXPECT_UKM(UkmEntry::kStatusName,
446 static_cast<int64_t>(EncoderStatus::Codes::kEncoderFailedEncode));
447 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
448 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
449 EXPECT_UKM(UkmEntry::kWidthName, kWidth);
452 TEST_F(MojoVideoEncoderMetricsProviderServiceTest,
453 CreateAndTwoInitializeAndSetEncodedFrameCounts_ReportTwoUKMs) {
455 mojom::VideoEncoderUseCase use_case;
456 VideoCodecProfile profile;
459 SVCScalabilityMode svc_mode;
460 EncoderStatus::Codes status;
461 uint64_t num_encoded_frames;
462 } kMetricsCases[] = {
464 mojom::VideoEncoderUseCase::kWebRTC,
468 SVCScalabilityMode::kL2T3Key,
469 EncoderStatus::Codes::kEncoderIllegalState,
473 mojom::VideoEncoderUseCase::kMediaRecorder,
475 gfx::Size(1200, 700),
476 /*is_hardware=*/true,
477 SVCScalabilityMode::kL2T3Key,
478 EncoderStatus::Codes::kOk,
482 constexpr uint64_t kEncoderId = 0;
483 auto [test_recorder, provider] = Create(kTestURL);
484 for (const auto& metrics : kMetricsCases) {
485 provider->Initialize(kEncoderId, metrics.use_case, metrics.profile,
486 metrics.size, metrics.is_hardware, metrics.svc_mode);
487 provider->SetEncodedFrameCount(kEncoderId, metrics.num_encoded_frames);
488 if (metrics.status != EncoderStatus::Codes::kOk) {
489 provider->SetError(kEncoderId, metrics.status);
493 base::RunLoop().RunUntilIdle();
495 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
496 ASSERT_EQ(std::size(kMetricsCases), entries.size());
497 for (size_t i = 0; i < entries.size(); ++i) {
498 const auto* entry = entries[i];
499 const auto& metrics = kMetricsCases[i];
500 EXPECT_UKM(UkmEntry::kHeightName, metrics.size.height());
501 EXPECT_UKM(UkmEntry::kIsHardwareName, metrics.is_hardware);
502 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, metrics.num_encoded_frames);
503 EXPECT_UKM(UkmEntry::kProfileName, metrics.profile);
504 EXPECT_UKM(UkmEntry::kStatusName, static_cast<int64_t>(metrics.status));
505 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(metrics.svc_mode));
506 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(metrics.use_case));
507 EXPECT_UKM(UkmEntry::kWidthName, metrics.size.width());
511 TEST_F(MojoVideoEncoderMetricsProviderServiceTest, HandleTwoEncoders) {
514 mojom::VideoEncoderUseCase use_case;
515 VideoCodecProfile profile;
518 SVCScalabilityMode svc_mode;
519 EncoderStatus::Codes status;
520 uint64_t num_encoded_frames;
521 } kMetricsCases[] = {
524 mojom::VideoEncoderUseCase::kWebRTC,
528 SVCScalabilityMode::kL2T3Key,
529 EncoderStatus::Codes::kEncoderIllegalState,
534 mojom::VideoEncoderUseCase::kMediaRecorder,
536 gfx::Size(1200, 700),
537 /*is_hardware=*/true,
538 SVCScalabilityMode::kL2T3Key,
539 EncoderStatus::Codes::kOk,
543 auto [test_recorder, provider] = Create(kTestURL);
544 for (const auto& metrics : kMetricsCases) {
545 provider->Initialize(metrics.encoder_id, metrics.use_case, metrics.profile,
546 metrics.size, metrics.is_hardware, metrics.svc_mode);
548 for (const auto& metrics : kMetricsCases) {
549 provider->SetEncodedFrameCount(metrics.encoder_id,
550 metrics.num_encoded_frames);
552 for (const auto& metrics : kMetricsCases) {
553 if (metrics.status != EncoderStatus::Codes::kOk) {
554 provider->SetError(metrics.encoder_id, metrics.status);
557 for (const auto& metrics : kMetricsCases) {
558 provider->Complete(metrics.encoder_id);
561 base::RunLoop().RunUntilIdle();
563 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
564 ASSERT_EQ(std::size(kMetricsCases), entries.size());
565 for (size_t i = 0; i < entries.size(); ++i) {
566 const auto* entry = entries[i];
567 const auto& metrics = kMetricsCases[i];
568 EXPECT_UKM(UkmEntry::kHeightName, metrics.size.height());
569 EXPECT_UKM(UkmEntry::kIsHardwareName, metrics.is_hardware);
570 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, metrics.num_encoded_frames);
571 EXPECT_UKM(UkmEntry::kProfileName, metrics.profile);
572 EXPECT_UKM(UkmEntry::kStatusName, static_cast<int64_t>(metrics.status));
573 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(metrics.svc_mode));
574 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(metrics.use_case));
575 EXPECT_UKM(UkmEntry::kWidthName, metrics.size.width());
579 TEST_F(MojoVideoEncoderMetricsProviderServiceTest, IgnoreUnknownEncoderIds) {
580 auto [test_recorder, provider] = Create(kTestURL);
581 constexpr uint64_t kKnownEncoderId = 123;
582 constexpr uint64_t kUnknownEncoderId = 321;
583 constexpr auto kEncoderUseCase = mojom::VideoEncoderUseCase::kWebRTC;
584 constexpr auto kCodecProfile = VP9PROFILE_PROFILE0;
585 constexpr gfx::Size kEncodeSize(1200, 700);
586 constexpr bool kIsHardwareEncoder = true;
587 constexpr auto kSVCMode = SVCScalabilityMode::kL1T3;
588 provider->Initialize(kKnownEncoderId, kEncoderUseCase, kCodecProfile,
589 kEncodeSize, kIsHardwareEncoder, kSVCMode);
590 provider->SetEncodedFrameCount(kUnknownEncoderId, 100);
591 provider->SetError(kUnknownEncoderId,
592 EncoderStatus::Codes::kEncoderFailedEncode);
593 provider->Complete(kUnknownEncoderId);
595 provider->Complete(kKnownEncoderId);
596 // This should be ignored as Complete() is already called.
597 provider->SetError(kKnownEncoderId,
598 EncoderStatus::Codes::kEncoderFailedEncode);
601 base::RunLoop().RunUntilIdle();
603 const auto entries = test_recorder->GetEntriesByName(UkmEntry::kEntryName);
604 ASSERT_EQ(1u, entries.size());
605 const auto* entry = entries[0];
606 EXPECT_UKM(UkmEntry::kHeightName, kEncodeSize.height());
607 EXPECT_UKM(UkmEntry::kIsHardwareName, kIsHardwareEncoder);
608 EXPECT_UKM(UkmEntry::kNumEncodedFramesName, 0);
609 EXPECT_UKM(UkmEntry::kProfileName, kCodecProfile);
610 EXPECT_UKM(UkmEntry::kStatusName,
611 static_cast<int64_t>(EncoderStatus::Codes::kOk));
612 EXPECT_UKM(UkmEntry::kSVCModeName, static_cast<int64_t>(kSVCMode));
613 EXPECT_UKM(UkmEntry::kUseCaseName, static_cast<int64_t>(kEncoderUseCase));
614 EXPECT_UKM(UkmEntry::kWidthName, kEncodeSize.width());