blob: e9687cf40448cab008f700f79e27f8cc3cf0a0be [file] [log] [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 <string>
#include <vector>
#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<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, absl::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, absl::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_