1 // Copyright 2022 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.
9 #include "base/functional/bind.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/test/bind.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "base/test/task_environment.h"
16 #include "media/base/media_switches.h"
17 #include "media/capabilities/webrtc_video_stats_db.h"
18 #include "media/mojo/mojom/media_types.mojom.h"
19 #include "media/mojo/services/webrtc_video_perf_history.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
24 using testing::IsNull;
29 // Aliases for readability.
30 constexpr bool kIsDecode = true;
31 constexpr bool kIsEncode = false;
32 constexpr bool kHardware = true;
33 constexpr bool kSoftware = false;
34 constexpr bool kIsSmooth = true;
35 constexpr bool kIsNotSmooth = false;
36 constexpr VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0;
37 constexpr int32_t kPixelsHd = 1280 * 720;
38 constexpr int32_t kPixelsFullHd = 1920 * 1080;
39 constexpr int32_t kPixels4K = 3840 * 2160;
40 constexpr int kFramesProcessed = 1000;
41 constexpr int kKeyFramesProcessed = 4;
45 class FakeWebrtcVideoStatsDB : public WebrtcVideoStatsDB {
47 FakeWebrtcVideoStatsDB() = default;
48 ~FakeWebrtcVideoStatsDB() override = default;
50 // Call CompleteInitialize(...) to run `init_cb` callback.
51 void Initialize(base::OnceCallback<void(bool)> init_cb) override {
52 EXPECT_FALSE(!!pendnding_init_cb_);
53 pendnding_init_cb_ = std::move(init_cb);
56 // Completes fake initialization, running `init_cb` with the supplied value
58 void CompleteInitialize(bool success) {
59 DVLOG(2) << __func__ << " running with success = " << success;
60 EXPECT_TRUE(!!pendnding_init_cb_);
61 std::move(pendnding_init_cb_).Run(success);
64 // Simple hooks to fail the next calls to AppendDecodeStats() and
65 // GetDecodeStats(). Will be reset to false after the call.
66 void set_fail_next_append(bool fail_append) {
67 fail_next_append_ = fail_append;
69 void set_fail_next_get(bool fail_get) { fail_next_get_ = fail_get; }
71 void AppendVideoStats(const VideoDescKey& key,
72 const VideoStats& new_stats,
73 AppendVideoStatsCB append_done_cb) override {
74 if (fail_next_append_) {
75 fail_next_append_ = false;
76 std::move(append_done_cb).Run(false);
80 std::string key_str = key.Serialize();
81 if (entries_.find(key_str) == entries_.end()) {
82 entries_.emplace(std::make_pair(key_str, VideoStatsEntry{new_stats}));
84 VideoStatsEntry& known_entry = entries_.at(key_str);
87 VideoStats(new_stats.frames_processed, new_stats.key_frames_processed,
88 new_stats.p99_processing_time_ms));
91 std::move(append_done_cb).Run(true);
94 void GetVideoStats(const VideoDescKey& key,
95 GetVideoStatsCB get_stats_cb) override {
97 fail_next_get_ = false;
98 std::move(get_stats_cb).Run(false, absl::nullopt);
102 auto entry_it = entries_.find(key.Serialize());
103 if (entry_it == entries_.end()) {
104 std::move(get_stats_cb).Run(true, absl::nullopt);
106 std::move(get_stats_cb).Run(true, entry_it->second);
110 void GetVideoStatsCollection(
111 const VideoDescKey& key,
112 GetVideoStatsCollectionCB get_stats_cb) override {
113 if (fail_next_get_) {
114 fail_next_get_ = false;
115 std::move(get_stats_cb).Run(false, absl::nullopt);
119 WebrtcVideoStatsDB::VideoStatsCollection collection;
120 std::string key_filter = key.SerializeWithoutPixels();
121 for (auto const& [str, video_stats_entry] : entries_) {
122 if (str.rfind(key_filter, 0) == 0) {
123 absl::optional<int> pixels = VideoDescKey::ParsePixelsFromKey(str);
125 collection.insert({*pixels, std::move(video_stats_entry)});
129 if (collection.empty()) {
130 std::move(get_stats_cb).Run(true, absl::nullopt);
132 std::move(get_stats_cb).Run(true, std::move(collection));
136 void ClearStats(base::OnceClosure clear_done_cb) override {
138 std::move(clear_done_cb).Run();
142 bool fail_next_append_ = false;
143 bool fail_next_get_ = false;
145 std::map<std::string, VideoStatsEntry> entries_;
147 base::OnceCallback<void(bool)> pendnding_init_cb_;
150 class WebrtcVideoPerfHistoryTest : public testing::Test {
152 void SetUp() override {
153 perf_history_ = std::make_unique<WebrtcVideoPerfHistory>(
154 std::make_unique<FakeWebrtcVideoStatsDB>());
157 void TearDown() override { perf_history_.reset(); }
159 FakeWebrtcVideoStatsDB* GetFakeDB() {
160 return static_cast<FakeWebrtcVideoStatsDB*>(perf_history_->db_.get());
163 void PreInitializeDB(bool success) {
164 // Invoke private method to start initialization. Usually invoked by first
165 // API call requiring DB access.
166 perf_history_->InitDatabase();
167 // Complete initialization by firing callback from our fake DB.
168 GetFakeDB()->CompleteInitialize(success);
171 // Tests may set this as the callback for WebrtcVideoPerfHistory::GetPerfInfo
172 // to check the results of the call.
173 MOCK_METHOD1(MockGetPerfInfoCB, void(bool is_smooth));
175 // Tests may set this as the callback for
176 // WebrtcVideoPerfHistory::SavePerfRecord to verify that the data is stored.
177 MOCK_METHOD0(MockSaveDoneCB, void());
179 // Tests should EXPECT_CALL this method prior to ClearHistory() to know that
180 // the operation has completed.
181 MOCK_METHOD0(MockOnClearedHistory, void());
183 MOCK_METHOD1(MockGetWebrtcVideoStatsDBCB, void(WebrtcVideoStatsDB* db));
185 void SavePerfRecord(mojom::WebrtcPredictionFeatures features,
186 mojom::WebrtcVideoStats video_stats,
187 bool expect_callback) {
188 base::OnceClosure save_done_cb = base::BindOnce(
189 &WebrtcVideoPerfHistoryTest::MockSaveDoneCB, base::Unretained(this));
190 if (expect_callback) {
191 EXPECT_CALL(*this, MockSaveDoneCB());
193 perf_history_->GetSaveCallback().Run(features, video_stats,
194 std::move(save_done_cb));
196 void SavePerfRecord(mojom::WebrtcPredictionFeatures features,
197 mojom::WebrtcVideoStats video_stats) {
198 SavePerfRecord(std::move(features), std::move(video_stats),
199 /*expect_callback=*/true);
203 using VideoDescKey = WebrtcVideoStatsDB::VideoDescKey;
204 using VideoStatsEntry = WebrtcVideoStatsDB::VideoStatsEntry;
205 using Features = media::mojom::WebrtcPredictionFeatures;
206 using VideoStats = media::mojom::WebrtcVideoStats;
208 float GetSmoothnessThreshold(bool is_decode) {
209 return WebrtcVideoPerfHistory::GetSmoothnessThreshold(is_decode);
212 float GetSmoothDecisionRatioThreshold() {
213 return WebrtcVideoPerfHistory::GetSmoothDecisionRatioThreshold();
216 base::test::TaskEnvironment task_environment_;
218 // The WebrtcVideoStatsReporter being tested.
219 std::unique_ptr<WebrtcVideoPerfHistory> perf_history_;
222 struct WebrtcPerfHistoryTestParams {
223 const bool defer_initialize;
226 // When bool param is true, tests should wait until the end to run
227 // GetFakeDB()->CompleteInitialize(). Otherwise run PreInitializeDB() at the
229 class WebrtcVideoPerfHistoryParamTest
230 : public testing::WithParamInterface<WebrtcPerfHistoryTestParams>,
231 public WebrtcVideoPerfHistoryTest {};
233 TEST_P(WebrtcVideoPerfHistoryParamTest, GetPerfInfo) {
234 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
235 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
236 // that EXPECT_CALLs arrive in top-to-bottom order.
237 WebrtcPerfHistoryTestParams params = GetParam();
238 testing::InSequence dummy;
240 // Complete initialization in advance of API calls when not asked to defer.
241 if (!params.defer_initialize)
242 PreInitializeDB(/*success=*/true);
244 // First add 2 records to the history. First record with HD resolution and
245 // second with Full HD resolution.
246 constexpr float kP99ProcessingTimeMsSmoothAt60Hz = 12.0f;
247 constexpr float kP99ProcessingTimeMsSmoothAt30Hz = 24.0f;
250 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
251 VideoStats(kFramesProcessed, kKeyFramesProcessed,
252 kP99ProcessingTimeMsSmoothAt60Hz));
253 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
254 VideoStats(kFramesProcessed, kKeyFramesProcessed,
255 kP99ProcessingTimeMsSmoothAt30Hz));
257 // Verify perf history returns is_smooth = true for HD at 30 and 60 fps.
258 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
259 perf_history_->GetPerfInfo(
260 Features::New(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
261 /*frames_per_second=*/30,
262 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
263 base::Unretained(this)));
264 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
265 perf_history_->GetPerfInfo(
266 Features::New(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
267 /*frames_per_second=*/60,
268 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
269 base::Unretained(this)));
271 // Verify perf history returns is_smooth = true for Full HD at 30 fps and
272 // is_smooth = false for Full HD at 60 fps.
273 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
274 perf_history_->GetPerfInfo(
275 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
276 /*frames_per_second=*/30,
277 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
278 base::Unretained(this)));
279 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
280 perf_history_->GetPerfInfo(
281 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
282 /*frames_per_second=*/60,
283 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
284 base::Unretained(this)));
286 // Verify perf history optimistically returns is_smooth = true when no entry
287 // can be found with the given configuration.
288 constexpr VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2;
289 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
290 perf_history_->GetPerfInfo(
291 Features::New(kIsDecode, kUnknownProfile, kPixelsFullHd, kSoftware),
292 /*frames_per_second=*/60,
293 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
294 base::Unretained(this)));
296 // Complete successful deferred DB initialization (see comment at top of test)
297 if (params.defer_initialize) {
298 GetFakeDB()->CompleteInitialize(true);
300 // Allow initialize-deferred API calls to complete.
301 task_environment_.RunUntilIdle();
305 // Test to override the smoothness threshold by setting the corresponding field
307 TEST_P(WebrtcVideoPerfHistoryParamTest,
308 GetPerfInfoSmoothnessThresholdOverride) {
309 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
310 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
311 // that EXPECT_CALLs arrive in top-to-bottom order.
312 WebrtcPerfHistoryTestParams params = GetParam();
313 testing::InSequence dummy;
315 base::test::ScopedFeatureList scoped_feature_list;
316 std::unique_ptr<base::FieldTrialList> field_trial_list;
318 float previousSmoothnessThresholdDecode = GetSmoothnessThreshold(kIsDecode);
319 float previousSmoothnessThresholdEncode = GetSmoothnessThreshold(kIsEncode);
320 // The 99th percentile decode time must be lower than 50% of 1/fps to be
321 // considered smooth.
322 float kNewSmoothnessThresholdDecode = 0.5f;
323 // The 99th percentile encode time must be lower than 120% of 1/fps to be
324 // considered smooth.
325 float kNewSmoothnessThresholdEncode = 1.2f;
327 // Override field trial.
328 base::FieldTrialParams field_trial_params;
329 field_trial_params["smoothness_threshold_decode"] =
330 base::NumberToString(kNewSmoothnessThresholdDecode);
331 field_trial_params["smoothness_threshold_encode"] =
332 base::NumberToString(kNewSmoothnessThresholdEncode);
333 scoped_feature_list.InitAndEnableFeatureWithParameters(
334 media::kWebrtcMediaCapabilitiesParameters, field_trial_params);
335 EXPECT_NE(kNewSmoothnessThresholdDecode, previousSmoothnessThresholdDecode);
336 EXPECT_NE(kNewSmoothnessThresholdEncode, previousSmoothnessThresholdEncode);
337 EXPECT_EQ(kNewSmoothnessThresholdDecode, GetSmoothnessThreshold(kIsDecode));
338 EXPECT_EQ(kNewSmoothnessThresholdEncode, GetSmoothnessThreshold(kIsEncode));
340 // Complete initialization in advance of API calls when not asked to defer.
341 if (!params.defer_initialize)
342 PreInitializeDB(/*success=*/true);
344 constexpr int kFramesPerSecond = 30;
346 // Add a Full HD decode entry just above the new threshold.
347 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
348 VideoStats(kFramesProcessed, kKeyFramesProcessed,
349 /*p99_processing_time_ms=*/1.01 *
350 kNewSmoothnessThresholdDecode * 1000.0 /
352 // Add an HD decode entry just below the new threshold.
353 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
354 VideoStats(kFramesProcessed, kKeyFramesProcessed,
355 /*p99_processing_time_ms=*/0.99 *
356 kNewSmoothnessThresholdDecode * 1000.0 /
359 // Verify that Full HD is not smooth and HD is smooth.
360 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
361 perf_history_->GetPerfInfo(
362 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
364 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
365 base::Unretained(this)));
367 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
368 perf_history_->GetPerfInfo(
369 Features::New(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
371 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
372 base::Unretained(this)));
374 // Add a Full HD encdde entry just above the new threshold.
375 SavePerfRecord(Features(kIsEncode, kKnownProfile, kPixelsFullHd, kSoftware),
376 VideoStats(kFramesProcessed, kKeyFramesProcessed,
377 /*p99_processing_time_ms=*/1.01 *
378 kNewSmoothnessThresholdEncode * 1000.0 /
380 // Add an HD encode entry just below the new threshold.
381 SavePerfRecord(Features(kIsEncode, kKnownProfile, kPixelsHd, kSoftware),
382 VideoStats(kFramesProcessed, kKeyFramesProcessed,
383 /*p99_processing_time_ms=*/0.99 *
384 kNewSmoothnessThresholdEncode * 1000.0 /
387 // Verify that Full HD is not smooth and HD is smooth.
388 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
389 perf_history_->GetPerfInfo(
390 Features::New(kIsEncode, kKnownProfile, kPixelsFullHd, kSoftware),
392 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
393 base::Unretained(this)));
395 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
396 perf_history_->GetPerfInfo(
397 Features::New(kIsEncode, kKnownProfile, kPixelsHd, kSoftware),
399 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
400 base::Unretained(this)));
402 // Complete successful deferred DB initialization (see comment at top of test)
403 if (params.defer_initialize) {
404 GetFakeDB()->CompleteInitialize(true);
406 // Allow initialize-deferred API calls to complete.
407 task_environment_.RunUntilIdle();
411 // Verify that the combined smoothness prediction is correct in the case that
412 // the database contains entries with mixed smoothness predicitions.
413 TEST_P(WebrtcVideoPerfHistoryParamTest, GetPerfInfoCombinedPrediction) {
414 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
415 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
416 // that EXPECT_CALLs arrive in top-to-bottom order.
417 WebrtcPerfHistoryTestParams params = GetParam();
418 testing::InSequence dummy;
420 // Complete initialization in advance of API calls when not asked to defer.
421 if (!params.defer_initialize)
422 PreInitializeDB(/*success=*/true);
424 constexpr float kP99ProcessingTimeMsSmoothAt60Hz = 12.0f;
425 constexpr float kP99ProcessingTimeMsSmoothAt30Hz = 24.0f;
427 // The SmoothDecisionRatioThreshold determines the minimum ratio of smooth
428 // entries for the combined prediction to be considered smooth.
429 constexpr int kNumberOfEntries = 10;
430 const float kSmoothDecisionRatioThreshold = GetSmoothDecisionRatioThreshold();
431 const int kNotSmoothEntries =
432 kNumberOfEntries * (1 - kSmoothDecisionRatioThreshold);
433 const int kSmoothEntries = kNumberOfEntries - kNotSmoothEntries;
435 // Add `kNotSmoothEntries` that are not smooth at 60 fps.
436 for (int i = 0; i < kNotSmoothEntries; ++i) {
438 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
439 VideoStats(kFramesProcessed, kKeyFramesProcessed,
440 kP99ProcessingTimeMsSmoothAt30Hz));
442 // Verify perf history returns is_smooth = false at 60 fps.
443 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
444 perf_history_->GetPerfInfo(
445 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
446 /*frames_per_second=*/60,
447 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
448 base::Unretained(this)));
450 // Add `kSmoothEntries` - 1 that are smooth at 60 fps and verify that
451 // is_smooth = false still.
452 for (int i = 0; i < kSmoothEntries - 1; ++i) {
454 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
455 VideoStats(kFramesProcessed, kKeyFramesProcessed,
456 kP99ProcessingTimeMsSmoothAt60Hz));
458 // Verify perf history returns is_smooth = false at 60 fps.
459 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
460 perf_history_->GetPerfInfo(
461 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
462 /*frames_per_second=*/60,
463 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
464 base::Unretained(this)));
466 // Add one more entry and verify that is_smooth = true now.
467 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
468 VideoStats(kFramesProcessed, kKeyFramesProcessed,
469 kP99ProcessingTimeMsSmoothAt60Hz));
470 // Verify perf history returns is_smooth = true at 60 fps.
471 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
472 perf_history_->GetPerfInfo(
473 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
474 /*frames_per_second=*/60,
475 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
476 base::Unretained(this)));
478 // Add 5 more entries that are smooth at 60 fps and verify that is_smooth =
480 for (int i = 0; i < 5 - 1; ++i) {
482 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
483 VideoStats(kFramesProcessed, kKeyFramesProcessed,
484 kP99ProcessingTimeMsSmoothAt60Hz));
486 // Verify perf history returns is_smooth = true at 60 fps.
487 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
488 perf_history_->GetPerfInfo(
489 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
490 /*frames_per_second=*/60,
491 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
492 base::Unretained(this)));
494 // Complete successful deferred DB initialization (see comment at top of test)
495 if (params.defer_initialize) {
496 GetFakeDB()->CompleteInitialize(true);
498 // Allow initialize-deferred API calls to complete.
499 task_environment_.RunUntilIdle();
503 // Test to override smooth decision ratio threshold by setting the corresponding
504 // field trial parameter.
505 TEST_P(WebrtcVideoPerfHistoryParamTest,
506 GetPerfInfoSmoothDecisionRatioThresholdOverride) {
507 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
508 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
509 // that EXPECT_CALLs arrive in top-to-bottom order.
510 WebrtcPerfHistoryTestParams params = GetParam();
511 testing::InSequence dummy;
513 base::test::ScopedFeatureList scoped_feature_list;
514 std::unique_ptr<base::FieldTrialList> field_trial_list;
515 // Override the smooth decision ratio threshold through the field trial.
516 float previousSmoothDecisionRatioThreshold =
517 GetSmoothDecisionRatioThreshold();
518 // The ratio of smooth entries must be greater than the threshold for the
519 // combined stats to be considered smooth.
520 float kNewSmoothDecisionRatioThreshold = 0.7f;
522 base::FieldTrialParams field_trial_params;
523 field_trial_params["smooth_decision_ratio_threshold"] =
524 base::NumberToString(kNewSmoothDecisionRatioThreshold);
525 scoped_feature_list.InitAndEnableFeatureWithParameters(
526 media::kWebrtcMediaCapabilitiesParameters, field_trial_params);
527 EXPECT_NE(kNewSmoothDecisionRatioThreshold,
528 previousSmoothDecisionRatioThreshold);
529 EXPECT_EQ(kNewSmoothDecisionRatioThreshold,
530 GetSmoothDecisionRatioThreshold());
532 // Complete initialization in advance of API calls when not asked to defer.
533 if (!params.defer_initialize)
534 PreInitializeDB(/*success=*/true);
536 constexpr float kP99ProcessingTimeMsSmoothAt60Hz = 12.0f;
537 constexpr float kP99ProcessingTimeMsSmoothAt30Hz = 24.0f;
538 constexpr int kFramesPerSecond = 60;
540 // Add two smooth Full HD @ 60 fps decode entries.
541 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
542 VideoStats(kFramesProcessed, kKeyFramesProcessed,
543 kP99ProcessingTimeMsSmoothAt60Hz));
544 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
545 VideoStats(kFramesProcessed, kKeyFramesProcessed,
546 kP99ProcessingTimeMsSmoothAt60Hz));
547 // Add one not smooth Full HD @ 30 fps decode entry.
548 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
549 VideoStats(kFramesProcessed, kKeyFramesProcessed,
550 kP99ProcessingTimeMsSmoothAt30Hz));
552 // Verify that Full HD @ 60 fps is not smooth since the ratio threshold is now
553 // set to 0.7, but only 2/3 = 0.66 of the entries are smooth.
554 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
555 perf_history_->GetPerfInfo(
556 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
558 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
559 base::Unretained(this)));
561 // Complete successful deferred DB initialization (see comment at top of test)
562 if (params.defer_initialize) {
563 GetFakeDB()->CompleteInitialize(true);
565 // Allow initialize-deferred API calls to complete.
566 task_environment_.RunUntilIdle();
570 TEST_P(WebrtcVideoPerfHistoryParamTest, GetPerfInfoFrameRateBucketing) {
571 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
572 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
573 // that EXPECT_CALLs arrive in top-to-bottom order.
574 WebrtcPerfHistoryTestParams params = GetParam();
575 testing::InSequence dummy;
577 // Complete initialization in advance of API calls when not asked to defer.
578 if (!params.defer_initialize)
579 PreInitializeDB(/*success=*/true);
581 // First add 2 records to the history. First record with HD resolution and
582 // second with Full HD resolution.
583 constexpr float kP99ProcessingTimeMsSmoothAt60Hz = 12.0f;
584 constexpr float kP99ProcessingTimeMsSmoothAt20Hz = 44.0f;
587 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
588 VideoStats(kFramesProcessed, kKeyFramesProcessed,
589 kP99ProcessingTimeMsSmoothAt60Hz));
590 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
591 VideoStats(kFramesProcessed, kKeyFramesProcessed,
592 kP99ProcessingTimeMsSmoothAt20Hz));
594 // Verify perf history returns is_smooth = true for HD at 60 fps.
595 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
596 perf_history_->GetPerfInfo(
597 Features::New(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
598 /*frames_per_second=*/60,
599 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
600 base::Unretained(this)));
601 // Verify perf history returns is_smooth = true for HD also at 120 fps since
602 // 120 fps is quantized to 60 fps due to privacy concerns.
603 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
604 perf_history_->GetPerfInfo(
605 Features::New(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
606 /*frames_per_second=*/120,
607 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
608 base::Unretained(this)));
610 // Verify perf history returns is_smooth = false for Full HD at both 20 and 30
611 // fps. Even though the processing time would work at 20 fps the output is
612 // still expected to be smooth = false since 20 fps is quantized to 30 fps.
613 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
614 perf_history_->GetPerfInfo(
615 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
616 /*frames_per_second=*/20,
617 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
618 base::Unretained(this)));
619 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
620 perf_history_->GetPerfInfo(
621 Features::New(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
622 /*frames_per_second=*/30,
623 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
624 base::Unretained(this)));
626 // Complete successful deferred DB initialization (see comment at top of test)
627 if (params.defer_initialize) {
628 GetFakeDB()->CompleteInitialize(true);
630 // Allow initialize-deferred API calls to complete.
631 task_environment_.RunUntilIdle();
635 // Only save valid keys and stats.
636 TEST_P(WebrtcVideoPerfHistoryParamTest, OnlySaveValidKeysAndStats) {
637 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
638 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
639 // that EXPECT_CALLs arrive in top-to-bottom order.
640 WebrtcPerfHistoryTestParams params = GetParam();
641 testing::InSequence dummy;
643 // Complete initialization in advance of API calls when not asked to defer.
644 if (!params.defer_initialize)
645 PreInitializeDB(/*success=*/true);
647 constexpr float kValidP99ProcessingTimeMs = 12.0f;
648 // Explicitly state that no save-done callbacks are expected.
649 EXPECT_CALL(*this, MockSaveDoneCB()).Times(0);
650 // Add invalid entries and verify that there's no save done callback.
653 Features(kIsDecode, VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN,
654 kPixelsHd, kSoftware),
655 VideoStats(kFramesProcessed, kKeyFramesProcessed,
656 kValidP99ProcessingTimeMs),
657 /*expect_callback=*/false);
658 // Out of bounds profile.
659 SavePerfRecord(Features(kIsDecode, static_cast<VideoCodecProfile>(1000),
660 kPixelsHd, kSoftware),
661 VideoStats(kFramesProcessed, kKeyFramesProcessed,
662 kValidP99ProcessingTimeMs),
663 /*expect_callback=*/false);
664 // Untracked codec profile.
666 Features(kIsDecode, DOLBYVISION_PROFILE5, kPixelsHd, kSoftware),
667 VideoStats(kFramesProcessed, kKeyFramesProcessed,
668 kValidP99ProcessingTimeMs),
669 /*expect_callback=*/false);
672 Features(kIsDecode, kKnownProfile, /*video_pixels=*/100, kSoftware),
673 VideoStats(kFramesProcessed, kKeyFramesProcessed,
674 kValidP99ProcessingTimeMs),
675 /*expect_callback=*/false);
677 Features(kIsDecode, kKnownProfile, /*video_pixels=*/1e9, kSoftware),
678 VideoStats(kFramesProcessed, kKeyFramesProcessed,
679 kValidP99ProcessingTimeMs),
680 /*expect_callback=*/false);
681 // Too few frames processed.
682 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
683 VideoStats(/*frames_processed=*/10, kKeyFramesProcessed,
684 kValidP99ProcessingTimeMs),
685 /*expect_callback=*/false);
686 // Too many frames processed.
687 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
688 VideoStats(/*frames_processed=*/1e6, kKeyFramesProcessed,
689 kValidP99ProcessingTimeMs),
690 /*expect_callback=*/false);
691 // Key frames higher than frames_processed.
692 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
693 VideoStats(kFramesProcessed,
694 /*key_frames_processed=*/kFramesProcessed + 1,
695 kValidP99ProcessingTimeMs),
696 /*expect_callback=*/false);
697 // Negative processing time.
698 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
699 VideoStats(kFramesProcessed, kKeyFramesProcessed,
700 /*p99_processing_time_ms=*/-1.0f),
701 /*expect_callback=*/false);
702 // Too high processing time.
703 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
704 VideoStats(kFramesProcessed, kKeyFramesProcessed,
705 /*p99_processing_time_ms=*/60000.0f),
706 /*expect_callback=*/false);
708 // Complete successful deferred DB initialization (see comment at top of test)
709 if (params.defer_initialize) {
710 GetFakeDB()->CompleteInitialize(true);
712 // Allow initialize-deferred API calls to complete.
713 task_environment_.RunUntilIdle();
717 TEST_P(WebrtcVideoPerfHistoryParamTest, SmoothIsTrueForUntrackedCodecProfiles) {
718 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
719 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
720 // that EXPECT_CALLs arrive in top-to-bottom order.
721 WebrtcPerfHistoryTestParams params = GetParam();
722 testing::InSequence dummy;
724 // Complete initialization in advance of API calls when not asked to defer.
725 if (!params.defer_initialize)
726 PreInitializeDB(/*success=*/true);
728 // First add 2 records with untracked codec profiles to the history that are
729 // not smooth at 60Hz.
730 constexpr float kP99ProcessingTimeMsNotSmoothAt60Hz = 40.0f;
732 Features(kIsDecode, DOLBYVISION_PROFILE4, kPixelsHd, kSoftware),
733 VideoStats(kFramesProcessed, kKeyFramesProcessed,
734 kP99ProcessingTimeMsNotSmoothAt60Hz),
735 /*expect_callback=*/false);
737 Features(kIsDecode, DOLBYVISION_PROFILE8, kPixelsHd, kSoftware),
738 VideoStats(kFramesProcessed, kKeyFramesProcessed,
739 kP99ProcessingTimeMsNotSmoothAt60Hz),
740 /*expect_callback=*/false);
742 // Verify perf history returns is_smooth = true anyway.
743 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
744 perf_history_->GetPerfInfo(
745 Features::New(kIsDecode, DOLBYVISION_PROFILE4, kPixelsHd, kSoftware),
746 /*frames_per_second=*/60,
747 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
748 base::Unretained(this)));
749 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
750 perf_history_->GetPerfInfo(
751 Features::New(kIsDecode, DOLBYVISION_PROFILE8, kPixelsHd, kSoftware),
752 /*frames_per_second=*/60,
753 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
754 base::Unretained(this)));
756 // Complete successful deferred DB initialization (see comment at top of test)
757 if (params.defer_initialize) {
758 GetFakeDB()->CompleteInitialize(true);
760 // Allow initialize-deferred API calls to complete.
761 task_environment_.RunUntilIdle();
765 TEST_P(WebrtcVideoPerfHistoryParamTest, GetPerfInfoFailedInitialize) {
766 WebrtcPerfHistoryTestParams params = GetParam();
767 // Fail initialization in advance of API calls when not asked to defer.
768 if (!params.defer_initialize)
769 PreInitializeDB(/*success=*/false);
771 // When initialization fails, callback should optimistically claim smooth
773 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
774 perf_history_->GetPerfInfo(
775 Features::New(kIsDecode, kKnownProfile, kPixelsHd, kSoftware),
776 /*frames_per_second=*/30,
777 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
778 base::Unretained(this)));
780 // Fail deferred DB initialization (see comment at top of test).
781 if (params.defer_initialize) {
782 GetFakeDB()->CompleteInitialize(false);
784 // Allow initialize-deferred API calls to complete.
785 task_environment_.RunUntilIdle();
789 TEST_P(WebrtcVideoPerfHistoryParamTest, AppendAndDestroyStats) {
790 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
791 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
792 // that EXPECT_CALLs arrive in top-to-bottom order.
793 WebrtcPerfHistoryTestParams params = GetParam();
794 testing::InSequence dummy;
796 // Complete initialization in advance of API calls when not asked to defer.
797 if (!params.defer_initialize)
798 PreInitializeDB(/*success=*/true);
800 constexpr float kP99ProcessingTimeMsSmoothAt30Hz = 24.0f;
803 SavePerfRecord(Features(kIsEncode, kKnownProfile, kPixelsFullHd, kHardware),
804 VideoStats(kFramesProcessed, kKeyFramesProcessed,
805 kP99ProcessingTimeMsSmoothAt30Hz));
807 // Verify its there before we ClearHistory(). Note that perf is NOT smooth at
809 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth));
810 perf_history_->GetPerfInfo(
811 Features::New(kIsEncode, kKnownProfile, kPixelsFullHd, kHardware),
812 /*frames_per_second=*/60,
813 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
814 base::Unretained(this)));
816 // Initiate async clearing of history.
817 EXPECT_CALL(*this, MockOnClearedHistory());
818 perf_history_->ClearHistory(
819 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockOnClearedHistory,
820 base::Unretained(this)));
822 // Verify record we added above is no longer present.
823 // SUBTLE: The PerfHistory will optimistically respond kIsSmooth when no data
824 // is found. So the signal that the entry was removed is the CB now claims
825 // "smooth" when it claimed NOT smooth just moments before.
826 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
827 perf_history_->GetPerfInfo(
828 Features::New(kIsEncode, kKnownProfile, kPixelsFullHd, kHardware),
829 /*frames_per_second=*/60,
830 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
831 base::Unretained(this)));
833 // Complete successful deferred DB initialization (see comment at top of test)
834 if (params.defer_initialize) {
835 GetFakeDB()->CompleteInitialize(true);
837 // Allow initialize-deferred API calls to complete.
838 task_environment_.RunUntilIdle();
842 TEST_P(WebrtcVideoPerfHistoryParamTest, GetWebrtcVideoStatsDB) {
843 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
844 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
845 // that EXPECT_CALLs arrive in top-to-bottom order.
846 WebrtcPerfHistoryTestParams params = GetParam();
847 testing::InSequence dummy;
849 // Complete initialization in advance of API calls when not asked to defer.
850 if (!params.defer_initialize)
851 PreInitializeDB(/*success=*/true);
853 // Request a pointer to WebrtcVideoStatsDB and verify the callback.
854 EXPECT_CALL(*this, MockGetWebrtcVideoStatsDBCB(_))
855 .WillOnce([&](const auto* db_ptr) {
856 // Not able to simply use a matcher because the DB does not exist at the
857 // time we setup the EXPECT_CALL.
858 EXPECT_EQ(GetFakeDB(), db_ptr);
861 perf_history_->GetWebrtcVideoStatsDB(
862 base::BindOnce(&WebrtcVideoPerfHistoryTest::MockGetWebrtcVideoStatsDBCB,
863 base::Unretained(this)));
865 task_environment_.RunUntilIdle();
867 // Complete successful deferred DB initialization (see comment at top of test)
868 if (params.defer_initialize) {
869 GetFakeDB()->CompleteInitialize(true);
871 // Allow initialize-deferred API calls to complete.
872 task_environment_.RunUntilIdle();
876 TEST_P(WebrtcVideoPerfHistoryParamTest, GetWebrtcVideoStatsDBFailedInitialize) {
877 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
878 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
879 // that EXPECT_CALLs arrive in top-to-bottom order.
880 WebrtcPerfHistoryTestParams params = GetParam();
881 testing::InSequence dummy;
883 // Complete initialization in advance of API calls when not asked to defer.
884 if (!params.defer_initialize)
885 PreInitializeDB(/*success=*/false);
887 // Request a pointer to WebrtcVideoStatsDB and verify the callback provides
888 // a nullptr due to failed initialization.
889 EXPECT_CALL(*this, MockGetWebrtcVideoStatsDBCB(IsNull()));
890 perf_history_->GetWebrtcVideoStatsDB(
891 base::BindOnce(&WebrtcVideoPerfHistoryTest::MockGetWebrtcVideoStatsDBCB,
892 base::Unretained(this)));
894 task_environment_.RunUntilIdle();
896 // Complete failed deferred DB initialization (see comment at top of test)
897 if (params.defer_initialize) {
898 GetFakeDB()->CompleteInitialize(false);
900 // Allow initialize-deferred API calls to complete.
901 task_environment_.RunUntilIdle();
905 TEST_P(WebrtcVideoPerfHistoryParamTest, FailedDatabaseGetForAppend) {
906 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
907 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
908 // that EXPECT_CALLs arrive in top-to-bottom order.
909 WebrtcPerfHistoryTestParams params = GetParam();
911 // Complete initialization in advance of API calls when not asked to defer.
912 if (!params.defer_initialize)
913 PreInitializeDB(/*success=*/true);
915 // Create a simple record. After we fail to save this record we should find
916 // smooth = true (the default for no-data-found).
917 constexpr float kP99ProcessingTimeMsSmoothAt30Hz = 24.0f;
919 // Fail the "get" step of the save (we always get existing stats so that the
920 // new stats can be appended to it).
921 GetFakeDB()->set_fail_next_get(true);
923 // Attempt (and fail) the save.
924 SavePerfRecord(Features(kIsEncode, kKnownProfile, kPixelsFullHd, kHardware),
925 VideoStats(kFramesProcessed, kKeyFramesProcessed,
926 kP99ProcessingTimeMsSmoothAt30Hz));
928 // Verify perf history still returns is_smooth = true since
929 // no data was successfully saved for the given configuration.
930 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
931 perf_history_->GetPerfInfo(
932 Features::New(kIsEncode, kKnownProfile, kPixelsFullHd, kHardware),
933 /*frames_per_second=*/60,
934 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
935 base::Unretained(this)));
937 // Complete successful deferred DB initialization (see comment at top of test)
938 if (params.defer_initialize) {
939 GetFakeDB()->CompleteInitialize(true);
941 // Allow initialize-deferred API calls to complete.
942 task_environment_.RunUntilIdle();
946 TEST_P(WebrtcVideoPerfHistoryParamTest, FailedDatabaseAppend) {
947 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
948 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
949 // that EXPECT_CALLs arrive in top-to-bottom order.
950 WebrtcPerfHistoryTestParams params = GetParam();
952 // Complete initialization in advance of API calls when not asked to defer.
953 if (!params.defer_initialize)
954 PreInitializeDB(/*success=*/true);
956 // Force the DB to fail on the next append.
957 GetFakeDB()->set_fail_next_append(true);
959 // Create a simple record. After we fail to save this record we should find
960 // smooth = true (the default for no-data-found).
962 constexpr float kP99ProcessingTimeMsSmoothAt30Hz = 24.0f;
964 // Attempt (and fail) the save.
965 SavePerfRecord(Features(kIsEncode, kKnownProfile, kPixelsFullHd, kHardware),
966 VideoStats(kFramesProcessed, kKeyFramesProcessed,
967 kP99ProcessingTimeMsSmoothAt30Hz));
969 // Verify perf history still returns is_smooth = true since
970 // no data was successfully saved for the given configuration.
971 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
972 perf_history_->GetPerfInfo(
973 Features::New(kIsEncode, kKnownProfile, kPixelsFullHd, kHardware),
974 /*frames_per_second=*/60,
975 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
976 base::Unretained(this)));
978 // Complete successful deferred DB initialization (see comment at top of test)
979 if (params.defer_initialize) {
980 GetFakeDB()->CompleteInitialize(true);
982 // Allow initialize-deferred API calls to complete.
983 task_environment_.RunUntilIdle();
987 TEST_P(WebrtcVideoPerfHistoryParamTest, GetPerfInfo4KSmoothImpliesHdSmooth) {
988 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
989 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
990 // that EXPECT_CALLs arrive in top-to-bottom order.
991 WebrtcPerfHistoryTestParams params = GetParam();
992 testing::InSequence dummy;
994 // Complete initialization in advance of API calls when not asked to defer.
995 if (!params.defer_initialize)
996 PreInitializeDB(/*success=*/true);
998 // Add 4K entry that indicates that 4K is smooth at 60 Hz.
999 constexpr float kP99ProcessingTimeMsSmoothAt60Hz = 12.0f;
1000 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixels4K, kSoftware),
1001 VideoStats(kFramesProcessed, kKeyFramesProcessed,
1002 kP99ProcessingTimeMsSmoothAt60Hz));
1004 // Verify perf history returns is_smooth = true for all resolutions at 30/60
1006 constexpr int kPixels[] = {1280 * 720, 1920 * 1080, 3840 * 2160};
1007 constexpr int kFramerates[] = {30, 60};
1008 for (auto pixels : kPixels) {
1009 for (auto framerate : kFramerates) {
1010 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
1011 perf_history_->GetPerfInfo(
1012 Features::New(kIsDecode, kKnownProfile, pixels, kSoftware), framerate,
1013 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
1014 base::Unretained(this)));
1018 // Add an entry indicating that Full HD is not smooth.
1019 constexpr float kP99ProcessingTimeMsNotSmoothAt30Hz = 60.0f;
1020 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
1021 VideoStats(kFramesProcessed, kKeyFramesProcessed,
1022 kP99ProcessingTimeMsNotSmoothAt30Hz));
1024 // This is an incosistency, but the 4K entry with smooth=true overrides the
1025 // FullHD entry with smooth=false. Verify perf history returns is_smooth =
1026 // true for all resolutions at 30/60 fps.
1027 for (auto pixels : kPixels) {
1028 for (auto framerate : kFramerates) {
1029 EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth));
1030 perf_history_->GetPerfInfo(
1031 Features::New(kIsDecode, kKnownProfile, pixels, kSoftware), framerate,
1032 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
1033 base::Unretained(this)));
1037 // Complete successful deferred DB initialization (see comment at top of test)
1038 if (params.defer_initialize) {
1039 GetFakeDB()->CompleteInitialize(true);
1041 // Allow initialize-deferred API calls to complete.
1042 task_environment_.RunUntilIdle();
1046 TEST_P(WebrtcVideoPerfHistoryParamTest,
1047 GetPerfInfoFullHdNotSmoothImplies4KNotSmooth) {
1048 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
1049 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
1050 // that EXPECT_CALLs arrive in top-to-bottom order.
1051 WebrtcPerfHistoryTestParams params = GetParam();
1052 testing::InSequence dummy;
1054 // Complete initialization in advance of API calls when not asked to defer.
1055 if (!params.defer_initialize)
1056 PreInitializeDB(/*success=*/true);
1058 // Add entry that indicates that FullHD is not smooth at 30 Hz.
1059 constexpr float kP99ProcessingTimeMsNotSmoothAt30Hz = 60.0f;
1060 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
1061 VideoStats(kFramesProcessed, kKeyFramesProcessed,
1062 kP99ProcessingTimeMsNotSmoothAt30Hz));
1064 // Verify perf history returns is_smooth = true only for resolutions below
1065 // FullHD at 30/60 fps.
1066 constexpr int kPixels[] = {1280 * 720, 1920 * 1080, 3840 * 2160};
1067 constexpr int kFramerates[] = {30, 60};
1068 for (auto pixels : kPixels) {
1069 for (auto framerate : kFramerates) {
1070 EXPECT_CALL(*this, MockGetPerfInfoCB(
1071 pixels < 1920 * 1080 ? kIsSmooth : kIsNotSmooth));
1072 perf_history_->GetPerfInfo(
1073 Features::New(kIsDecode, kKnownProfile, pixels, kSoftware), framerate,
1074 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
1075 base::Unretained(this)));
1079 // Complete successful deferred DB initialization (see comment at top of test)
1080 if (params.defer_initialize) {
1081 GetFakeDB()->CompleteInitialize(true);
1083 // Allow initialize-deferred API calls to complete.
1084 task_environment_.RunUntilIdle();
1088 TEST_P(WebrtcVideoPerfHistoryParamTest,
1089 GetPerfInfoFullHdSmoothEvenIf4KNotSmooth) {
1090 // NOTE: When the DB initialization is deferred, All EXPECT_CALLs are then
1091 // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
1092 // that EXPECT_CALLs arrive in top-to-bottom order.
1093 WebrtcPerfHistoryTestParams params = GetParam();
1094 testing::InSequence dummy;
1096 // Complete initialization in advance of API calls when not asked to defer.
1097 if (!params.defer_initialize)
1098 PreInitializeDB(/*success=*/true);
1100 // Add 4K entry that indicates that 4K is not smooth at 30 Hz.
1101 constexpr float kP99ProcessingTimeMsNotSmoothAt30Hz = 60.0f;
1102 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixels4K, kSoftware),
1103 VideoStats(kFramesProcessed, kKeyFramesProcessed,
1104 kP99ProcessingTimeMsNotSmoothAt30Hz));
1106 // Verify perf history returns is_smooth = true for all resolutions below 4K
1108 constexpr int kPixels[] = {1280 * 720, 1920 * 1080, 3840 * 2160};
1109 constexpr int kFramerates[] = {30, 60};
1110 for (auto pixels : kPixels) {
1111 for (auto framerate : kFramerates) {
1112 EXPECT_CALL(*this, MockGetPerfInfoCB(
1113 pixels <= 1920 * 1080 ? kIsSmooth : kIsNotSmooth));
1114 perf_history_->GetPerfInfo(
1115 Features::New(kIsDecode, kKnownProfile, pixels, kSoftware), framerate,
1116 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
1117 base::Unretained(this)));
1121 // Add an entry indicating that Full HD is smooth.
1122 constexpr float kP99ProcessingTimeMsSmoothAt60Hz = 12.0f;
1123 SavePerfRecord(Features(kIsDecode, kKnownProfile, kPixelsFullHd, kSoftware),
1124 VideoStats(kFramesProcessed, kKeyFramesProcessed,
1125 kP99ProcessingTimeMsSmoothAt60Hz));
1127 // Repeat test. The added entry is consistent with the default prediction.
1128 for (auto pixels : kPixels) {
1129 for (auto framerate : kFramerates) {
1130 EXPECT_CALL(*this, MockGetPerfInfoCB(
1131 pixels <= 1920 * 1080 ? kIsSmooth : kIsNotSmooth));
1132 perf_history_->GetPerfInfo(
1133 Features::New(kIsDecode, kKnownProfile, pixels, kSoftware), framerate,
1134 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockGetPerfInfoCB,
1135 base::Unretained(this)));
1139 // Complete successful deferred DB initialization (see comment at top of test)
1140 if (params.defer_initialize) {
1141 GetFakeDB()->CompleteInitialize(true);
1143 // Allow initialize-deferred API calls to complete.
1144 task_environment_.RunUntilIdle();
1148 const WebrtcPerfHistoryTestParams kWebrtcPerfHistoryTestParams[] = {
1149 {/*defer_initialize=*/true},
1150 {/*defer_initialize=*/false},
1153 INSTANTIATE_TEST_SUITE_P(VaryDBInitTiming,
1154 WebrtcVideoPerfHistoryParamTest,
1155 ::testing::ValuesIn(kWebrtcPerfHistoryTestParams));
1158 // The following tests are not parameterized. They instead always hard code
1159 // deferred initialization.
1162 TEST_F(WebrtcVideoPerfHistoryTest, ClearHistoryTriggersSuccessfulInitialize) {
1163 // Clear the DB. Completion callback shouldn't fire until initialize
1165 EXPECT_CALL(*this, MockOnClearedHistory()).Times(0);
1166 perf_history_->ClearHistory(
1167 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockOnClearedHistory,
1168 base::Unretained(this)));
1170 // Give completion callback a chance to fire. Confirm it did not fire.
1171 task_environment_.RunUntilIdle();
1172 testing::Mock::VerifyAndClearExpectations(this);
1174 // Expect completion callback after we successfully initialize.
1175 EXPECT_CALL(*this, MockOnClearedHistory());
1176 GetFakeDB()->CompleteInitialize(true);
1178 // Give deferred callback a chance to fire.
1179 task_environment_.RunUntilIdle();
1182 TEST_F(WebrtcVideoPerfHistoryTest, ClearHistoryTriggersFailedInitialize) {
1183 // Clear the DB. Completion callback shouldn't fire until initialize
1185 EXPECT_CALL(*this, MockOnClearedHistory()).Times(0);
1186 perf_history_->ClearHistory(
1187 base::BindOnce(&WebrtcVideoPerfHistoryParamTest::MockOnClearedHistory,
1188 base::Unretained(this)));
1190 // Give completion callback a chance to fire. Confirm it did not fire.
1191 task_environment_.RunUntilIdle();
1192 testing::Mock::VerifyAndClearExpectations(this);
1194 // Expect completion callback after completing initialize. "Failure" is
1195 // still a form of completion.
1196 EXPECT_CALL(*this, MockOnClearedHistory());
1197 GetFakeDB()->CompleteInitialize(false);
1199 // Give deferred callback a chance to fire.
1200 task_environment_.RunUntilIdle();
1203 } // namespace media