video_encoder.cc (12348B)
1 /* 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "api/video_codecs/video_encoder.h" 12 13 #include <algorithm> 14 #include <cstdint> 15 #include <cstring> 16 #include <optional> 17 #include <string> 18 #include <tuple> 19 #include <vector> 20 21 #include "absl/container/inlined_vector.h" 22 #include "api/fec_controller_override.h" 23 #include "api/units/data_rate.h" 24 #include "api/video/video_bitrate_allocation.h" 25 #include "api/video/video_codec_constants.h" 26 #include "api/video/video_frame_buffer.h" 27 #include "api/video_codecs/video_codec.h" 28 #include "rtc_base/checks.h" 29 #include "rtc_base/strings/string_builder.h" 30 31 namespace webrtc { 32 33 // TODO(mflodman): Add default complexity for VP9 and VP9. 34 VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() { 35 VideoCodecVP8 vp8_settings; 36 memset(&vp8_settings, 0, sizeof(vp8_settings)); 37 38 vp8_settings.numberOfTemporalLayers = 1; 39 vp8_settings.denoisingOn = true; 40 vp8_settings.automaticResizeOn = false; 41 vp8_settings.keyFrameInterval = 3000; 42 43 return vp8_settings; 44 } 45 46 VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() { 47 VideoCodecVP9 vp9_settings; 48 memset(&vp9_settings, 0, sizeof(vp9_settings)); 49 50 vp9_settings.numberOfTemporalLayers = 1; 51 vp9_settings.denoisingOn = true; 52 vp9_settings.keyFrameInterval = 3000; 53 vp9_settings.adaptiveQpMode = true; 54 vp9_settings.automaticResizeOn = true; 55 vp9_settings.numberOfSpatialLayers = 1; 56 vp9_settings.flexibleMode = false; 57 vp9_settings.interLayerPred = InterLayerPredMode::kOn; 58 59 return vp9_settings; 60 } 61 62 VideoCodecH264 VideoEncoder::GetDefaultH264Settings() { 63 VideoCodecH264 h264_settings; 64 memset(&h264_settings, 0, sizeof(h264_settings)); 65 66 h264_settings.keyFrameInterval = 3000; 67 h264_settings.numberOfTemporalLayers = 1; 68 69 return h264_settings; 70 } 71 72 VideoEncoder::ScalingSettings::ScalingSettings() = default; 73 74 VideoEncoder::ScalingSettings::ScalingSettings(KOff) : ScalingSettings() {} 75 76 VideoEncoder::ScalingSettings::ScalingSettings(int low, int high) 77 : thresholds(QpThresholds(low, high)) {} 78 79 VideoEncoder::ScalingSettings::ScalingSettings(int low, 80 int high, 81 int min_pixels) 82 : thresholds(QpThresholds(low, high)), min_pixels_per_frame(min_pixels) {} 83 84 VideoEncoder::ScalingSettings::ScalingSettings(const ScalingSettings&) = 85 default; 86 87 VideoEncoder::ScalingSettings::~ScalingSettings() {} 88 89 bool VideoEncoder::ResolutionBitrateLimits::operator==( 90 const ResolutionBitrateLimits& rhs) const { 91 return frame_size_pixels == rhs.frame_size_pixels && 92 min_start_bitrate_bps == rhs.min_start_bitrate_bps && 93 min_bitrate_bps == rhs.min_bitrate_bps && 94 max_bitrate_bps == rhs.max_bitrate_bps; 95 } 96 97 VideoEncoder::EncoderInfo::EncoderInfo() 98 : scaling_settings(VideoEncoder::ScalingSettings::kOff), 99 requested_resolution_alignment(1), 100 apply_alignment_to_all_simulcast_layers(false), 101 supports_native_handle(false), 102 implementation_name("unknown"), 103 has_trusted_rate_controller(false), 104 is_hardware_accelerated(true), 105 fps_allocation{absl::InlinedVector<uint8_t, kMaxTemporalStreams>( 106 1, 107 kMaxFramerateFraction)}, 108 supports_simulcast(false), 109 preferred_pixel_formats{VideoFrameBuffer::Type::kI420} {} 110 111 VideoEncoder::EncoderInfo::EncoderInfo(const EncoderInfo&) = default; 112 113 VideoEncoder::EncoderInfo::~EncoderInfo() = default; 114 115 std::string VideoEncoder::EncoderInfo::ToString() const { 116 StringBuilder oss; 117 oss << "EncoderInfo { " 118 "ScalingSettings { "; 119 if (scaling_settings.thresholds) { 120 oss << "Thresholds { " 121 "low = " 122 << scaling_settings.thresholds->low 123 << ", high = " << scaling_settings.thresholds->high << "}, "; 124 } 125 oss << "min_pixels_per_frame = " << scaling_settings.min_pixels_per_frame 126 << " }"; 127 oss << ", requested_resolution_alignment = " << requested_resolution_alignment 128 << ", apply_alignment_to_all_simulcast_layers = " 129 << apply_alignment_to_all_simulcast_layers 130 << ", supports_native_handle = " << supports_native_handle 131 << ", implementation_name = '" << implementation_name 132 << "'" 133 ", has_trusted_rate_controller = " 134 << has_trusted_rate_controller 135 << ", is_hardware_accelerated = " << is_hardware_accelerated 136 << ", fps_allocation = ["; 137 size_t num_spatial_layer_with_fps_allocation = 0; 138 for (size_t i = 0; i < kMaxSpatialLayers; ++i) { 139 if (!fps_allocation[i].empty()) { 140 num_spatial_layer_with_fps_allocation = i + 1; 141 } 142 } 143 bool first = true; 144 for (size_t i = 0; i < num_spatial_layer_with_fps_allocation; ++i) { 145 if (fps_allocation[i].empty()) { 146 break; 147 } 148 if (!first) { 149 oss << ", "; 150 } 151 const absl::InlinedVector<uint8_t, kMaxTemporalStreams>& fractions = 152 fps_allocation[i]; 153 if (!fractions.empty()) { 154 first = false; 155 oss << "[ "; 156 for (size_t j = 0; j < fractions.size(); ++j) { 157 if (j > 0) { 158 oss << ", "; 159 } 160 oss << (static_cast<double>(fractions[j]) / kMaxFramerateFraction); 161 } 162 oss << "] "; 163 } 164 } 165 oss << "]"; 166 oss << ", resolution_bitrate_limits = ["; 167 for (size_t i = 0; i < resolution_bitrate_limits.size(); ++i) { 168 if (i > 0) { 169 oss << ", "; 170 } 171 ResolutionBitrateLimits l = resolution_bitrate_limits[i]; 172 oss << "Limits { " 173 "frame_size_pixels = " 174 << l.frame_size_pixels 175 << ", min_start_bitrate_bps = " << l.min_start_bitrate_bps 176 << ", min_bitrate_bps = " << l.min_bitrate_bps 177 << ", max_bitrate_bps = " << l.max_bitrate_bps << "} "; 178 } 179 oss << "] " 180 ", supports_simulcast = " 181 << supports_simulcast; 182 oss << ", preferred_pixel_formats = ["; 183 for (size_t i = 0; i < preferred_pixel_formats.size(); ++i) { 184 if (i > 0) 185 oss << ", "; 186 #if defined(WEBRTC_MOZILLA_BUILD) 187 // This could assert, as opposed to throw using the form in the 188 // else, but since we're in a for loop that uses .size() we can 189 // be fairly sure that this is safe without doing a further 190 // check to make sure 'i' is in-range. 191 oss << VideoFrameBufferTypeToString(preferred_pixel_formats[i]); 192 #else 193 oss << VideoFrameBufferTypeToString(preferred_pixel_formats.at(i)); 194 #endif 195 } 196 oss << "]"; 197 if (is_qp_trusted.has_value()) { 198 oss << ", is_qp_trusted = " << is_qp_trusted.value(); 199 } 200 if (mapped_resolution.has_value()) { 201 oss << ", mapped_resolution = " << mapped_resolution->width << " x " 202 << mapped_resolution->height; 203 } 204 oss << "}"; 205 return oss.str(); 206 } 207 208 bool VideoEncoder::EncoderInfo::operator==(const EncoderInfo& rhs) const { 209 if (scaling_settings.thresholds.has_value() != 210 rhs.scaling_settings.thresholds.has_value()) { 211 return false; 212 } 213 if (scaling_settings.thresholds.has_value()) { 214 QpThresholds l = *scaling_settings.thresholds; 215 QpThresholds r = *rhs.scaling_settings.thresholds; 216 if (l.low != r.low || l.high != r.high) { 217 return false; 218 } 219 } 220 if (scaling_settings.min_pixels_per_frame != 221 rhs.scaling_settings.min_pixels_per_frame) { 222 return false; 223 } 224 225 if (supports_native_handle != rhs.supports_native_handle || 226 implementation_name != rhs.implementation_name || 227 has_trusted_rate_controller != rhs.has_trusted_rate_controller || 228 is_hardware_accelerated != rhs.is_hardware_accelerated) { 229 return false; 230 } 231 232 for (size_t i = 0; i < kMaxSpatialLayers; ++i) { 233 if (fps_allocation[i] != rhs.fps_allocation[i]) { 234 return false; 235 } 236 } 237 238 if (resolution_bitrate_limits != rhs.resolution_bitrate_limits || 239 supports_simulcast != rhs.supports_simulcast) { 240 return false; 241 } 242 243 return true; 244 } 245 246 std::optional<VideoEncoder::ResolutionBitrateLimits> 247 VideoEncoder::EncoderInfo::GetEncoderBitrateLimitsForResolution( 248 int frame_size_pixels) const { 249 std::vector<ResolutionBitrateLimits> bitrate_limits = 250 resolution_bitrate_limits; 251 252 // Sort the list of bitrate limits by resolution. 253 sort(bitrate_limits.begin(), bitrate_limits.end(), 254 [](const ResolutionBitrateLimits& lhs, 255 const ResolutionBitrateLimits& rhs) { 256 return lhs.frame_size_pixels < rhs.frame_size_pixels; 257 }); 258 259 for (size_t i = 0; i < bitrate_limits.size(); ++i) { 260 RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, 0); 261 RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, 0); 262 RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps, 263 bitrate_limits[i].min_bitrate_bps); 264 if (i > 0) { 265 // The bitrate limits aren't expected to decrease with resolution. 266 RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, 267 bitrate_limits[i - 1].min_bitrate_bps); 268 RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, 269 bitrate_limits[i - 1].min_start_bitrate_bps); 270 RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps, 271 bitrate_limits[i - 1].max_bitrate_bps); 272 } 273 274 if (bitrate_limits[i].frame_size_pixels >= frame_size_pixels) { 275 return std::optional<ResolutionBitrateLimits>(bitrate_limits[i]); 276 } 277 } 278 279 return std::nullopt; 280 } 281 282 VideoEncoder::RateControlParameters::RateControlParameters() 283 : bitrate(VideoBitrateAllocation()), 284 framerate_fps(0.0), 285 bandwidth_allocation(DataRate::Zero()) {} 286 287 VideoEncoder::RateControlParameters::RateControlParameters( 288 const VideoBitrateAllocation& bitrate, 289 double framerate_fps) 290 : bitrate(bitrate), 291 framerate_fps(framerate_fps), 292 bandwidth_allocation(DataRate::BitsPerSec(bitrate.get_sum_bps())) {} 293 294 VideoEncoder::RateControlParameters::RateControlParameters( 295 const VideoBitrateAllocation& bitrate, 296 double framerate_fps, 297 DataRate bandwidth_allocation) 298 : bitrate(bitrate), 299 framerate_fps(framerate_fps), 300 bandwidth_allocation(bandwidth_allocation) {} 301 302 bool VideoEncoder::RateControlParameters::operator==( 303 const VideoEncoder::RateControlParameters& rhs) const { 304 return std::tie(bitrate, framerate_fps, bandwidth_allocation) == 305 std::tie(rhs.bitrate, rhs.framerate_fps, rhs.bandwidth_allocation); 306 } 307 308 bool VideoEncoder::RateControlParameters::operator!=( 309 const VideoEncoder::RateControlParameters& rhs) const { 310 return !(rhs == *this); 311 } 312 313 VideoEncoder::RateControlParameters::~RateControlParameters() = default; 314 315 void VideoEncoder::SetFecControllerOverride( 316 FecControllerOverride* /* fec_controller_override */) {} 317 318 int32_t VideoEncoder::InitEncode(const VideoCodec* codec_settings, 319 int32_t number_of_cores, 320 size_t max_payload_size) { 321 const VideoEncoder::Capabilities capabilities(/* loss_notification= */ false); 322 const VideoEncoder::Settings settings(capabilities, number_of_cores, 323 max_payload_size); 324 // In theory, this and the other version of InitEncode() could end up calling 325 // each other in a loop until we get a stack overflow. 326 // In practice, any subclass of VideoEncoder would overload at least one 327 // of these, and we have a TODO in the header file to make this pure virtual. 328 return InitEncode(codec_settings, settings); 329 } 330 331 int VideoEncoder::InitEncode(const VideoCodec* codec_settings, 332 const VideoEncoder::Settings& settings) { 333 // In theory, this and the other version of InitEncode() could end up calling 334 // each other in a loop until we get a stack overflow. 335 // In practice, any subclass of VideoEncoder would overload at least one 336 // of these, and we have a TODO in the header file to make this pure virtual. 337 return InitEncode(codec_settings, settings.number_of_cores, 338 settings.max_payload_size); 339 } 340 341 void VideoEncoder::OnPacketLossRateUpdate(float /* packet_loss_rate */) {} 342 343 void VideoEncoder::OnRttUpdate(int64_t /* rtt_ms */) {} 344 345 void VideoEncoder::OnLossNotification( 346 const LossNotification& /* loss_notification */) {} 347 348 } // namespace webrtc