gpu_video_encode_accelerator_helpers.cc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright 2018 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/gpu/gpu_video_encode_accelerator_helpers.h"
  5. #include <algorithm>
  6. #include "base/check_op.h"
  7. #include "base/notreached.h"
  8. #include "base/numerics/safe_conversions.h"
  9. #include "media/base/bitrate.h"
  10. namespace media {
  11. namespace {
  12. // The maximum number of supported spatial layers and temporal layers. These
  13. // come from the maximum number of layers currently supported by
  14. // VideoEncodeAccelerator implementation.
  15. constexpr size_t kMaxSpatialLayers = 3;
  16. constexpr size_t kMaxTemporalLayers = 3;
  17. // The maximum size for output buffer, which is chosen empirically for
  18. // 1080p video.
  19. constexpr size_t kMaxBitstreamBufferSizeInBytes = 2 * 1024 * 1024; // 2MB
  20. // The frame size for 1080p (FHD) video in pixels.
  21. constexpr int k1080PSizeInPixels = 1920 * 1080;
  22. // The frame size for 1440p (QHD) video in pixels.
  23. constexpr int k1440PSizeInPixels = 2560 * 1440;
  24. // The mapping from resolution, bitrate, framerate to the bitstream buffer size.
  25. struct BitstreamBufferSizeInfo {
  26. int coded_size_area;
  27. uint32_t bitrate_in_bps;
  28. uint32_t framerate;
  29. uint32_t buffer_size_in_bytes;
  30. };
  31. // The bitstream buffer size for each resolution. The table must be sorted in
  32. // increasing order by the resolution. The value is decided by measuring the
  33. // biggest buffer size, and then double the size as margin. (crbug.com/889739)
  34. constexpr BitstreamBufferSizeInfo kBitstreamBufferSizeTable[] = {
  35. {320 * 180, 100000, 30, 15000},
  36. {640 * 360, 500000, 30, 52000},
  37. {1280 * 720, 1200000, 30, 110000},
  38. {1920 * 1080, 4000000, 30, 380000},
  39. {3840 * 2160, 20000000, 30, 970000},
  40. };
  41. // Use quadruple size of kMaxBitstreamBufferSizeInBytes when the input frame
  42. // size is larger than 1440p, double if larger than 1080p. This is chosen
  43. // empirically for some 4k encoding use cases and Android CTS VideoEncoderTest
  44. // (crbug.com/927284).
  45. size_t GetMaxEncodeBitstreamBufferSize(const gfx::Size& size) {
  46. if (size.GetArea() > k1440PSizeInPixels)
  47. return kMaxBitstreamBufferSizeInBytes * 4;
  48. if (size.GetArea() > k1080PSizeInPixels)
  49. return kMaxBitstreamBufferSizeInBytes * 2;
  50. return kMaxBitstreamBufferSizeInBytes;
  51. }
  52. // This function sets the peak equal to the target. The peak can then be
  53. // updated by callers.
  54. VideoBitrateAllocation AllocateBitrateForDefaultEncodingWithBitrates(
  55. const std::vector<uint32_t>& sl_bitrates,
  56. const size_t num_temporal_layers,
  57. const bool uses_vbr) {
  58. CHECK(!sl_bitrates.empty());
  59. CHECK_LE(sl_bitrates.size(), kMaxSpatialLayers);
  60. // The same bitrate factors as the software encoder.
  61. // https://source.chromium.org/chromium/chromium/src/+/main:media/video/vpx_video_encoder.cc;l=131;drc=d383d0b3e4f76789a6de2a221c61d3531f4c59da
  62. constexpr double kTemporalLayersBitrateScaleFactors[][kMaxTemporalLayers] = {
  63. {1.00, 0.00, 0.00}, // For one temporal layer.
  64. {0.60, 0.40, 0.00}, // For two temporal layers.
  65. {0.50, 0.20, 0.30}, // For three temporal layers.
  66. };
  67. CHECK_GT(num_temporal_layers, 0u);
  68. CHECK_LE(num_temporal_layers, std::size(kTemporalLayersBitrateScaleFactors));
  69. DCHECK_EQ(std::size(kTemporalLayersBitrateScaleFactors), kMaxTemporalLayers);
  70. VideoBitrateAllocation bitrate_allocation;
  71. bitrate_allocation = VideoBitrateAllocation(
  72. uses_vbr ? Bitrate::Mode::kVariable : Bitrate::Mode::kConstant);
  73. for (size_t spatial_id = 0; spatial_id < sl_bitrates.size(); ++spatial_id) {
  74. const uint32_t bitrate_bps = sl_bitrates[spatial_id];
  75. for (size_t temporal_id = 0; temporal_id < num_temporal_layers;
  76. ++temporal_id) {
  77. const double factor =
  78. kTemporalLayersBitrateScaleFactors[num_temporal_layers - 1]
  79. [temporal_id];
  80. bitrate_allocation.SetBitrate(
  81. spatial_id, temporal_id,
  82. base::saturated_cast<uint32_t>(bitrate_bps * factor));
  83. }
  84. }
  85. return bitrate_allocation;
  86. }
  87. } // namespace
  88. size_t GetEncodeBitstreamBufferSize(const gfx::Size& size,
  89. uint32_t bitrate,
  90. uint32_t framerate) {
  91. DCHECK_NE(framerate, 0u);
  92. for (auto& data : kBitstreamBufferSizeTable) {
  93. if (size.GetArea() <= data.coded_size_area) {
  94. // The buffer size is proportional to (bitrate / framerate), but linear
  95. // interpolation for smaller ratio is not enough. Therefore we only use
  96. // linear extrapolation for larger ratio.
  97. double ratio = std::max(
  98. 1.0f * (bitrate / framerate) / (data.bitrate_in_bps / data.framerate),
  99. 1.0f);
  100. return std::min(static_cast<size_t>(data.buffer_size_in_bytes * ratio),
  101. GetMaxEncodeBitstreamBufferSize(size));
  102. }
  103. }
  104. return GetMaxEncodeBitstreamBufferSize(size);
  105. }
  106. // Get the maximum output bitstream buffer size. Since we don't change the
  107. // buffer size when we update bitrate and framerate, we have to calculate the
  108. // buffer size for the maximum bitrate.
  109. // However, the maximum bitrate for intel chipset is 40Mbps. The buffer size
  110. // calculated with this bitrate is always larger than 2MB. Therefore we just
  111. // return the value.
  112. // TODO(crbug.com/889739): Deprecate this function after we can update the
  113. // buffer size while requesting new bitrate and framerate.
  114. size_t GetEncodeBitstreamBufferSize(const gfx::Size& size) {
  115. return GetMaxEncodeBitstreamBufferSize(size);
  116. }
  117. std::vector<uint8_t> GetFpsAllocation(size_t num_temporal_layers) {
  118. DCHECK_LT(num_temporal_layers, 4u);
  119. constexpr uint8_t kFullAllocation = 255;
  120. // The frame rate fraction is given as an 8 bit unsigned integer where 0 = 0%
  121. // and 255 = 100%. Each layer's allocated fps refers to the previous one, so
  122. // e.g. your camera is opened at 30fps, and you want to have decode targets at
  123. // 15fps and 7.5fps as well:
  124. // TL0 then gets an allocation of 7.5/30 = 1/4. TL1 adds another 7.5fps to end
  125. // up at (7.5 + 7.5)/30 = 15/30 = 1/2 of the total allocation. TL2 adds the
  126. // final 15fps to end up at (15 + 15)/30, which is the full allocation.
  127. // Therefor, fps_allocation values are as follows,
  128. // fps_allocation[0][0] = kFullAllocation / 4;
  129. // fps_allocation[0][1] = kFullAllocation / 2;
  130. // fps_allocation[0][2] = kFullAllocation;
  131. // For more information, see webrtc::VideoEncoderInfo::fps_allocation.
  132. switch (num_temporal_layers) {
  133. case 1:
  134. // In this case, the number of spatial layers must great than 1.
  135. return {kFullAllocation};
  136. case 2:
  137. return {kFullAllocation / 2, kFullAllocation};
  138. case 3:
  139. return {kFullAllocation / 4, kFullAllocation / 2, kFullAllocation};
  140. default:
  141. NOTREACHED() << "Unsupported temporal layers";
  142. return {};
  143. }
  144. }
  145. VideoBitrateAllocation AllocateBitrateForDefaultEncoding(
  146. const VideoEncodeAccelerator::Config& config) {
  147. VideoBitrateAllocation allocation;
  148. const bool use_vbr = config.bitrate.mode() == Bitrate::Mode::kVariable;
  149. if (config.spatial_layers.empty()) {
  150. allocation = AllocateBitrateForDefaultEncodingWithBitrates(
  151. {config.bitrate.target_bps()},
  152. /*num_temporal_layers=*/1u, use_vbr);
  153. if (use_vbr) {
  154. allocation.SetPeakBps(config.bitrate.peak_bps());
  155. }
  156. return allocation;
  157. }
  158. const size_t num_temporal_layers =
  159. config.spatial_layers[0].num_of_temporal_layers;
  160. std::vector<uint32_t> bitrates;
  161. bitrates.reserve(config.spatial_layers.size());
  162. for (const auto& spatial_layer : config.spatial_layers) {
  163. DCHECK_EQ(spatial_layer.num_of_temporal_layers, num_temporal_layers);
  164. bitrates.push_back(spatial_layer.bitrate_bps);
  165. }
  166. allocation = AllocateBitrateForDefaultEncodingWithBitrates(
  167. bitrates, num_temporal_layers, use_vbr);
  168. if (use_vbr) {
  169. allocation.SetPeakBps(config.bitrate.peak_bps());
  170. }
  171. return allocation;
  172. }
  173. VideoBitrateAllocation AllocateDefaultBitrateForTesting(
  174. const size_t num_spatial_layers,
  175. const size_t num_temporal_layers,
  176. const Bitrate& bitrate) {
  177. // Higher spatial layers (those to the right) get more bitrate.
  178. constexpr double kSpatialLayersBitrateScaleFactors[][kMaxSpatialLayers] = {
  179. {1.00, 0.00, 0.00}, // For one spatial layer.
  180. {0.30, 0.70, 0.00}, // For two spatial layers.
  181. {0.07, 0.23, 0.70}, // For three spatial layers.
  182. };
  183. CHECK_GT(num_spatial_layers, 0u);
  184. CHECK_LE(num_spatial_layers, std::size(kSpatialLayersBitrateScaleFactors));
  185. DCHECK_EQ(std::size(kSpatialLayersBitrateScaleFactors), kMaxSpatialLayers);
  186. std::vector<uint32_t> bitrates(num_spatial_layers);
  187. for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
  188. const double bitrate_factor =
  189. kSpatialLayersBitrateScaleFactors[num_spatial_layers - 1][sid];
  190. bitrates[sid] = bitrate.target_bps() * bitrate_factor;
  191. }
  192. const bool use_vbr = bitrate.mode() == Bitrate::Mode::kVariable;
  193. auto allocation = AllocateBitrateForDefaultEncodingWithBitrates(
  194. bitrates, num_temporal_layers, use_vbr);
  195. if (use_vbr)
  196. allocation.SetPeakBps(bitrate.peak_bps());
  197. return allocation;
  198. }
  199. } // namespace media