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.
5 #ifndef MEDIA_MOJO_SERVICES_WEBRTC_VIDEO_PERF_HISTORY_H_
6 #define MEDIA_MOJO_SERVICES_WEBRTC_VIDEO_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/webrtc_video_stats_db.h"
18 #include "media/capabilities/webrtc_video_stats_db_provider.h"
19 #include "media/mojo/mojom/webrtc_video_perf.mojom.h"
20 #include "media/mojo/services/media_mojo_export.h"
21 #include "mojo/public/cpp/bindings/pending_receiver.h"
22 #include "mojo/public/cpp/bindings/receiver_set.h"
26 // This class saves and retrieves WebRTC video performance statistics on behalf
27 // of the MediaCapabilities API.
29 // The database is lazily initialized/loaded upon the first API call requiring
30 // DB access. DB implementations must take care to perform work on a separate
33 // Retrieving stats is triggered by calls to the GetPerfInfo() Mojo interface.
34 // The raw values are reduced to a boolean (is_smooth) which is sent along the
37 // Saving stats is performed by SavePerfRecord(), where a record is defined as a
38 // continuous playback/encoding of a stream with fixed characteristics (codec
39 // profile, number of pixels, hardware accelerated).
42 // This class is not thread safe. All API calls should be made on the same
44 class MEDIA_MOJO_EXPORT WebrtcVideoPerfHistory
45 : public media::mojom::WebrtcVideoPerfHistory,
46 public WebrtcVideoStatsDBProvider,
47 public base::SupportsUserData::Data {
49 explicit WebrtcVideoPerfHistory(std::unique_ptr<WebrtcVideoStatsDB> db);
50 ~WebrtcVideoPerfHistory() override;
51 WebrtcVideoPerfHistory(const WebrtcVideoPerfHistory&) = delete;
52 WebrtcVideoPerfHistory& operator=(const WebrtcVideoPerfHistory&) = delete;
54 // Bind the mojo receiver to this instance. Single instance will be used to
55 // serve multiple receivers.
57 mojo::PendingReceiver<media::mojom::WebrtcVideoPerfHistory> receiver);
59 // mojom::WebrtcVideoPerfHistory implementation.
60 void GetPerfInfo(media::mojom::WebrtcPredictionFeaturesPtr features,
61 int frames_per_second,
62 GetPerfInfoCallback got_info_cb) override;
64 // Provides a callback for saving a stats record for the described stream.
65 // This callback will silently fail if called after `this` is destroyed.
66 // Saving is generally fire-and-forget, but `save_done_cb` may be provided
67 // for tests to know the save is complete.
68 using SaveCallback = base::RepeatingCallback<void(
69 media::mojom::WebrtcPredictionFeatures features,
70 media::mojom::WebrtcVideoStats video_stats,
71 base::OnceClosure save_done_cb)>;
72 SaveCallback GetSaveCallback();
74 // Clear all history from the underlying database. Run `clear_done_cb` when
76 void ClearHistory(base::OnceClosure clear_done_cb);
78 // WebrtcVideoStatsDBProvider implementation. `cb` receives a pointer to the
79 // *initialized* WebrtcVideoStatsDB, or null in case of error.
80 void GetWebrtcVideoStatsDB(GetCB cb) override;
83 friend class WebrtcVideoPerfHistoryTest;
85 // Threshold that is used when determining if the processing can be handled
86 // smoothly. A threshold of 1.0 means that the 99th percentile is allowed to
87 // the same a 1 s / `frames_per_second` and still considered smooth.
88 static float GetSmoothnessThreshold(bool is_decode);
90 // Threshold that determines how several entries are combined into a
91 // smoothness decision. A threshold of 0.5 means that 50% of the individual
92 // sessions should be assessed as smooth for the combined outcome to be
94 static float GetSmoothDecisionRatioThreshold();
96 // Returns the estimated smoothness response for the specified `stats_entry`
97 // at the rate given by `frames_per_second`.
98 static bool PredictSmooth(
100 const WebrtcVideoStatsDB::VideoStatsEntry& stats_entry,
101 int frames_per_second);
103 // Simulates what the smoothness response will be after the update to the DB
104 // at the rate given by `frames_per_second`.
105 static bool PredictSmoothAfterUpdate(
107 const WebrtcVideoStatsDB::VideoStats& new_stats,
108 const WebrtcVideoStatsDB::VideoStatsEntry& past_stats_entry,
109 int frames_per_second);
111 // Reports UMA metrics comparing the predicted smoothness before and after a
113 static void ReportUmaMetricsOnSave(
114 bool is_decode_stats,
115 const WebrtcVideoStatsDB::VideoStats& new_stats,
116 const WebrtcVideoStatsDB::VideoStatsEntry& past_stats_entry);
118 // Track the status of database lazy initialization.
126 // Initialize the database. Will return early if initialization is
130 // Callback from `db_->Initialize()`.
131 void OnDatabaseInit(bool success);
133 // Initiate saving of the provided record. See GetSaveCallback().
134 void SavePerfRecord(media::mojom::WebrtcPredictionFeatures features,
135 media::mojom::WebrtcVideoStats video_stats,
136 base::OnceClosure save_done_cb);
138 // Internal callback for database queries made from GetPerfInfo() (mojo API).
139 // Assesses performance from database stats and passes results to
141 void OnGotStatsCollectionForRequest(
142 const WebrtcVideoStatsDB::VideoDescKey& video_key,
143 int frames_per_second,
144 GetPerfInfoCallback got_info_cb,
145 bool database_success,
146 absl::optional<WebrtcVideoStatsDB::VideoStatsCollection> 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. Then updates the database with the `new_stats`.
151 void OnGotStatsForSave(
152 const WebrtcVideoStatsDB::VideoDescKey& video_key,
153 const WebrtcVideoStatsDB::VideoStats& new_stats,
154 base::OnceClosure save_done_cb,
156 absl::optional<WebrtcVideoStatsDB::VideoStatsEntry> past_stats);
158 // Internal callback for saving to database. Will run `save_done_cb` if
160 void OnSaveDone(base::OnceClosure save_done_cb, bool success);
162 // Internal callback for ClearHistory(). Reinitializes the database and runs
164 void OnClearedHistory(base::OnceClosure clear_done_cb);
166 // Underlying database for managing/coalescing decode stats. Const to enforce
167 // assignment during construction and never cleared. We hand out references to
168 // the db via GetWebrtcVideoStatsDB(), so clearing or reassigning breaks
169 // those dependencies.
170 const std::unique_ptr<WebrtcVideoStatsDB> db_;
172 // Tracks whether we've received OnDatabaseInit() callback. All database
173 // operations should be deferred until initialization is complete.
174 InitStatus db_init_status_ = UNINITIALIZED;
176 // Vector of bound public API calls, to be run once DB initialization
178 std::vector<base::OnceClosure> init_deferred_api_calls_;
180 // Maps receivers from several render-processes to this single browser-process
182 mojo::ReceiverSet<media::mojom::WebrtcVideoPerfHistory> receivers_;
184 // Ensures all access to class members come on the same sequence.
185 SEQUENCE_CHECKER(sequence_checker_);
187 base::WeakPtrFactory<WebrtcVideoPerfHistory> weak_ptr_factory_{this};
192 #endif // MEDIA_MOJO_SERVICES_WEBRTC_VIDEO_PERF_HISTORY_H_