bucket_utility.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright 2017 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/bucket_utility.h"
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <iterator>
  8. #include "base/check_op.h"
  9. namespace {
  10. // TODO(chcunningham): Find some authoritative list of frame rates.
  11. // Framerates in this list go way beyond typical values to account for changes
  12. // to playback rate.
  13. const int kFrameRateBuckets[] = {5, 10, 20, 25, 30, 40, 50, 60,
  14. 70, 80, 90, 100, 120, 150, 200, 250,
  15. 300, 350, 400, 450, 500, 550, 600, 650,
  16. 700, 750, 800, 850, 900, 950, 1000, 1500};
  17. // A mix of width and height dimensions for common and not-so-common resolutions
  18. // spanning 50p -> 12K.
  19. // TODO(chcunningham): Ponder these a bit more.
  20. const int kSizeBuckets[] = {
  21. 50, 100, 144, 240, 256, 280, 360, 426, 480, 640, 720,
  22. 854, 960, 1080, 1280, 1440, 1920, 2160, 2560, 2880, 3160, 3840,
  23. 4128, 4320, 5120, 6144, 7360, 7680, 8000, 9000, 10000, 11000, 11520};
  24. // Pixel buckets that are used to quantize the resolution to limit the amount of
  25. // information that is stored and exposed through the API. The pixel size
  26. // indices are used for logging, the pixel size buckets can therefore not be
  27. // changed unless the corresponding logging code is updated.
  28. constexpr int kWebrtcPixelsBuckets[] = {1280 * 720, 1920 * 1080, 2560 * 1440,
  29. 3840 * 2160};
  30. // The boundaries between buckets are calculated as the point between the two
  31. // buckets.
  32. constexpr int kWebrtcPixelsBoundaries[] = {
  33. (kWebrtcPixelsBuckets[0] + kWebrtcPixelsBuckets[1]) / 2,
  34. (kWebrtcPixelsBuckets[1] + kWebrtcPixelsBuckets[2]) / 2,
  35. (kWebrtcPixelsBuckets[2] + kWebrtcPixelsBuckets[3]) / 2};
  36. // Static assert to make sure that `kWebrtcPixelsBoundaries[]` is updated if new
  37. // pixel sizes are added to kWebrtcPixelsBuckets[]`.
  38. static_assert(std::size(kWebrtcPixelsBoundaries) + 1 ==
  39. std::size(kWebrtcPixelsBuckets));
  40. } // namespace
  41. namespace media {
  42. gfx::Size GetSizeBucket(const gfx::Size& raw_size) {
  43. // If either dimension is less than 75% of the min size bucket, return an
  44. // empty size. Empty |natural_size_| will signal ShouldBeReporting() to return
  45. // false.
  46. const double kMinSizeBucketPercent = .75;
  47. if (raw_size.width() < kMinSizeBucketPercent * kSizeBuckets[0] ||
  48. raw_size.height() < kMinSizeBucketPercent * kSizeBuckets[0]) {
  49. return gfx::Size();
  50. }
  51. // Round width and height to first bucket >= |raw_size| dimensions. See
  52. // explanation in header file.
  53. const int* width_bound = std::lower_bound(
  54. std::begin(kSizeBuckets), std::end(kSizeBuckets), raw_size.width());
  55. const int* height_bound = std::lower_bound(
  56. std::begin(kSizeBuckets), std::end(kSizeBuckets), raw_size.height());
  57. // If no bucket is larger than the raw dimension, just use the last bucket.
  58. if (width_bound == std::end(kSizeBuckets))
  59. --width_bound;
  60. if (height_bound == std::end(kSizeBuckets))
  61. --height_bound;
  62. return gfx::Size(*width_bound, *height_bound);
  63. }
  64. int GetFpsBucket(double raw_fps) {
  65. int rounded_fps = std::round(raw_fps);
  66. // Find the first bucket that is strictly > than |rounded_fps|.
  67. const int* upper_bound =
  68. std::upper_bound(std::begin(kFrameRateBuckets),
  69. std::end(kFrameRateBuckets), std::round(rounded_fps));
  70. // If no bucket is larger than |rounded_fps|, just used the last bucket;
  71. if (upper_bound == std::end(kFrameRateBuckets))
  72. return *(upper_bound - 1);
  73. // Return early if its the first bucket.
  74. if (upper_bound == std::begin(kFrameRateBuckets))
  75. return *upper_bound;
  76. int higher_bucket = *upper_bound;
  77. int previous_bucket = *(upper_bound - 1);
  78. if (std::abs(previous_bucket - rounded_fps) <
  79. std::abs(higher_bucket - rounded_fps)) {
  80. return previous_bucket;
  81. }
  82. return higher_bucket;
  83. }
  84. int GetWebrtcPixelsBucket(int pixels) {
  85. return kWebrtcPixelsBuckets[GetWebrtcPixelsBucketIndex(pixels)];
  86. }
  87. int GetWebrtcPixelsBucketIndex(int pixels) {
  88. const int* pixels_bucket_it =
  89. std::lower_bound(std::begin(kWebrtcPixelsBoundaries),
  90. std::end(kWebrtcPixelsBoundaries), pixels);
  91. // The output from std::lower_bound is in the range [begin, end], hence the
  92. // subtraction below is well defined.
  93. int pixels_bucket_index =
  94. std::distance(std::begin(kWebrtcPixelsBoundaries), pixels_bucket_it);
  95. DCHECK_GE(pixels_bucket_index, 0);
  96. DCHECK_LT(pixels_bucket_index,
  97. static_cast<int>(std::size(kWebrtcPixelsBuckets)));
  98. return pixels_bucket_index;
  99. }
  100. } // namespace media