1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
media / capabilities / webrtc_video_stats_db.h [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_CAPABILITIES_WEBRTC_VIDEO_STATS_DB_H_
#define MEDIA_CAPABILITIES_WEBRTC_VIDEO_STATS_DB_H_
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/check.h"
#include "base/containers/flat_map.h"
#include "base/functional/callback_forward.h"
#include "base/time/time.h"
#include "media/base/media_export.h"
#include "media/base/video_codecs.h"
#include "ui/gfx/geometry/size.h"
namespace media {
// This defines the interface to be used by various media capabilities services
// to store/retrieve video encoding and decoding performance statistics.
class MEDIA_EXPORT WebrtcVideoStatsDB {
public:
// Simple description of video encode/decode complexity, serving as a key to
// look up associated VideoStatsEntries in the database.
struct MEDIA_EXPORT VideoDescKey {
static VideoDescKey MakeBucketedKey(bool is_decode_stats,
VideoCodecProfile codec_profile,
bool hardware_accelerated,
int pixels);
// Returns a concise string representation of the key for storing in DB.
std::string Serialize() const;
// Returns a concise string representation of the key without pixels for
// querying the DB.
std::string SerializeWithoutPixels() const;
// For debug logging. NOT interchangeable with Serialize().
std::string ToLogStringForDebug() const;
static std::optional<int> ParsePixelsFromKey(std::string key);
// Note: operator == and != are defined outside this class.
const bool is_decode_stats;
const VideoCodecProfile codec_profile;
const bool hardware_accelerated;
const int pixels;
private:
// All key's should be "bucketed" using MakeBucketedKey(...).
VideoDescKey(bool is_decode_stats,
VideoCodecProfile codec_profile,
bool hardware_accelerated,
int pixels);
};
struct MEDIA_EXPORT VideoStats {
VideoStats(uint32_t frames_processed,
uint32_t key_frames_processed,
float p99_processing_time_ms);
VideoStats(double timestamp,
uint32_t frames_processed,
uint32_t key_frames_processed,
float p99_processing_time_ms);
VideoStats(const VideoStats& entry);
VideoStats& operator=(const VideoStats& entry);
// For debug logging.
std::string ToLogString() const;
// Note: operator == and != are defined outside this class.
double timestamp;
uint32_t frames_processed;
uint32_t key_frames_processed;
float p99_processing_time_ms;
};
// VideoStatsEntry saved to identify the capabilities related to a given
// |VideoDescKey|.
using VideoStatsEntry = std::vector<VideoStats>;
// VideoStatsCollection is used to return a collection of entries
// corresponding to a certain key except for the number of pixels used. The
// number of pixels is instead used as a key in the map for each
// VideoStatsEntry.
using VideoStatsCollection = base::flat_map<int, VideoStatsEntry>;
virtual ~WebrtcVideoStatsDB() = default;
// The maximum number of pixels that a stats key can have without being
// considered out of range. This is used in sanity checks and is higher than
// the maximum pixels value that can be saved to the database. For example, a
// user may query the API for 8K resolution even though no data will be stored
// for anything higher than 4K resolution.
static constexpr int kPixelsAbsoluteMaxValue = 10 * 3840 * 2160;
// The minimum number of pixels that a stats key can have to be considered to
// be saved to the database. Set to 80% of the minimum pixels bucket.
static constexpr int kPixelsMinValueToSave = 0.8 * 1280 * 720;
// The maximum number of pixels that a stats key can have to be considered to
// be saved to the database. Set to 120% of the largest pixels bucket.
static constexpr int kPixelsMaxValueToSave = 1.2 * 3840 * 2160;
// The minimum number of frames processed that a stats entry is based on. The
// 99th percentile is not useful for anything less than 100 samples.
static constexpr uint32_t kFramesProcessedMinValue = 100;
// The maximum number of frames processed that a stats entry is based on.
// Expected max number is around 30000.
static constexpr uint32_t kFramesProcessedMaxValue = 60000;
// Minimum valid 99th percentile of the processing time, which is either the
// time needed for encoding or decoding.
static constexpr float kP99ProcessingTimeMinValueMs = 0.0;
// Maximum valid 99th percentile of the processing time, which is either the
// time needed for encoding or decoding.
static constexpr float kP99ProcessingTimeMaxValueMs = 10000.0;
// Number of stats entries that are stored per configuration. The oldest
// stats entry will be discarded when new stats are added if the list is
// already full.
static int GetMaxEntriesPerConfig();
// Number of days after which a stats entry will be discarded. This
// avoids users getting stuck with a bad capability prediction that may have
// been due to one-off circumstances.
static base::TimeDelta GetMaxTimeToKeepStats();
// Run asynchronous initialization of database. Initialization must complete
// before calling other APIs. |init_cb| must not be
// a null callback.
using InitializeCB = base::OnceCallback<void(bool)>;
virtual void Initialize(InitializeCB init_cb) = 0;
// Appends `video_stats` to existing entry associated with `key`. Will create
// a new entry if none exists. The operation is asynchronous. The caller
// should be aware of potential race conditions when calling this method for
// the same `key` very close to other calls. `append_done_cb` will be run with
// a bool to indicate whether the save succeeded.
using AppendVideoStatsCB = base::OnceCallback<void(bool)>;
virtual void AppendVideoStats(const VideoDescKey& key,
const VideoStats& video_stats,
AppendVideoStatsCB append_done_cb) = 0;
// Returns the stats associated with `key`. The `get_stats_cb` will receive
// the stats in addition to a boolean signaling if the call was successful.
// VideoStatsEntry can be nullopt if there was no data associated with `key`.
using GetVideoStatsCB =
base::OnceCallback<void(bool, std::optional<VideoStatsEntry>)>;
virtual void GetVideoStats(const VideoDescKey& key,
GetVideoStatsCB get_stats_cb) = 0;
// Returns a collection of stats associated with `key` disregarding pixels.
// The `get_stats_cb` will receive the stats in addition to a boolean
// signaling if the call was successful. VideoStatsEntry can be nullopt if
// there was no data associated with `key`.
using GetVideoStatsCollectionCB =
base::OnceCallback<void(bool, std::optional<VideoStatsCollection>)>;
virtual void GetVideoStatsCollection(
const VideoDescKey& key,
GetVideoStatsCollectionCB get_stats_cb) = 0;
// Clear all statistics from the DB.
virtual void ClearStats(base::OnceClosure clear_done_cb) = 0;
};
MEDIA_EXPORT bool operator==(const WebrtcVideoStatsDB::VideoDescKey& x,
const WebrtcVideoStatsDB::VideoDescKey& y);
MEDIA_EXPORT bool operator!=(const WebrtcVideoStatsDB::VideoDescKey& x,
const WebrtcVideoStatsDB::VideoDescKey& y);
MEDIA_EXPORT bool operator==(const WebrtcVideoStatsDB::VideoStats& x,
const WebrtcVideoStatsDB::VideoStats& y);
MEDIA_EXPORT bool operator!=(const WebrtcVideoStatsDB::VideoStats& x,
const WebrtcVideoStatsDB::VideoStats& y);
} // namespace media
#endif // MEDIA_CAPABILITIES_WEBRTC_VIDEO_STATS_DB_H_