// Copyright 2022 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. #ifndef MEDIA_CAPABILITIES_WEBRTC_VIDEO_STATS_DB_H_ #define MEDIA_CAPABILITIES_WEBRTC_VIDEO_STATS_DB_H_ #include #include #include #include "base/callback_forward.h" #include "base/check.h" #include "base/containers/flat_map.h" #include "base/time/time.h" #include "media/base/media_export.h" #include "media/base/video_codecs.h" #include "third_party/abseil-cpp/absl/types/optional.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 absl::optional 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; // 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; 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; 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; 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)>; 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)>; 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_