1 // Copyright 2017 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.
5 #ifndef MEDIA_MOJO_SERVICES_VIDEO_DECODE_PERF_HISTORY_H_
6 #define MEDIA_MOJO_SERVICES_VIDEO_DECODE_PERF_HISTORY_H_
12 #include "base/functional/callback.h"
13 #include "base/metrics/field_trial_params.h"
14 #include "base/sequence_checker.h"
15 #include "base/supports_user_data.h"
16 #include "media/base/video_codecs.h"
17 #include "media/capabilities/video_decode_stats_db.h"
18 #include "media/capabilities/video_decode_stats_db_provider.h"
19 #include "media/learning/impl/feature_provider.h"
20 #include "media/mojo/mojom/video_decode_perf_history.mojom.h"
21 #include "media/mojo/services/media_mojo_export.h"
22 #include "mojo/public/cpp/bindings/pending_receiver.h"
23 #include "mojo/public/cpp/bindings/receiver_set.h"
24 #include "services/metrics/public/cpp/ukm_source_id.h"
25 #include "ui/gfx/geometry/size.h"
31 // This class saves and retrieves video decode performance statistics on behalf
32 // of the MediaCapabilities API. It also helps to grade the accuracy of the API
33 // by comparing its history-based assessment of smoothness/power-efficiency to
34 // the observed performance as new stats are saved.
36 // The database is lazily initialized/loaded upon the first API call requiring
37 // DB access. DB implementations must take care to perform work on a separate
40 // Retrieving stats is triggered by calls to the GetPerfInfo() Mojo interface.
41 // The raw values are reduced to booleans (is_smooth, is_power_efficient) which
42 // are sent along the Mojo callback.
44 // Saving stats is performed by SavePerfRecord(), where a record is defined as a
45 // continuous playback of a stream with fixed decode characteristics (profile,
46 // natural size, frame rate).
49 // This class is not thread safe. All API calls should be made on the same
51 class MEDIA_MOJO_EXPORT VideoDecodePerfHistory
52 : public mojom::VideoDecodePerfHistory,
53 public VideoDecodeStatsDBProvider,
54 public base::SupportsUserData::Data {
56 static const char kMaxSmoothDroppedFramesPercentParamName[];
57 static const char kEmeMaxSmoothDroppedFramesPercentParamName[];
59 explicit VideoDecodePerfHistory(
60 std::unique_ptr<VideoDecodeStatsDB> db,
61 learning::FeatureProviderFactoryCB feature_factory_cb =
62 learning::FeatureProviderFactoryCB());
64 VideoDecodePerfHistory(const VideoDecodePerfHistory&) = delete;
65 VideoDecodePerfHistory& operator=(const VideoDecodePerfHistory&) = delete;
67 ~VideoDecodePerfHistory() override;
69 // Bind the mojo receiver to this instance. Single instance will be used to
70 // serve multiple receivers.
72 mojo::PendingReceiver<mojom::VideoDecodePerfHistory> receiver);
74 // mojom::VideoDecodePerfHistory implementation:
75 void GetPerfInfo(mojom::PredictionFeaturesPtr features,
76 GetPerfInfoCallback got_info_cb) override;
78 // Provides a callback for saving a stats record for the described stream.
79 // This callback will silently fail if called after |this| is destroyed.
80 // Saving is generally fire-and-forget, but |save_done_cb| may be provided
81 // for tests to know the save is complete.
83 base::RepeatingCallback<void(ukm::SourceId source_id,
84 learning::FeatureValue origin,
86 mojom::PredictionFeatures features,
87 mojom::PredictionTargets targets,
89 base::OnceClosure save_done_cb)>;
90 SaveCallback GetSaveCallback();
92 // Clear all history from the underlying database. Run |clear_done_cb| when
94 void ClearHistory(base::OnceClosure clear_done_cb);
96 // From VideoDecodeStatsDBProvider. |cb| receives a pointer to the
97 // *initialized* VideoDecodeStatsDB, or null in case of error.
98 void GetVideoDecodeStatsDB(GetCB cb) override;
101 friend class VideoDecodePerfHistoryTest;
103 // Decode capabilities will be described as "smooth" whenever the percentage
104 // of dropped frames is less-than-or-equal-to this value.
105 static double GetMaxSmoothDroppedFramesPercent(bool is_eme);
107 // Returns current feature params.
108 static base::FieldTrialParams GetFieldTrialParams();
110 // Track the status of database lazy initialization.
118 // Decode capabilities will be described as "power efficient" whenever the
119 // percentage of power efficient decoded frames is higher-than-or-equal-to
121 static constexpr double kMinPowerEfficientDecodedFramePercent = .50;
123 // Initialize the database. Will return early if initialization is
127 // Callback from |db_->Initialize()|.
128 void OnDatabaseInit(bool success);
130 // Initiate saving of the provided record. See GetSaveCallback().
131 void SavePerfRecord(ukm::SourceId source_id,
132 learning::FeatureValue origin,
134 mojom::PredictionFeatures features,
135 mojom::PredictionTargets targets,
137 base::OnceClosure save_done_cb);
139 // Internal callback for database queries made from GetPerfInfo() (mojo API).
140 // Assesses performance from database stats and passes results to
142 void OnGotStatsForRequest(
143 const VideoDecodeStatsDB::VideoDescKey& video_key,
144 GetPerfInfoCallback got_info_cb,
145 bool database_success,
146 std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> stats);
148 // Internal callback for database queries made from SavePerfRecord(). Compares
149 // past performance to this latest record as means of "grading" the accuracy
150 // of the GetPerfInfo() API. Comparison is recorded via UKM. Then saves the
151 // |new_*| performance stats to the database.
152 void OnGotStatsForSave(
153 ukm::SourceId source_id,
156 const VideoDecodeStatsDB::VideoDescKey& video_key,
157 const VideoDecodeStatsDB::DecodeStatsEntry& new_stats,
158 base::OnceClosure save_done_cb,
160 std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> past_stats);
162 // Internal callback for saving to database. Will run |save_done_cb| if
164 void OnSaveDone(base::OnceClosure save_done_cb, bool success);
166 // Report UKM metrics to grade the claims of the API by evaluating how well
167 // |past_stats| predicts |new_stats|.
168 void ReportUkmMetrics(ukm::SourceId source_id,
171 const VideoDecodeStatsDB::VideoDescKey& video_key,
172 const VideoDecodeStatsDB::DecodeStatsEntry& new_stats,
173 VideoDecodeStatsDB::DecodeStatsEntry* past_stats);
175 void AssessStats(const VideoDecodeStatsDB::VideoDescKey& key,
176 const VideoDecodeStatsDB::DecodeStatsEntry* stats,
178 bool* is_power_efficient);
180 // Internal callback for ClearHistory(). Reinitializes the database and runs
182 void OnClearedHistory(base::OnceClosure clear_done_cb);
184 // Underlying database for managing/coalescing decode stats. Const to enforce
185 // assignment during construction and never cleared. We hand out references to
186 // the db via GetVideoDecodeStatsDB(), so clearing or reassigning breaks those
188 const std::unique_ptr<VideoDecodeStatsDB> db_;
190 // Tracks whether we've received OnDatabaseIniti() callback. All database
191 // operations should be deferred until initialization is complete.
192 InitStatus db_init_status_;
194 // Vector of bound public API calls, to be run once DB initialization
196 std::vector<base::OnceClosure> init_deferred_api_calls_;
198 // Maps receivers from several render-processes to this single browser-process
200 mojo::ReceiverSet<mojom::VideoDecodePerfHistory> receivers_;
202 // Optional helper for local learning.
203 std::unique_ptr<LearningHelper> learning_helper_;
205 // Optional callback to create a FeatureProvider for |learning_helper_|.
206 learning::FeatureProviderFactoryCB feature_factory_cb_;
208 // Ensures all access to class members come on the same sequence.
209 SEQUENCE_CHECKER(sequence_checker_);
211 base::WeakPtrFactory<VideoDecodePerfHistory> weak_ptr_factory_{this};
216 #endif // MEDIA_MOJO_SERVICES_VIDEO_DECODE_PERF_HISTORY_H_