webrtc_video_stats_db.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/capabilities/webrtc_video_stats_db.h"
  5. #include "base/check_op.h"
  6. #include "base/format_macros.h"
  7. #include "base/metrics/field_trial_params.h"
  8. #include "base/strings/string_number_conversions.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "media/base/media_switches.h"
  11. #include "media/capabilities/bucket_utility.h"
  12. namespace media {
  13. namespace {
  14. // Default value for maximum number of days until a stats entry is considered
  15. // expired.
  16. constexpr int kMaxDaysToKeepStatsDefault = 30;
  17. // Default value for maximum number of stats entries per config.
  18. constexpr int kMaxEntriesPerConfigDefault = 10;
  19. // Field trial parameter names.
  20. constexpr char kMaxDaysToKeepStatsParamName[] = "db_days_to_keep_stats";
  21. constexpr char kMaxEntriesPerConfigParamName[] = "db_max_entries_per_cpnfig";
  22. // Group similar codec profiles to the same entry. Returns
  23. // VIDEO_CODEC_PROFILE_UNKNOWN if `codec_profile` is outside the valid range or
  24. // not tracked. The reason to not track all codec profiles is to limit the
  25. // fingerprinting surface.
  26. VideoCodecProfile GetWebrtcCodecProfileBucket(VideoCodecProfile codec_profile) {
  27. if (codec_profile >= H264PROFILE_MIN && codec_profile <= H264PROFILE_MAX) {
  28. return H264PROFILE_MIN;
  29. }
  30. if (codec_profile >= VP8PROFILE_MIN && codec_profile <= VP8PROFILE_MAX) {
  31. return VP8PROFILE_MIN;
  32. }
  33. if (codec_profile == VP9PROFILE_PROFILE0) {
  34. return VP9PROFILE_PROFILE0;
  35. }
  36. if (codec_profile == VP9PROFILE_PROFILE2) {
  37. return VP9PROFILE_PROFILE2;
  38. }
  39. if (codec_profile >= AV1PROFILE_MIN && codec_profile <= AV1PROFILE_MAX) {
  40. return AV1PROFILE_MIN;
  41. }
  42. return VIDEO_CODEC_PROFILE_UNKNOWN;
  43. }
  44. } // namespace
  45. // static
  46. WebrtcVideoStatsDB::VideoDescKey
  47. WebrtcVideoStatsDB::VideoDescKey::MakeBucketedKey(
  48. bool is_decode_stats,
  49. VideoCodecProfile codec_profile,
  50. bool hardware_accelerated,
  51. int pixels) {
  52. // Bucket pixel size to prevent an explosion of one-off values in the
  53. // database and add basic guards against fingerprinting.
  54. return VideoDescKey(is_decode_stats,
  55. GetWebrtcCodecProfileBucket(codec_profile),
  56. hardware_accelerated, GetWebrtcPixelsBucket(pixels));
  57. }
  58. WebrtcVideoStatsDB::VideoDescKey::VideoDescKey(bool is_decode_stats,
  59. VideoCodecProfile codec_profile,
  60. bool hardware_accelerated,
  61. int pixels)
  62. : is_decode_stats(is_decode_stats),
  63. codec_profile(codec_profile),
  64. hardware_accelerated(hardware_accelerated),
  65. pixels(pixels) {}
  66. std::string WebrtcVideoStatsDB::VideoDescKey::Serialize() const {
  67. std::string video_part = base::StringPrintf("%d|%d|%d|%d", is_decode_stats,
  68. static_cast<int>(codec_profile),
  69. hardware_accelerated, pixels);
  70. return video_part;
  71. }
  72. std::string WebrtcVideoStatsDB::VideoDescKey::SerializeWithoutPixels() const {
  73. std::string video_part =
  74. base::StringPrintf("%d|%d|%d|", is_decode_stats,
  75. static_cast<int>(codec_profile), hardware_accelerated);
  76. return video_part;
  77. }
  78. std::string WebrtcVideoStatsDB::VideoDescKey::ToLogStringForDebug() const {
  79. return "Key {" + Serialize() + "}";
  80. }
  81. // static
  82. absl::optional<int> WebrtcVideoStatsDB::VideoDescKey::ParsePixelsFromKey(
  83. std::string key) {
  84. constexpr size_t kMinimumIndexOfLastSeparator = 5;
  85. size_t last_separator_index = key.rfind("|");
  86. if (last_separator_index != std::string::npos &&
  87. last_separator_index >= kMinimumIndexOfLastSeparator &&
  88. (last_separator_index + 1) < key.size()) {
  89. int parsed_pixels;
  90. if (base::StringToInt(&key.c_str()[last_separator_index + 1],
  91. &parsed_pixels))
  92. return parsed_pixels;
  93. }
  94. return absl::nullopt;
  95. }
  96. WebrtcVideoStatsDB::VideoStats::VideoStats(double timestamp,
  97. uint32_t frames_processed,
  98. uint32_t key_frames_processed,
  99. float p99_processing_time_ms)
  100. : timestamp(timestamp),
  101. frames_processed(frames_processed),
  102. key_frames_processed(key_frames_processed),
  103. p99_processing_time_ms(p99_processing_time_ms) {
  104. DCHECK_GE(frames_processed, 0u);
  105. DCHECK_GE(key_frames_processed, 0u);
  106. DCHECK_GE(p99_processing_time_ms, 0);
  107. }
  108. WebrtcVideoStatsDB::VideoStats::VideoStats(uint32_t frames_processed,
  109. uint32_t key_frames_processed,
  110. float p99_processing_time_ms)
  111. : VideoStats(/*timestamp=*/0.0,
  112. frames_processed,
  113. key_frames_processed,
  114. p99_processing_time_ms) {}
  115. WebrtcVideoStatsDB::VideoStats::VideoStats(const VideoStats& entry) = default;
  116. WebrtcVideoStatsDB::VideoStats& WebrtcVideoStatsDB::VideoStats::operator=(
  117. const VideoStats& entry) = default;
  118. std::string WebrtcVideoStatsDB::VideoStats::ToLogString() const {
  119. return base::StringPrintf(
  120. "VideoStats {Frames processed:%u, key frames processed:%u, p99 "
  121. "processing time:%.2f}",
  122. frames_processed, key_frames_processed, p99_processing_time_ms);
  123. }
  124. bool operator==(const WebrtcVideoStatsDB::VideoDescKey& x,
  125. const WebrtcVideoStatsDB::VideoDescKey& y) {
  126. return x.is_decode_stats == y.is_decode_stats &&
  127. x.codec_profile == y.codec_profile &&
  128. x.hardware_accelerated == y.hardware_accelerated &&
  129. x.pixels == y.pixels;
  130. }
  131. bool operator!=(const WebrtcVideoStatsDB::VideoDescKey& x,
  132. const WebrtcVideoStatsDB::VideoDescKey& y) {
  133. return !(x == y);
  134. }
  135. bool operator==(const WebrtcVideoStatsDB::VideoStats& x,
  136. const WebrtcVideoStatsDB::VideoStats& y) {
  137. return x.timestamp == y.timestamp &&
  138. x.frames_processed == y.frames_processed &&
  139. x.key_frames_processed == y.key_frames_processed &&
  140. x.p99_processing_time_ms == y.p99_processing_time_ms;
  141. }
  142. bool operator!=(const WebrtcVideoStatsDB::VideoStats& x,
  143. const WebrtcVideoStatsDB::VideoStats& y) {
  144. return !(x == y);
  145. }
  146. // static
  147. base::TimeDelta WebrtcVideoStatsDB::GetMaxTimeToKeepStats() {
  148. return base::Days(base::GetFieldTrialParamByFeatureAsInt(
  149. kWebrtcMediaCapabilitiesParameters, kMaxDaysToKeepStatsParamName,
  150. kMaxDaysToKeepStatsDefault));
  151. }
  152. // static
  153. int WebrtcVideoStatsDB::GetMaxEntriesPerConfig() {
  154. return base::GetFieldTrialParamByFeatureAsInt(
  155. kWebrtcMediaCapabilitiesParameters, kMaxEntriesPerConfigParamName,
  156. kMaxEntriesPerConfigDefault);
  157. }
  158. } // namespace media