| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <map> |
| #include <string> |
| |
| #include "base/bind.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/run_loop.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/task/post_task.h" |
| #include "base/test/bind_test_util.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/task_environment.h" |
| #include "components/ukm/test_ukm_recorder.h" |
| #include "media/base/key_systems.h" |
| #include "media/base/media_switches.h" |
| #include "media/capabilities/video_decode_stats_db.h" |
| #include "media/mojo/mojom/media_types.mojom.h" |
| #include "media/mojo/services/test_helpers.h" |
| #include "media/mojo/services/video_decode_perf_history.h" |
| #include "services/metrics/public/cpp/ukm_builders.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| |
| using UkmEntry = ukm::builders::Media_VideoDecodePerfRecord; |
| using testing::IsNull; |
| using testing::_; |
| |
| namespace { |
| |
| // Aliases for readability. |
| const bool kIsSmooth = true; |
| const bool kIsNotSmooth = false; |
| const bool kIsPowerEfficient = true; |
| const bool kIsNotPowerEfficient = false; |
| const url::Origin kOrigin = url::Origin::Create(GURL("http://example.com")); |
| const bool kIsTopFrame = true; |
| const uint64_t kPlayerId = 1234u; |
| |
| } // namespace |
| |
| namespace media { |
| |
| class FakeVideoDecodeStatsDB : public VideoDecodeStatsDB { |
| public: |
| FakeVideoDecodeStatsDB() = default; |
| ~FakeVideoDecodeStatsDB() override = default; |
| |
| // Call CompleteInitialize(...) to run |init_cb| callback. |
| void Initialize(base::OnceCallback<void(bool)> init_cb) override { |
| pendnding_init_cb_ = std::move(init_cb); |
| } |
| |
| // Completes fake initialization, running |init_cb| with the supplied value |
| // for success. |
| void CompleteInitialize(bool success) { |
| DVLOG(2) << __func__ << " running with success = " << success; |
| EXPECT_FALSE(!pendnding_init_cb_); |
| std::move(pendnding_init_cb_).Run(success); |
| } |
| |
| // Simple hooks to fail the next calls to AppendDecodeStats() and |
| // GetDecodeStats(). Will be reset to false after the call. |
| void set_fail_next_append(bool fail_append) { |
| fail_next_append_ = fail_append; |
| } |
| void set_fail_next_get(bool fail_get) { fail_next_get_ = fail_get; } |
| |
| void AppendDecodeStats(const VideoDescKey& key, |
| const DecodeStatsEntry& new_entry, |
| AppendDecodeStatsCB append_done_cb) override { |
| if (fail_next_append_) { |
| fail_next_append_ = false; |
| std::move(append_done_cb).Run(false); |
| return; |
| } |
| |
| std::string key_str = key.Serialize(); |
| if (entries_.find(key_str) == entries_.end()) { |
| entries_.emplace(std::make_pair(key_str, new_entry)); |
| } else { |
| const DecodeStatsEntry& known_entry = entries_.at(key_str); |
| entries_.at(key_str) = DecodeStatsEntry( |
| known_entry.frames_decoded + new_entry.frames_decoded, |
| known_entry.frames_dropped + new_entry.frames_dropped, |
| known_entry.frames_power_efficient + |
| new_entry.frames_power_efficient); |
| } |
| |
| std::move(append_done_cb).Run(true); |
| } |
| |
| void GetDecodeStats(const VideoDescKey& key, |
| GetDecodeStatsCB get_stats_cb) override { |
| if (fail_next_get_) { |
| fail_next_get_ = false; |
| std::move(get_stats_cb).Run(false, nullptr); |
| return; |
| } |
| |
| auto entry_it = entries_.find(key.Serialize()); |
| if (entry_it == entries_.end()) { |
| std::move(get_stats_cb).Run(true, nullptr); |
| } else { |
| std::move(get_stats_cb) |
| .Run(true, std::make_unique<DecodeStatsEntry>(entry_it->second)); |
| } |
| } |
| |
| void ClearStats(base::OnceClosure clear_done_cb) override { |
| entries_.clear(); |
| std::move(clear_done_cb).Run(); |
| } |
| |
| private: |
| friend class VideoDecodePerfHistoryTest; |
| |
| // Private method for immediate retrieval of stats for test helpers. |
| std::unique_ptr<DecodeStatsEntry> GetDecodeStatsSync( |
| const VideoDescKey& key) { |
| auto entry_it = entries_.find(key.Serialize()); |
| if (entry_it == entries_.end()) { |
| return nullptr; |
| } else { |
| return std::make_unique<DecodeStatsEntry>(entry_it->second); |
| } |
| } |
| |
| bool fail_next_append_ = false; |
| bool fail_next_get_ = false; |
| |
| std::map<std::string, DecodeStatsEntry> entries_; |
| |
| base::OnceCallback<void(bool)> pendnding_init_cb_; |
| }; |
| |
| class VideoDecodePerfHistoryTest : public testing::Test { |
| public: |
| // Indicates what type of UKM verification should be performed upon saving |
| // new stats to the perf history. |
| enum class UkmVerifcation { |
| kNoUkmsAdded, |
| kSaveTriggersUkm, |
| }; |
| |
| void SetUp() override { |
| test_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); |
| perf_history_ = std::make_unique<VideoDecodePerfHistory>( |
| std::make_unique<FakeVideoDecodeStatsDB>()); |
| } |
| |
| void TearDown() override { perf_history_.reset(); } |
| |
| FakeVideoDecodeStatsDB* GetFakeDB() { |
| return static_cast<FakeVideoDecodeStatsDB*>(perf_history_->db_.get()); |
| } |
| |
| void PreInitializeDB(bool initialize_success) { |
| // Invoke private method to start initialization. Usually invoked by first |
| // API call requiring DB access. |
| perf_history_->InitDatabase(); |
| // Complete initialization by firing callback from our fake DB. |
| GetFakeDB()->CompleteInitialize(initialize_success); |
| } |
| |
| double GetMaxSmoothDroppedFramesPercent(bool is_eme = false) { |
| return VideoDecodePerfHistory::GetMaxSmoothDroppedFramesPercent(is_eme); |
| } |
| |
| // Tests may set this as the callback for VideoDecodePerfHistory::GetPerfInfo |
| // to check the results of the call. |
| MOCK_METHOD2(MockGetPerfInfoCB, |
| void(bool is_smooth, bool is_power_efficient)); |
| |
| // Tests should EXPECT_CALL this method prior to ClearHistory() to know that |
| // the operation has completed. |
| MOCK_METHOD0(MockOnClearedHistory, void()); |
| |
| MOCK_METHOD1(MockGetVideoDecodeStatsDBCB, void(VideoDecodeStatsDB* db)); |
| |
| // Internal check that the UKM verification is complete before the test exits. |
| MOCK_METHOD0(UkmVerifyDoneCb, void()); |
| |
| void SavePerfRecord(UkmVerifcation ukm_verification, |
| const url::Origin& origin, |
| bool is_top_frame, |
| mojom::PredictionFeatures features, |
| mojom::PredictionTargets targets, |
| uint64_t player_id) { |
| // Manually associate URL with |source_id|. In production this happens |
| // externally at a higher layer. |
| const ukm::SourceId source_id = test_recorder_->GetNewSourceID(); |
| test_recorder_->UpdateSourceURL(source_id, origin.GetURL()); |
| |
| // Use save callback to verify UKM reporting. |
| base::OnceClosure save_done_cb; |
| switch (ukm_verification) { |
| case UkmVerifcation::kSaveTriggersUkm: { |
| // Expect UKM report with given properties upon successful save. Use |
| // old stats values from DB to set expectations about what API would |
| // have claimed pre-save. |
| std::unique_ptr<DecodeStatsEntry> old_stats = |
| GetStatsForFeatures(features); |
| save_done_cb = |
| base::BindOnce(&VideoDecodePerfHistoryTest::VerifyLastUkmReport, |
| base::Unretained(this), origin, is_top_frame, |
| features, targets, player_id, std::move(old_stats)); |
| break; |
| } |
| case UkmVerifcation::kNoUkmsAdded: { |
| // Expect no additional UKM entries upon failing to save. Capture the |
| // current entry count before save to verify no new entries are added. |
| size_t current_num_entries = |
| test_recorder_->GetEntriesByName(UkmEntry::kEntryName).size(); |
| save_done_cb = base::BindOnce( |
| &VideoDecodePerfHistoryTest::VerifyNoUkmReportForFailedSave, |
| base::Unretained(this), current_num_entries); |
| break; |
| } |
| } |
| |
| // Check that the UKM verification is complete before the test exits. |
| EXPECT_CALL(*this, UkmVerifyDoneCb()); |
| |
| perf_history_->GetSaveCallback().Run( |
| source_id, learning::FeatureValue(kOrigin.host()), is_top_frame, |
| features, targets, player_id, std::move(save_done_cb)); |
| } |
| |
| protected: |
| using VideoDescKey = VideoDecodeStatsDB::VideoDescKey; |
| using DecodeStatsEntry = VideoDecodeStatsDB::DecodeStatsEntry; |
| |
| // Private helper to public test methods. This bypasses VPH::GetPerfInfo() |
| // to synchronously grab stats from the fake DB. Tests should instead use |
| // the VPH::GetPerfInfo(). |
| std::unique_ptr<DecodeStatsEntry> GetStatsForFeatures( |
| mojom::PredictionFeatures features) { |
| VideoDecodeStatsDB::VideoDescKey video_key = |
| VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey( |
| features.profile, features.video_size, features.frames_per_sec, |
| features.key_system, features.use_hw_secure_codecs); |
| return GetFakeDB()->GetDecodeStatsSync(video_key); |
| } |
| |
| // Lookup up the most recent recorded entry and verify its properties against |
| // method arguments. |
| void VerifyLastUkmReport(const url::Origin& origin, |
| bool is_top_frame, |
| mojom::PredictionFeatures features, |
| mojom::PredictionTargets new_targets, |
| uint64_t player_id, |
| std::unique_ptr<DecodeStatsEntry> old_stats) { |
| #define EXPECT_UKM(name, value) \ |
| test_recorder_->ExpectEntryMetric(entry, name, value) |
| #define EXPECT_NO_UKM(name) \ |
| EXPECT_FALSE(test_recorder_->EntryHasMetric(entry, name)) |
| |
| const auto& entries = |
| test_recorder_->GetEntriesByName(UkmEntry::kEntryName); |
| ASSERT_GE(entries.size(), 1U); |
| auto* entry = entries.back(); |
| |
| // Verify stream properties. Make a key to ensure we check bucketed values. |
| VideoDecodeStatsDB::VideoDescKey key = |
| VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey( |
| features.profile, features.video_size, features.frames_per_sec, |
| features.key_system, features.use_hw_secure_codecs); |
| test_recorder_->ExpectEntrySourceHasUrl(entry, origin.GetURL()); |
| EXPECT_UKM(UkmEntry::kVideo_InTopFrameName, is_top_frame); |
| EXPECT_UKM(UkmEntry::kVideo_PlayerIDName, player_id); |
| EXPECT_UKM(UkmEntry::kVideo_CodecProfileName, key.codec_profile); |
| EXPECT_UKM(UkmEntry::kVideo_FramesPerSecondName, key.frame_rate); |
| EXPECT_UKM(UkmEntry::kVideo_NaturalHeightName, key.size.height()); |
| EXPECT_UKM(UkmEntry::kVideo_NaturalWidthName, key.size.width()); |
| if (key.key_system.empty()) { |
| EXPECT_NO_UKM(UkmEntry::kVideo_EME_KeySystemName); |
| EXPECT_NO_UKM(UkmEntry::kVideo_EME_UseHwSecureCodecsName); |
| } else { |
| EXPECT_UKM(UkmEntry::kVideo_EME_KeySystemName, |
| GetKeySystemIntForUKM(key.key_system)); |
| EXPECT_UKM(UkmEntry::kVideo_EME_UseHwSecureCodecsName, |
| key.use_hw_secure_codecs); |
| } |
| |
| // Verify past stats. |
| bool past_is_smooth = false; |
| bool past_is_efficient = false; |
| perf_history_->AssessStats(key, old_stats.get(), &past_is_smooth, |
| &past_is_efficient); |
| EXPECT_UKM(UkmEntry::kPerf_ApiWouldClaimIsSmoothName, past_is_smooth); |
| EXPECT_UKM(UkmEntry::kPerf_ApiWouldClaimIsPowerEfficientName, |
| past_is_efficient); |
| // Zero it out to make verification readable. |
| if (!old_stats) |
| old_stats.reset(new DecodeStatsEntry(0, 0, 0)); |
| EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesDecodedName, |
| old_stats->frames_decoded); |
| EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesDroppedName, |
| old_stats->frames_dropped); |
| EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesPowerEfficientName, |
| old_stats->frames_power_efficient); |
| |
| // Verify latest stats. |
| VideoDecodeStatsDB::DecodeStatsEntry new_stats( |
| new_targets.frames_decoded, new_targets.frames_dropped, |
| new_targets.frames_power_efficient); |
| bool new_is_smooth = false; |
| bool new_is_efficient = false; |
| perf_history_->AssessStats(key, &new_stats, &new_is_smooth, |
| &new_is_efficient); |
| EXPECT_UKM(UkmEntry::kPerf_RecordIsSmoothName, new_is_smooth); |
| EXPECT_UKM(UkmEntry::kPerf_RecordIsPowerEfficientName, new_is_efficient); |
| EXPECT_UKM(UkmEntry::kPerf_VideoFramesDecodedName, |
| new_stats.frames_decoded); |
| EXPECT_UKM(UkmEntry::kPerf_VideoFramesDroppedName, |
| new_stats.frames_dropped); |
| EXPECT_UKM(UkmEntry::kPerf_VideoFramesPowerEfficientName, |
| new_stats.frames_power_efficient); |
| |
| #undef EXPECT_UKM |
| #undef EXPECT_NO_UKM |
| |
| UkmVerifyDoneCb(); |
| } |
| |
| void VerifyNoUkmReportForFailedSave(size_t expected_num_ukm_entries) { |
| // Verify no new UKM entries appear after failed save. |
| const auto& entries = |
| test_recorder_->GetEntriesByName(UkmEntry::kEntryName); |
| EXPECT_EQ(expected_num_ukm_entries, entries.size()); |
| |
| UkmVerifyDoneCb(); |
| } |
| |
| static constexpr double kMinPowerEfficientDecodedFramePercent = |
| VideoDecodePerfHistory::kMinPowerEfficientDecodedFramePercent; |
| |
| base::test::TaskEnvironment task_environment_; |
| |
| std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_recorder_; |
| |
| // The VideoDecodeStatsReporter being tested. |
| std::unique_ptr<VideoDecodePerfHistory> perf_history_; |
| }; |
| |
| struct PerfHistoryTestParams { |
| const bool defer_initialize; |
| const std::string key_system; |
| const bool use_hw_secure_codecs; |
| }; |
| |
| // When bool param is true, tests should wait until the end to run |
| // GetFakeDB()->CompleteInitialize(). Otherwise run PreInitializeDB() at the |
| // test start. |
| class VideoDecodePerfHistoryParamTest |
| : public testing::WithParamInterface<PerfHistoryTestParams>, |
| public VideoDecodePerfHistoryTest {}; |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, GetPerfInfo_Smooth) { |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| testing::InSequence dummy; |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // First add 2 records to the history. The second record has a higher frame |
| // rate and a higher number of dropped frames such that it is "not smooth". |
| const VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0; |
| const gfx::Size kKownSize(100, 200); |
| const int kSmoothFrameRate = 30; |
| const int kNotSmoothFrameRate = 90; |
| const int kFramesDecoded = 1000; |
| const int kNotPowerEfficientFramesDecoded = 0; |
| // Sets the ratio of dropped frames to barely qualify as smooth. |
| const int kSmoothFramesDropped = |
| kFramesDecoded * GetMaxSmoothDroppedFramesPercent(); |
| // Set the ratio of dropped frames to barely qualify as NOT smooth. |
| const int kNotSmoothFramesDropped = |
| kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1; |
| |
| // Add the entries. |
| SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kSmoothFramesDropped, |
| kNotPowerEfficientFramesDecoded), |
| kPlayerId); |
| SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kKnownProfile, kKownSize, kNotSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kNotSmoothFramesDropped, |
| kNotPowerEfficientFramesDecoded), |
| kPlayerId); |
| |
| // Verify perf history returns is_smooth = true for the smooth entry. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Verify perf history returns is_smooth = false for the NOT smooth entry. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsNotPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kKnownProfile, kKownSize, kNotSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Verify perf history optimistically returns is_smooth = true when no entry |
| // can be found with the given configuration. |
| const VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2; |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kUnknownProfile, kKownSize, kNotSmoothFrameRate), |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, GetPerfInfo_PowerEfficient) { |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| testing::InSequence dummy; |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // First add 3 records to the history: |
| // - the first has a high number of power efficiently decoded frames; |
| // - the second has a low number of power efficiently decoded frames; |
| // - the third is similar to the first with a high number of dropped frames. |
| const VideoCodecProfile kPowerEfficientProfile = VP9PROFILE_PROFILE0; |
| const VideoCodecProfile kNotPowerEfficientProfile = VP8PROFILE_ANY; |
| const gfx::Size kKownSize(100, 200); |
| const int kSmoothFrameRate = 30; |
| const int kNotSmoothFrameRate = 90; |
| const int kFramesDecoded = 1000; |
| const int kPowerEfficientFramesDecoded = |
| kFramesDecoded * kMinPowerEfficientDecodedFramePercent; |
| const int kNotPowerEfficientFramesDecoded = |
| kFramesDecoded * kMinPowerEfficientDecodedFramePercent - 1; |
| // Sets the ratio of dropped frames to barely qualify as smooth. |
| const int kSmoothFramesDropped = |
| kFramesDecoded * GetMaxSmoothDroppedFramesPercent(); |
| // Set the ratio of dropped frames to barely qualify as NOT smooth. |
| const int kNotSmoothFramesDropped = |
| kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1; |
| |
| // Add the entries. |
| SavePerfRecord( |
| UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kPowerEfficientProfile, kKownSize, kSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kSmoothFramesDropped, |
| kPowerEfficientFramesDecoded), |
| kPlayerId); |
| SavePerfRecord( |
| UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kNotPowerEfficientProfile, kKownSize, kSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kSmoothFramesDropped, |
| kNotPowerEfficientFramesDecoded), |
| kPlayerId); |
| SavePerfRecord( |
| UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kPowerEfficientProfile, kKownSize, kNotSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kNotSmoothFramesDropped, |
| kPowerEfficientFramesDecoded), |
| kPlayerId); |
| |
| // Verify perf history returns is_smooth = true, is_power_efficient = true. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kPowerEfficientProfile, kKownSize, kSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Verify perf history returns is_smooth = true, is_power_efficient = false. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kNotPowerEfficientProfile, kKownSize, kSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Verify perf history returns is_smooth = false, is_power_efficient = true. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kPowerEfficientProfile, kKownSize, kNotSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Verify perf history optimistically returns is_smooth = true and |
| // is_power_efficient = true when no entry can be found with the given |
| // configuration. |
| const VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2; |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kUnknownProfile, kKownSize, kNotSmoothFrameRate, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, GetPerfInfo_FailedInitialize) { |
| PerfHistoryTestParams params = GetParam(); |
| // Fail initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ false); |
| |
| const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0; |
| const gfx::Size kSize(100, 200); |
| const int kFrameRate = 30; |
| |
| // When initialization fails, callback should optimistically claim both smooth |
| // and power efficient performance. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Fail deferred DB initialization (see comment at top of test). |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(false); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, AppendAndDestroyStats) { |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| testing::InSequence dummy; |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // Add a simple record to the history. |
| const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0; |
| const gfx::Size kSize(100, 200); |
| const int kFrameRate = 30; |
| const int kFramesDecoded = 1000; |
| const int kManyFramesDropped = kFramesDecoded / 2; |
| const int kFramesPowerEfficient = kFramesDecoded; |
| SavePerfRecord( |
| UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kManyFramesDropped, kFramesPowerEfficient), |
| kPlayerId); |
| |
| // Verify its there before we ClearHistory(). Note that perf is NOT smooth. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Initiate async clearing of history. |
| EXPECT_CALL(*this, MockOnClearedHistory()); |
| perf_history_->ClearHistory( |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockOnClearedHistory, |
| base::Unretained(this))); |
| |
| // Verify record we added above is no longer present. |
| // SUBTLE: The PerfHistory will optimistically respond kIsSmooth when no data |
| // is found. So the signal that the entry was removed is the CB now claims |
| // "smooth" when it claimed NOT smooth just moments before. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, GetVideoDecodeStatsDB) { |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| testing::InSequence dummy; |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // Request a pointer to VideoDecodeStatsDB and verify the callback. |
| EXPECT_CALL(*this, MockGetVideoDecodeStatsDBCB(_)) |
| .WillOnce([&](const auto* db_ptr) { |
| // Not able to simply use a matcher because the DB does not exist at the |
| // time we setup the EXPECT_CALL. |
| EXPECT_EQ(GetFakeDB(), db_ptr); |
| }); |
| |
| perf_history_->GetVideoDecodeStatsDB( |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetVideoDecodeStatsDBCB, |
| base::Unretained(this))); |
| |
| task_environment_.RunUntilIdle(); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, |
| GetVideoDecodeStatsDB_FailedInitialize) { |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| testing::InSequence dummy; |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ false); |
| |
| // Request a pointer to VideoDecodeStatsDB and verify the callback provides |
| // a nullptr due to failed initialization. |
| EXPECT_CALL(*this, MockGetVideoDecodeStatsDBCB(IsNull())); |
| perf_history_->GetVideoDecodeStatsDB( |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetVideoDecodeStatsDBCB, |
| base::Unretained(this))); |
| |
| task_environment_.RunUntilIdle(); |
| |
| // Complete failed deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(false); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, FailedDatabaseGetForAppend) { |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // Create a record that is neither smooth nor power efficient. After we fail |
| // to save this record we should find smooth = power_efficient = true (the |
| // default for no-data-found). |
| const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0; |
| const gfx::Size kSize(100, 200); |
| const int kFrameRate = 30; |
| const int kFramesDecoded = 1000; |
| const int kFramesDropped = |
| kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1; |
| const int kFramesPowerEfficient = 0; |
| |
| // Fail the "get" step of the save (we always get existing stats prior to |
| // save for UKM reporting). |
| GetFakeDB()->set_fail_next_get(true); |
| |
| // Attempt (and fail) the save. UKM report depends on successful retrieval |
| // of stats from the DB, so no UKM reporting should occur here. |
| SavePerfRecord( |
| UkmVerifcation::kNoUkmsAdded, kOrigin, kIsTopFrame, |
| MakeFeatures(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kFramesDropped, kFramesPowerEfficient), |
| kPlayerId); |
| |
| // Verify perf history still returns is_smooth = power_efficient = true since |
| // no data was successfully saved for the given configuration. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, FailedDatabaseAppend) { |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // Force the DB to fail on the next append. |
| GetFakeDB()->set_fail_next_append(true); |
| |
| // Create a record that is neither smooth nor power efficient. After we fail |
| // to save this record we should find smooth = power_efficient = true (the |
| // default for no-data-found). |
| const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0; |
| const gfx::Size kSize(100, 200); |
| const int kFrameRate = 30; |
| const int kFramesDecoded = 1000; |
| const int kFramesDropped = |
| kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1; |
| const int kFramesPowerEfficient = 0; |
| |
| // Attempt (and fail) the save. Note that we still expect UKM to be reported |
| // because we successfully retrieved stats from the DB, we just fail to append |
| // the new stats. UKM reporting occurs between retrieval and appending. |
| SavePerfRecord( |
| UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kFramesDropped, kFramesPowerEfficient), |
| kPlayerId); |
| |
| // Verify perf history still returns is_smooth = power_efficient = true since |
| // no data was successfully saved for the given configuration. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system, |
| params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| // Tests that the feature parameters are used to override constants for the |
| // Media Capabilities feature. |
| // To avoid race conditions when setting the parameter, the test sets it when |
| // starting and make sure the values recorded to the DB wouldn't be smooth per |
| // the default value. |
| TEST_P(VideoDecodePerfHistoryParamTest, |
| SmoothThresholdFinchOverride_NoEmeOverride) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| |
| // EME and non EME threshold should initially be the same (neither is |
| // overridden). |
| double previous_smooth_dropped_frames_threshold = |
| GetMaxSmoothDroppedFramesPercent(false /* is_eme */); |
| EXPECT_EQ(previous_smooth_dropped_frames_threshold, |
| GetMaxSmoothDroppedFramesPercent(true /* is_eme */)); |
| |
| double new_smooth_dropped_frames_threshold = |
| previous_smooth_dropped_frames_threshold / 2; |
| |
| ASSERT_LT(new_smooth_dropped_frames_threshold, |
| previous_smooth_dropped_frames_threshold); |
| |
| // Override field trial. |
| base::FieldTrialParams trial_params; |
| trial_params |
| [VideoDecodePerfHistory::kMaxSmoothDroppedFramesPercentParamName] = |
| base::NumberToString(new_smooth_dropped_frames_threshold); |
| scoped_feature_list.InitAndEnableFeatureWithParameters( |
| media::kMediaCapabilitiesWithParameters, trial_params); |
| |
| base::FieldTrialParams actual_trial_params; |
| EXPECT_TRUE(base::GetFieldTrialParamsByFeature( |
| media::kMediaCapabilitiesWithParameters, &actual_trial_params)); |
| EXPECT_EQ(trial_params, actual_trial_params); |
| |
| // Non EME threshold is overridden. |
| EXPECT_EQ(new_smooth_dropped_frames_threshold, |
| GetMaxSmoothDroppedFramesPercent(false /* is_eme */)); |
| |
| // EME threshold is also implicitly overridden (we didn't set an EME specific |
| // value, so it should defer to the non-EME override). |
| EXPECT_EQ(new_smooth_dropped_frames_threshold, |
| GetMaxSmoothDroppedFramesPercent(true /* is_eme */)); |
| |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| testing::InSequence dummy; |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // First add 2 records to the history. The second record has a higher frame |
| // rate and a higher number of dropped frames such that it is "not smooth". |
| const VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0; |
| const gfx::Size kKownSize(100, 200); |
| const int kSmoothFrameRatePrevious = 30; |
| const int kSmoothFrameRateNew = 90; |
| const int kFramesDecoded = 1000; |
| const int kNotPowerEfficientFramesDecoded = 0; |
| |
| // Sets the ratio of dropped frames to qualify as smooth per the default |
| // threshold. |
| const int kSmoothFramesDroppedPrevious = |
| kFramesDecoded * previous_smooth_dropped_frames_threshold; |
| // Sets the ratio of dropped frames to quality as smooth per the new |
| // threshold. |
| const int kSmoothFramesDroppedNew = |
| kFramesDecoded * new_smooth_dropped_frames_threshold; |
| |
| // Add the entry. |
| SavePerfRecord( |
| UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRatePrevious, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kSmoothFramesDroppedPrevious, |
| kNotPowerEfficientFramesDecoded), |
| kPlayerId); |
| |
| SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRateNew, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kSmoothFramesDroppedNew, |
| kNotPowerEfficientFramesDecoded), |
| kPlayerId); |
| |
| // Verify perf history returns is_smooth = false for entry that would be |
| // smooth per previous smooth threshold. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsNotPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRatePrevious, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Verify perf history returns is_smooth = true for entry that would be |
| // smooth per new smooth theshold. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRateNew, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| TEST_P(VideoDecodePerfHistoryParamTest, |
| SmoothThresholdFinchOverride_WithEmeOverride) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| |
| // EME and non EME threshold should initially be the same (neither is |
| // overridden). |
| double previous_smooth_dropped_frames_threshold = |
| GetMaxSmoothDroppedFramesPercent(false /* is_eme */); |
| EXPECT_EQ(previous_smooth_dropped_frames_threshold, |
| GetMaxSmoothDroppedFramesPercent(true /* is_eme */)); |
| |
| double new_CLEAR_smooth_dropped_frames_threshold = |
| previous_smooth_dropped_frames_threshold / 2; |
| double new_EME_smooth_dropped_frames_threshold = |
| previous_smooth_dropped_frames_threshold / 3; |
| |
| ASSERT_LT(new_CLEAR_smooth_dropped_frames_threshold, |
| previous_smooth_dropped_frames_threshold); |
| ASSERT_LT(new_EME_smooth_dropped_frames_threshold, |
| new_CLEAR_smooth_dropped_frames_threshold); |
| |
| // Override field trial. |
| base::FieldTrialParams trial_params; |
| trial_params |
| [VideoDecodePerfHistory::kMaxSmoothDroppedFramesPercentParamName] = |
| base::NumberToString(new_CLEAR_smooth_dropped_frames_threshold); |
| trial_params |
| [VideoDecodePerfHistory::kEmeMaxSmoothDroppedFramesPercentParamName] = |
| base::NumberToString(new_EME_smooth_dropped_frames_threshold); |
| |
| scoped_feature_list.InitAndEnableFeatureWithParameters( |
| media::kMediaCapabilitiesWithParameters, trial_params); |
| |
| base::FieldTrialParams actual_trial_params; |
| EXPECT_TRUE(base::GetFieldTrialParamsByFeature( |
| media::kMediaCapabilitiesWithParameters, &actual_trial_params)); |
| EXPECT_EQ(trial_params, actual_trial_params); |
| |
| // Both thresholds should be overridden. |
| EXPECT_EQ(new_CLEAR_smooth_dropped_frames_threshold, |
| GetMaxSmoothDroppedFramesPercent(false /* is_eme */)); |
| EXPECT_EQ(new_EME_smooth_dropped_frames_threshold, |
| GetMaxSmoothDroppedFramesPercent(true /* is_eme */)); |
| |
| // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then |
| // delayed until we db_->CompleteInitialize(). testing::InSequence enforces |
| // that EXPECT_CALLs arrive in top-to-bottom order. |
| PerfHistoryTestParams params = GetParam(); |
| testing::InSequence dummy; |
| |
| // Complete initialization in advance of API calls when not asked to defer. |
| if (!params.defer_initialize) |
| PreInitializeDB(/* success */ true); |
| |
| // First add 2 records to the history. The second record has a higher frame |
| // rate and a higher number of dropped frames such that it is "not smooth". |
| const VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0; |
| const gfx::Size kKownSize(100, 200); |
| const int kSmoothFrameRatePrevious = 30; |
| const int kSmoothFrameRateNew = 90; |
| const int kFramesDecoded = 1000; |
| const int kNotPowerEfficientFramesDecoded = 0; |
| |
| // Sets the ratio of dropped frames to qualify as NOT smooth. For CLEAR, use |
| // the previous smooth threshold. For EME, use the new CLEAR threshold to |
| // verify that the EME threshold is lower than CLEAR. |
| const int kSmoothFramesDroppedPrevious = |
| params.key_system.empty() |
| ? kFramesDecoded * previous_smooth_dropped_frames_threshold |
| : kFramesDecoded * new_CLEAR_smooth_dropped_frames_threshold; |
| // Sets the ratio of dropped frames to quality as smooth per the new threshold |
| // depending on whether the key indicates this record is EME. |
| const int kSmoothFramesDroppedNew = |
| params.key_system.empty() |
| ? kFramesDecoded * new_CLEAR_smooth_dropped_frames_threshold |
| : kFramesDecoded * new_EME_smooth_dropped_frames_threshold; |
| |
| // Add the entry. |
| SavePerfRecord( |
| UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRatePrevious, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kSmoothFramesDroppedPrevious, |
| kNotPowerEfficientFramesDecoded), |
| kPlayerId); |
| |
| SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame, |
| MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRateNew, |
| params.key_system, params.use_hw_secure_codecs), |
| MakeTargets(kFramesDecoded, kSmoothFramesDroppedNew, |
| kNotPowerEfficientFramesDecoded), |
| kPlayerId); |
| |
| // Verify perf history returns is_smooth = false for entry that would be |
| // smooth per previous smooth threshold. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsNotPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRatePrevious, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Verify perf history returns is_smooth = true for entry that would be |
| // smooth per new smooth threshold. |
| EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient)); |
| perf_history_->GetPerfInfo( |
| MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRateNew, |
| params.key_system, params.use_hw_secure_codecs), |
| base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB, |
| base::Unretained(this))); |
| |
| // Complete successful deferred DB initialization (see comment at top of test) |
| if (params.defer_initialize) { |
| GetFakeDB()->CompleteInitialize(true); |
| |
| // Allow initialize-deferred API calls to complete. |
| task_environment_.RunUntilIdle(); |
| } |
| } |
| |
| const PerfHistoryTestParams kPerfHistoryTestParams[] = { |
| {true, "", false}, |
| {false, "", false}, |
| {true, "com.widevine.alpha", false}, |
| {true, "com.widevine.alpha", true}, |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P(VaryDBInitTiming, |
| VideoDecodePerfHistoryParamTest, |
| ::testing::ValuesIn(kPerfHistoryTestParams)); |
| |
| } // namespace media |