libaom_av1_encoder.cc (42991B)
1 /* 2 * Copyright (c) 2020 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 #include "modules/video_coding/codecs/av1/libaom_av1_encoder.h" 11 12 #include <cstddef> 13 #include <cstdint> 14 #include <map> 15 #include <memory> 16 #include <numeric> 17 #include <optional> 18 #include <utility> 19 #include <variant> 20 #include <vector> 21 22 #include "absl/algorithm/container.h" 23 #include "absl/base/nullability.h" 24 #include "absl/container/inlined_vector.h" 25 #include "api/environment/environment.h" 26 #include "api/field_trials_view.h" 27 #include "api/scoped_refptr.h" 28 #include "api/video/encoded_image.h" 29 #include "api/video/render_resolution.h" 30 #include "api/video/video_codec_constants.h" 31 #include "api/video/video_codec_type.h" 32 #include "api/video/video_content_type.h" 33 #include "api/video/video_frame.h" 34 #include "api/video/video_frame_buffer.h" 35 #include "api/video/video_frame_type.h" 36 #include "api/video/video_timing.h" 37 #include "api/video_codecs/scalability_mode.h" 38 #include "api/video_codecs/video_codec.h" 39 #include "api/video_codecs/video_encoder.h" 40 #include "common_video/generic_frame_descriptor/generic_frame_info.h" 41 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 42 #include "modules/video_coding/include/video_codec_interface.h" 43 #include "modules/video_coding/include/video_error_codes.h" 44 #include "modules/video_coding/svc/create_scalability_structure.h" 45 #include "modules/video_coding/svc/scalable_video_controller.h" 46 #include "modules/video_coding/utility/frame_sampler.h" 47 #include "rtc_base/checks.h" 48 #include "rtc_base/experiments/encoder_info_settings.h" 49 #include "rtc_base/logging.h" 50 #include "third_party/libaom/source/libaom/aom/aom_codec.h" 51 #include "third_party/libaom/source/libaom/aom/aom_encoder.h" 52 #include "third_party/libaom/source/libaom/aom/aom_image.h" 53 #include "third_party/libaom/source/libaom/aom/aomcx.h" 54 55 #if (defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)) && \ 56 (defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)) 57 #define MOBILE_ARM 58 #endif 59 60 #define SET_ENCODER_PARAM_OR_RETURN_ERROR(param_id, param_value) \ 61 do { \ 62 if (!SetEncoderControlParameters(param_id, param_value)) { \ 63 return WEBRTC_VIDEO_CODEC_ERROR; \ 64 } \ 65 } while (0) 66 67 namespace webrtc { 68 namespace { 69 70 // Encoder configuration parameters 71 constexpr int kMinQp = 10; 72 constexpr int kMinQindex = 40; // Min qindex corresponding to kMinQp. 73 constexpr int kUsageProfile = AOM_USAGE_REALTIME; 74 constexpr int kLowQindex = 145; // Low qindex threshold for QP scaling. 75 constexpr int kHighQindex = 205; // High qindex threshold for QP scaling. 76 constexpr int kBitDepth = 8; 77 constexpr int kLagInFrames = 0; // No look ahead. 78 constexpr double kMinFrameRateFps = 1.0; 79 80 aom_superblock_size_t GetSuperblockSize(int width, int height, int threads) { 81 int resolution = width * height; 82 if (threads >= 4 && resolution >= 960 * 540 && resolution < 1920 * 1080) 83 return AOM_SUPERBLOCK_SIZE_64X64; 84 else 85 return AOM_SUPERBLOCK_SIZE_DYNAMIC; 86 } 87 88 void PopulateEncodedImageFromVideoFrame(const VideoFrame& frame, 89 EncodedImage& encoded_image) { 90 encoded_image.SetRtpTimestamp(frame.rtp_timestamp()); 91 encoded_image.SetPresentationTimestamp(frame.presentation_timestamp()); 92 encoded_image.capture_time_ms_ = frame.render_time_ms(); 93 encoded_image.rotation_ = frame.rotation(); 94 encoded_image.SetColorSpace(frame.color_space()); 95 } 96 class LibaomAv1Encoder final : public VideoEncoder { 97 public: 98 LibaomAv1Encoder(const Environment& env, LibaomAv1EncoderSettings settings); 99 ~LibaomAv1Encoder() override; 100 101 int InitEncode(const VideoCodec* codec_settings, 102 const Settings& settings) override; 103 104 int32_t RegisterEncodeCompleteCallback( 105 EncodedImageCallback* encoded_image_callback) override; 106 107 int32_t Release() override; 108 109 int32_t Encode(const VideoFrame& frame, 110 const std::vector<VideoFrameType>* frame_types) override; 111 112 void SetRates(const RateControlParameters& parameters) override; 113 114 EncoderInfo GetEncoderInfo() const override; 115 116 private: 117 template <typename P> 118 bool SetEncoderControlParameters(int param_id, P param_value); 119 120 // Get value to be used for encoder cpu_speed setting 121 int GetCpuSpeed(int width, int height); 122 123 // Determine number of encoder threads to use. 124 int NumberOfThreads(int width, int height, int number_of_cores); 125 126 bool SvcEnabled() const { return svc_params_.has_value(); } 127 // Fills svc_params_ memeber value. Returns false on error. 128 bool SetSvcParams(ScalableVideoController::StreamLayersConfig svc_config, 129 const aom_codec_enc_cfg_t& encoder_config); 130 // Configures the encoder with layer for the next frame. 131 void SetSvcLayerId( 132 const ScalableVideoController::LayerFrameConfig& layer_frame); 133 // Configures the encoder which buffers next frame updates and can reference. 134 void SetSvcRefFrameConfig( 135 const ScalableVideoController::LayerFrameConfig& layer_frame); 136 // If pixel format doesn't match, then reallocate. 137 void MaybeRewrapImgWithFormat(const aom_img_fmt_t fmt, 138 unsigned int width, 139 unsigned int height); 140 141 // Adjust sclaing factors assuming that the top active SVC layer 142 // will be the input resolution. 143 void AdjustScalingFactorsForTopActiveLayer(); 144 145 using EncodeResult = std::variant<aom_codec_err_t, EncodedImage>; 146 147 // Duration is specified in ticks based on aom_codec_enc_cfg_t::g_timebase, 148 // in practice that that is kVideoPayloadTypeFrequency (90kHz). 149 EncodeResult DoEncode(uint32_t duration, 150 aom_enc_frame_flags_t flags, 151 ScalableVideoController::LayerFrameConfig* layer_frame); 152 153 CodecSpecificInfo CreateCodecSpecificInfo( 154 const EncodedImage& image, 155 const ScalableVideoController::LayerFrameConfig& layer_frame, 156 bool end_of_picture); 157 158 std::unique_ptr<ScalableVideoController> svc_controller_; 159 std::optional<ScalabilityMode> scalability_mode_; 160 // Original scaling factors for all configured layers active and inactive. 161 // `svc_params_` stores factors ignoring top inactive layers. 162 std::vector<int> scaling_factors_num_; 163 std::vector<int> scaling_factors_den_; 164 int last_active_layer_ = 0; 165 166 bool inited_; 167 bool rates_configured_; 168 std::optional<aom_svc_params_t> svc_params_; 169 VideoCodec encoder_settings_; 170 LibaomAv1EncoderSettings settings_; 171 aom_image_t* frame_for_encode_; 172 aom_codec_ctx_t ctx_; 173 aom_codec_enc_cfg_t cfg_; 174 EncodedImageCallback* encoded_image_callback_; 175 double framerate_fps_; // Current target frame rate. 176 int64_t timestamp_; 177 const LibaomAv1EncoderInfoSettings encoder_info_override_; 178 // TODO(webrtc:351644568): Remove this kill-switch after the feature is fully 179 // deployed. 180 const bool post_encode_frame_drop_; 181 182 // Determine whether the frame should be sampled for PSNR. 183 FrameSampler psnr_frame_sampler_; 184 // TODO(webrtc:388070060): Remove after rollout. 185 const bool calculate_psnr_; 186 const bool drop_repeat_frames_on_enhancement_layers_; 187 std::map<int, uint32_t> last_encoded_timestamp_by_sid_; 188 }; 189 190 int32_t VerifyCodecSettings(const VideoCodec& codec_settings) { 191 if (codec_settings.width < 1) { 192 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 193 } 194 if (codec_settings.height < 1) { 195 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 196 } 197 // maxBitrate == 0 represents an unspecified maxBitRate. 198 if (codec_settings.maxBitrate > 0 && 199 codec_settings.minBitrate > codec_settings.maxBitrate) { 200 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 201 } 202 if (codec_settings.maxBitrate > 0 && 203 codec_settings.startBitrate > codec_settings.maxBitrate) { 204 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 205 } 206 if (codec_settings.startBitrate < codec_settings.minBitrate) { 207 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 208 } 209 if (codec_settings.maxFramerate < 1) { 210 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 211 } 212 if (codec_settings.qpMax < kMinQp || codec_settings.qpMax > 63) { 213 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 214 } 215 return WEBRTC_VIDEO_CODEC_OK; 216 } 217 218 LibaomAv1Encoder::LibaomAv1Encoder(const Environment& env, 219 LibaomAv1EncoderSettings settings) 220 : inited_(false), 221 rates_configured_(false), 222 settings_(std::move(settings)), 223 frame_for_encode_(nullptr), 224 encoded_image_callback_(nullptr), 225 framerate_fps_(0), 226 timestamp_(0), 227 encoder_info_override_(env.field_trials()), 228 post_encode_frame_drop_(!env.field_trials().IsDisabled( 229 "WebRTC-LibaomAv1Encoder-PostEncodeFrameDrop")), 230 calculate_psnr_( 231 env.field_trials().IsEnabled("WebRTC-Video-CalculatePsnr")), 232 drop_repeat_frames_on_enhancement_layers_(env.field_trials().IsEnabled( 233 "WebRTC-LibaomAv1Encoder-DropRepeatFramesOnEnhancementLayers")) {} 234 235 LibaomAv1Encoder::~LibaomAv1Encoder() { 236 Release(); 237 } 238 239 int LibaomAv1Encoder::InitEncode(const VideoCodec* codec_settings, 240 const Settings& settings) { 241 if (codec_settings == nullptr) { 242 RTC_LOG(LS_WARNING) << "No codec settings provided to " 243 "LibaomAv1Encoder."; 244 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 245 } 246 if (settings.number_of_cores < 1) { 247 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 248 } 249 if (inited_) { 250 RTC_LOG(LS_WARNING) << "Initing LibaomAv1Encoder without first releasing."; 251 Release(); 252 } 253 encoder_settings_ = *codec_settings; 254 255 // Sanity checks for encoder configuration. 256 const int32_t result = VerifyCodecSettings(encoder_settings_); 257 if (result < 0) { 258 RTC_LOG(LS_WARNING) << "Incorrect codec settings provided to " 259 "LibaomAv1Encoder."; 260 return result; 261 } 262 if (encoder_settings_.numberOfSimulcastStreams > 1) { 263 RTC_LOG(LS_WARNING) << "Simulcast is not implemented by LibaomAv1Encoder."; 264 return result; 265 } 266 scalability_mode_ = encoder_settings_.GetScalabilityMode(); 267 if (!scalability_mode_.has_value()) { 268 RTC_LOG(LS_WARNING) << "Scalability mode is not set, using 'L1T1'."; 269 scalability_mode_ = ScalabilityMode::kL1T1; 270 } 271 svc_controller_ = CreateScalabilityStructure(*scalability_mode_); 272 if (svc_controller_ == nullptr) { 273 RTC_LOG(LS_WARNING) << "Failed to set scalability mode " 274 << static_cast<int>(*scalability_mode_); 275 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 276 } 277 278 // Initialize encoder configuration structure with default values 279 aom_codec_err_t ret = 280 aom_codec_enc_config_default(aom_codec_av1_cx(), &cfg_, kUsageProfile); 281 if (ret != AOM_CODEC_OK) { 282 RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret 283 << " on aom_codec_enc_config_default."; 284 return WEBRTC_VIDEO_CODEC_ERROR; 285 } 286 287 // Overwrite default config with input encoder settings & RTC-relevant values. 288 cfg_.g_w = encoder_settings_.width; 289 cfg_.g_h = encoder_settings_.height; 290 cfg_.g_threads = 291 NumberOfThreads(cfg_.g_w, cfg_.g_h, settings.number_of_cores); 292 cfg_.g_timebase.num = 1; 293 cfg_.g_timebase.den = kVideoPayloadTypeFrequency; 294 cfg_.rc_target_bitrate = encoder_settings_.startBitrate; // kilobits/sec. 295 cfg_.rc_dropframe_thresh = encoder_settings_.GetFrameDropEnabled() ? 30 : 0; 296 cfg_.g_input_bit_depth = kBitDepth; 297 cfg_.kf_mode = AOM_KF_DISABLED; 298 cfg_.rc_min_quantizer = kMinQp; 299 cfg_.rc_max_quantizer = encoder_settings_.qpMax; 300 cfg_.rc_undershoot_pct = 50; 301 cfg_.rc_overshoot_pct = 50; 302 cfg_.rc_buf_initial_sz = 600; 303 cfg_.rc_buf_optimal_sz = 600; 304 cfg_.rc_buf_sz = 1000; 305 cfg_.g_usage = kUsageProfile; 306 cfg_.g_error_resilient = 0; 307 // Low-latency settings. 308 cfg_.rc_end_usage = AOM_CBR; // Constant Bit Rate (CBR) mode 309 cfg_.g_pass = AOM_RC_ONE_PASS; // One-pass rate control 310 cfg_.g_lag_in_frames = kLagInFrames; // No look ahead when lag equals 0. 311 312 if (frame_for_encode_ != nullptr) { 313 aom_img_free(frame_for_encode_); 314 frame_for_encode_ = nullptr; 315 } 316 317 // Flag options: AOM_EFLAG_CALCULATE_PSNR and AOM_CODEC_USE_HIGHBITDEPTH 318 aom_codec_flags_t flags = 0; 319 320 // Initialize an encoder instance. 321 ret = aom_codec_enc_init(&ctx_, aom_codec_av1_cx(), &cfg_, flags); 322 if (ret != AOM_CODEC_OK) { 323 RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret 324 << " on aom_codec_enc_init."; 325 return WEBRTC_VIDEO_CODEC_ERROR; 326 } 327 328 if (!SetSvcParams(svc_controller_->StreamConfig(), cfg_)) { 329 return WEBRTC_VIDEO_CODEC_ERROR; 330 } 331 332 inited_ = true; 333 334 // Set control parameters 335 SET_ENCODER_PARAM_OR_RETURN_ERROR(AOME_SET_CPUUSED, 336 GetCpuSpeed(cfg_.g_w, cfg_.g_h)); 337 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_CDEF, 1); 338 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_TPL_MODEL, 0); 339 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_DELTAQ_MODE, 0); 340 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_ORDER_HINT, 0); 341 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_AQ_MODE, 3); 342 SET_ENCODER_PARAM_OR_RETURN_ERROR(AOME_SET_MAX_INTRA_BITRATE_PCT, 300); 343 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_COEFF_COST_UPD_FREQ, 3); 344 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_MODE_COST_UPD_FREQ, 3); 345 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_MV_COST_UPD_FREQ, 3); 346 347 if (codec_settings->mode == VideoCodecMode::kScreensharing) { 348 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_TUNE_CONTENT, 349 AOM_CONTENT_SCREEN); 350 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_PALETTE, 1); 351 } else { 352 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_PALETTE, 0); 353 } 354 355 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_AUTO_TILES, 1); 356 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ROW_MT, 1); 357 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_OBMC, 0); 358 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_NOISE_SENSITIVITY, 0); 359 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_WARPED_MOTION, 0); 360 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_GLOBAL_MOTION, 0); 361 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_REF_FRAME_MVS, 0); 362 SET_ENCODER_PARAM_OR_RETURN_ERROR( 363 AV1E_SET_SUPERBLOCK_SIZE, 364 GetSuperblockSize(cfg_.g_w, cfg_.g_h, cfg_.g_threads)); 365 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_CFL_INTRA, 0); 366 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_SMOOTH_INTRA, 0); 367 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_ANGLE_DELTA, 0); 368 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_FILTER_INTRA, 0); 369 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_INTRA_DEFAULT_TX_ONLY, 1); 370 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_DISABLE_TRELLIS_QUANT, 1); 371 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_DIST_WTD_COMP, 0); 372 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_DIFF_WTD_COMP, 0); 373 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_DUAL_FILTER, 0); 374 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_INTERINTRA_COMP, 0); 375 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_INTERINTRA_WEDGE, 0); 376 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_INTRA_EDGE_FILTER, 0); 377 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_INTRABC, 0); 378 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_MASKED_COMP, 0); 379 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_PAETH_INTRA, 0); 380 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_QM, 0); 381 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_RECT_PARTITIONS, 0); 382 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_RESTORATION, 0); 383 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_SMOOTH_INTERINTRA, 0); 384 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_TX64, 0); 385 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_MAX_REFERENCE_FRAMES, 3); 386 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR, 250); 387 388 if (post_encode_frame_drop_) { 389 SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_POSTENCODE_DROP_RTC, 1); 390 } 391 392 return WEBRTC_VIDEO_CODEC_OK; 393 } 394 395 template <typename P> 396 bool LibaomAv1Encoder::SetEncoderControlParameters(int param_id, 397 P param_value) { 398 aom_codec_err_t error_code = aom_codec_control(&ctx_, param_id, param_value); 399 if (error_code != AOM_CODEC_OK) { 400 RTC_LOG(LS_WARNING) 401 << "LibaomAv1Encoder::SetEncoderControlParameters returned " 402 << error_code << " on id: " << param_id << "."; 403 } 404 return error_code == AOM_CODEC_OK; 405 } 406 407 // Only positive speeds, range for real-time coding currently is: 6 - 10. 408 // Speed 11 is used for screen sharing. 409 // Lower means slower/better quality, higher means fastest/lower quality. 410 int LibaomAv1Encoder::GetCpuSpeed(int width, int height) { 411 if (!settings_.max_pixel_count_to_cpu_speed.empty()) { 412 if (auto it = 413 settings_.max_pixel_count_to_cpu_speed.lower_bound(width * height); 414 it != settings_.max_pixel_count_to_cpu_speed.end()) { 415 return it->second; 416 } 417 418 return 10; 419 } else { 420 if (encoder_settings_.mode == VideoCodecMode::kScreensharing) { 421 return 11; 422 } 423 // For smaller resolutions, use lower speed setting (get some coding gain at 424 // the cost of increased encoding complexity). 425 switch (encoder_settings_.GetVideoEncoderComplexity()) { 426 case VideoCodecComplexity::kComplexityHigh: 427 if (width * height <= 320 * 180) 428 return 8; 429 else if (width * height <= 640 * 360) 430 return 9; 431 else 432 return 10; 433 case VideoCodecComplexity::kComplexityHigher: 434 if (width * height <= 320 * 180) 435 return 7; 436 else if (width * height <= 640 * 360) 437 return 8; 438 else if (width * height <= 1280 * 720) 439 return 9; 440 else 441 return 10; 442 case VideoCodecComplexity::kComplexityMax: 443 if (width * height <= 320 * 180) 444 return 6; 445 else if (width * height <= 640 * 360) 446 return 7; 447 else if (width * height <= 1280 * 720) 448 return 8; 449 else 450 return 9; 451 default: 452 return 10; 453 } 454 } 455 } 456 457 int LibaomAv1Encoder::NumberOfThreads(int width, 458 int height, 459 int number_of_cores) { 460 // Keep the number of encoder threads equal to the possible number of 461 // column/row tiles, which is (1, 2, 4, 8). See comments below for 462 // AV1E_SET_TILE_COLUMNS/ROWS. 463 if (width * height > 1280 * 720 && number_of_cores > 8) { 464 return 8; 465 } else if (width * height >= 640 * 360 && number_of_cores > 4) { 466 return 4; 467 } else if (width * height >= 320 * 180 && number_of_cores > 2) { 468 return 2; 469 } else { 470 // Use 2 threads for low res on ARM. 471 #ifdef MOBILE_ARM 472 if (width * height >= 320 * 180 && number_of_cores > 2) { 473 return 2; 474 } 475 #endif 476 // 1 thread less than VGA. 477 return 1; 478 } 479 } 480 481 bool LibaomAv1Encoder::SetSvcParams( 482 ScalableVideoController::StreamLayersConfig svc_config, 483 const aom_codec_enc_cfg_t& encoder_config) { 484 bool svc_enabled = 485 svc_config.num_spatial_layers > 1 || svc_config.num_temporal_layers > 1; 486 if (!svc_enabled) { 487 svc_params_ = std::nullopt; 488 return true; 489 } 490 if (svc_config.num_spatial_layers < 1 || svc_config.num_spatial_layers > 4) { 491 RTC_LOG(LS_WARNING) << "Av1 supports up to 4 spatial layers. " 492 << svc_config.num_spatial_layers << " configured."; 493 return false; 494 } 495 if (svc_config.num_temporal_layers < 1 || 496 svc_config.num_temporal_layers > 8) { 497 RTC_LOG(LS_WARNING) << "Av1 supports up to 8 temporal layers. " 498 << svc_config.num_temporal_layers << " configured."; 499 return false; 500 } 501 aom_svc_params_t& svc_params = svc_params_.emplace(); 502 svc_params.number_spatial_layers = svc_config.num_spatial_layers; 503 svc_params.number_temporal_layers = svc_config.num_temporal_layers; 504 505 int num_layers = 506 svc_config.num_spatial_layers * svc_config.num_temporal_layers; 507 for (int i = 0; i < num_layers; ++i) { 508 svc_params.min_quantizers[i] = encoder_config.rc_min_quantizer; 509 svc_params.max_quantizers[i] = encoder_config.rc_max_quantizer; 510 } 511 512 // Assume each temporal layer doubles framerate. 513 for (int tid = 0; tid < svc_config.num_temporal_layers; ++tid) { 514 svc_params.framerate_factor[tid] = 515 1 << (svc_config.num_temporal_layers - tid - 1); 516 } 517 518 scaling_factors_den_.resize(svc_config.num_spatial_layers); 519 scaling_factors_num_.resize(svc_config.num_spatial_layers); 520 for (int sid = 0; sid < svc_config.num_spatial_layers; ++sid) { 521 scaling_factors_num_[sid] = svc_config.scaling_factor_num[sid]; 522 svc_params.scaling_factor_num[sid] = svc_config.scaling_factor_num[sid]; 523 scaling_factors_den_[sid] = svc_config.scaling_factor_den[sid]; 524 svc_params.scaling_factor_den[sid] = svc_config.scaling_factor_den[sid]; 525 encoder_settings_.spatialLayers[sid].width = encoder_settings_.width * 526 scaling_factors_num_[sid] / 527 scaling_factors_den_[sid]; 528 encoder_settings_.spatialLayers[sid].height = encoder_settings_.height * 529 scaling_factors_num_[sid] / 530 scaling_factors_den_[sid]; 531 } 532 533 // svc_params.layer_target_bitrate is set in SetRates() before svc_params is 534 // passed to SetEncoderControlParameters(AV1E_SET_SVC_PARAMS). 535 536 return true; 537 } 538 539 void LibaomAv1Encoder::SetSvcLayerId( 540 const ScalableVideoController::LayerFrameConfig& layer_frame) { 541 aom_svc_layer_id_t layer_id = {}; 542 layer_id.spatial_layer_id = layer_frame.SpatialId(); 543 layer_id.temporal_layer_id = layer_frame.TemporalId(); 544 SetEncoderControlParameters(AV1E_SET_SVC_LAYER_ID, &layer_id); 545 } 546 547 void LibaomAv1Encoder::SetSvcRefFrameConfig( 548 const ScalableVideoController::LayerFrameConfig& layer_frame) { 549 // Buffer name to use for each layer_frame.buffers position. In particular 550 // when there are 2 buffers are referenced, prefer name them last and golden, 551 // because av1 bitstream format has dedicated fields for these two names. 552 // See last_frame_idx and golden_frame_idx in the av1 spec 553 // https://aomediacodec.github.io/av1-spec/av1-spec.pdf 554 static constexpr int kPreferedSlotName[] = {0, // Last 555 3, // Golden 556 1, 2, 4, 5, 6}; 557 static constexpr int kAv1NumBuffers = 8; 558 559 aom_svc_ref_frame_config_t ref_frame_config = {}; 560 RTC_CHECK_LE(layer_frame.Buffers().size(), std::size(kPreferedSlotName)); 561 for (size_t i = 0; i < layer_frame.Buffers().size(); ++i) { 562 const CodecBufferUsage& buffer = layer_frame.Buffers()[i]; 563 int slot_name = kPreferedSlotName[i]; 564 RTC_CHECK_GE(buffer.id, 0); 565 RTC_CHECK_LT(buffer.id, kAv1NumBuffers); 566 ref_frame_config.ref_idx[slot_name] = buffer.id; 567 if (buffer.referenced) { 568 ref_frame_config.reference[slot_name] = 1; 569 } 570 if (buffer.updated) { 571 ref_frame_config.refresh[buffer.id] = 1; 572 } 573 } 574 575 SetEncoderControlParameters(AV1E_SET_SVC_REF_FRAME_CONFIG, &ref_frame_config); 576 } 577 578 int32_t LibaomAv1Encoder::RegisterEncodeCompleteCallback( 579 EncodedImageCallback* encoded_image_callback) { 580 encoded_image_callback_ = encoded_image_callback; 581 return WEBRTC_VIDEO_CODEC_OK; 582 } 583 584 int32_t LibaomAv1Encoder::Release() { 585 if (frame_for_encode_ != nullptr) { 586 aom_img_free(frame_for_encode_); 587 frame_for_encode_ = nullptr; 588 } 589 if (inited_) { 590 if (aom_codec_destroy(&ctx_)) { 591 return WEBRTC_VIDEO_CODEC_MEMORY; 592 } 593 inited_ = false; 594 } 595 rates_configured_ = false; 596 return WEBRTC_VIDEO_CODEC_OK; 597 } 598 599 void LibaomAv1Encoder::MaybeRewrapImgWithFormat(const aom_img_fmt_t fmt, 600 unsigned int width, 601 unsigned int height) { 602 if (!frame_for_encode_) { 603 RTC_LOG(LS_INFO) << "Configuring AV1 encoder pixel format to " 604 << (fmt == AOM_IMG_FMT_NV12 ? "NV12" : "I420") << " " 605 << width << "x" << height; 606 frame_for_encode_ = aom_img_wrap(nullptr, fmt, width, height, 1, nullptr); 607 } else if (frame_for_encode_->fmt != fmt || frame_for_encode_->d_w != width || 608 frame_for_encode_->d_h != height) { 609 RTC_LOG(LS_INFO) << "Switching AV1 encoder pixel format to " 610 << (fmt == AOM_IMG_FMT_NV12 ? "NV12" : "I420") << " " 611 << width << "x" << height; 612 aom_img_free(frame_for_encode_); 613 frame_for_encode_ = aom_img_wrap(nullptr, fmt, width, height, 1, nullptr); 614 } 615 // else no-op since the image is already in the right format. 616 } 617 618 void LibaomAv1Encoder::AdjustScalingFactorsForTopActiveLayer() { 619 if (!SvcEnabled()) 620 return; 621 last_active_layer_ = svc_params_->number_spatial_layers - 1; 622 for (int sid = 0; sid < svc_params_->number_spatial_layers; ++sid) { 623 for (int tid = 0; tid < svc_params_->number_temporal_layers; ++tid) { 624 int layer_index = sid * svc_params_->number_temporal_layers + tid; 625 if (svc_params_->layer_target_bitrate[layer_index] > 0) { 626 last_active_layer_ = sid; 627 } 628 } 629 } 630 if (static_cast<int>(cfg_.g_w) == 631 encoder_settings_.spatialLayers[last_active_layer_].width) { 632 return; 633 } 634 635 cfg_.g_w = encoder_settings_.spatialLayers[last_active_layer_].width; 636 cfg_.g_h = encoder_settings_.spatialLayers[last_active_layer_].height; 637 638 // Recalculate scaling factors ignoring top inactive layers. 639 // Divide all by scaling factor of the last active layer. 640 for (int i = 0; i <= last_active_layer_; ++i) { 641 int n = scaling_factors_num_[i] * scaling_factors_den_[last_active_layer_]; 642 int d = scaling_factors_den_[i] * scaling_factors_num_[last_active_layer_]; 643 int gcd = std::gcd(n, d); 644 svc_params_->scaling_factor_num[i] = n / gcd; 645 svc_params_->scaling_factor_den[i] = d / gcd; 646 } 647 for (int i = last_active_layer_ + 1; i < svc_params_->number_spatial_layers; 648 ++i) { 649 svc_params_->scaling_factor_num[i] = 1; 650 svc_params_->scaling_factor_den[i] = 1; 651 } 652 } 653 654 int32_t LibaomAv1Encoder::Encode( 655 const VideoFrame& frame, 656 const std::vector<VideoFrameType>* frame_types) { 657 if (!inited_ || encoded_image_callback_ == nullptr || !rates_configured_) { 658 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 659 } 660 661 bool keyframe_required = 662 frame_types != nullptr && 663 absl::c_linear_search(*frame_types, VideoFrameType::kVideoFrameKey); 664 665 std::vector<ScalableVideoController::LayerFrameConfig> layer_frames = 666 svc_controller_->NextFrameConfig(keyframe_required); 667 668 if (layer_frames.empty()) { 669 RTC_LOG(LS_ERROR) << "SVCController returned no configuration for a frame."; 670 return WEBRTC_VIDEO_CODEC_ERROR; 671 } 672 673 if (drop_repeat_frames_on_enhancement_layers_ && frame.is_repeat_frame()) { 674 bool all_layers_droppable = !layer_frames.empty(); 675 for (const auto& layer_frame : layer_frames) { 676 if (layer_frame.TemporalId() == 0) { 677 all_layers_droppable = false; 678 break; 679 } 680 if (auto it = 681 last_encoded_timestamp_by_sid_.find(layer_frame.SpatialId()); 682 it != last_encoded_timestamp_by_sid_.end()) { 683 // Get the time since the last encoded frame for this spatial layer. 684 // Don't drop enhancement layer repeat frame if last encode was more 685 // than one second ago. 686 if ((frame.rtp_timestamp() - it->second) > kVideoPayloadTypeFrequency) { 687 all_layers_droppable = false; 688 break; 689 } 690 } 691 } 692 693 if (all_layers_droppable) { 694 RTC_LOG(LS_VERBOSE) << "Dropping repeat frame on enhancement layers."; 695 for (const auto& layer_frame : layer_frames) { 696 svc_controller_->OnEncodeDone(layer_frame); 697 } 698 return WEBRTC_VIDEO_CODEC_OK; // Frame dropped 699 } 700 } 701 702 scoped_refptr<VideoFrameBuffer> buffer = frame.video_frame_buffer(); 703 absl::InlinedVector<VideoFrameBuffer::Type, kMaxPreferredPixelFormats> 704 supported_formats = {VideoFrameBuffer::Type::kI420, 705 VideoFrameBuffer::Type::kNV12}; 706 707 scoped_refptr<VideoFrameBuffer> scaled_image; 708 if (!SvcEnabled() || 709 last_active_layer_ + 1 == svc_params_->number_spatial_layers) { 710 scaled_image = buffer; 711 } else { 712 scaled_image = buffer->Scale( 713 encoder_settings_.spatialLayers[last_active_layer_].width, 714 encoder_settings_.spatialLayers[last_active_layer_].height); 715 } 716 717 scoped_refptr<VideoFrameBuffer> mapped_buffer; 718 if (scaled_image->type() != VideoFrameBuffer::Type::kNative) { 719 // `buffer` is already mapped. 720 mapped_buffer = scaled_image; 721 } else { 722 // Attempt to map to one of the supported formats. 723 mapped_buffer = scaled_image->GetMappedFrameBuffer(supported_formats); 724 } 725 726 // Convert input frame to I420, if needed. 727 if (!mapped_buffer || 728 (absl::c_find(supported_formats, mapped_buffer->type()) == 729 supported_formats.end() && 730 mapped_buffer->type() != VideoFrameBuffer::Type::kI420A)) { 731 scoped_refptr<I420BufferInterface> converted_buffer(buffer->ToI420()); 732 if (!converted_buffer) { 733 RTC_LOG(LS_ERROR) << "Failed to convert " 734 << VideoFrameBufferTypeToString( 735 frame.video_frame_buffer()->type()) 736 << " image to I420. Can't encode frame."; 737 return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE; 738 } 739 RTC_CHECK(converted_buffer->type() == VideoFrameBuffer::Type::kI420 || 740 converted_buffer->type() == VideoFrameBuffer::Type::kI420A); 741 742 mapped_buffer = converted_buffer; 743 } 744 745 switch (mapped_buffer->type()) { 746 case VideoFrameBuffer::Type::kI420: 747 case VideoFrameBuffer::Type::kI420A: { 748 // Set frame_for_encode_ data pointers and strides. 749 MaybeRewrapImgWithFormat(AOM_IMG_FMT_I420, mapped_buffer->width(), 750 mapped_buffer->height()); 751 auto i420_buffer = mapped_buffer->GetI420(); 752 RTC_DCHECK(i420_buffer); 753 RTC_CHECK_EQ(i420_buffer->width(), frame_for_encode_->d_w); 754 RTC_CHECK_EQ(i420_buffer->height(), frame_for_encode_->d_h); 755 frame_for_encode_->planes[AOM_PLANE_Y] = 756 const_cast<unsigned char*>(i420_buffer->DataY()); 757 frame_for_encode_->planes[AOM_PLANE_U] = 758 const_cast<unsigned char*>(i420_buffer->DataU()); 759 frame_for_encode_->planes[AOM_PLANE_V] = 760 const_cast<unsigned char*>(i420_buffer->DataV()); 761 frame_for_encode_->stride[AOM_PLANE_Y] = i420_buffer->StrideY(); 762 frame_for_encode_->stride[AOM_PLANE_U] = i420_buffer->StrideU(); 763 frame_for_encode_->stride[AOM_PLANE_V] = i420_buffer->StrideV(); 764 break; 765 } 766 case VideoFrameBuffer::Type::kNV12: { 767 MaybeRewrapImgWithFormat(AOM_IMG_FMT_NV12, mapped_buffer->width(), 768 mapped_buffer->height()); 769 const NV12BufferInterface* nv12_buffer = mapped_buffer->GetNV12(); 770 RTC_DCHECK(nv12_buffer); 771 RTC_CHECK_EQ(nv12_buffer->width(), frame_for_encode_->d_w); 772 RTC_CHECK_EQ(nv12_buffer->height(), frame_for_encode_->d_h); 773 frame_for_encode_->planes[AOM_PLANE_Y] = 774 const_cast<unsigned char*>(nv12_buffer->DataY()); 775 frame_for_encode_->planes[AOM_PLANE_U] = 776 const_cast<unsigned char*>(nv12_buffer->DataUV()); 777 frame_for_encode_->planes[AOM_PLANE_V] = nullptr; 778 frame_for_encode_->stride[AOM_PLANE_Y] = nv12_buffer->StrideY(); 779 frame_for_encode_->stride[AOM_PLANE_U] = nv12_buffer->StrideUV(); 780 frame_for_encode_->stride[AOM_PLANE_V] = 0; 781 break; 782 } 783 default: 784 return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE; 785 } 786 787 const uint32_t duration = kVideoPayloadTypeFrequency / framerate_fps_; 788 timestamp_ += duration; 789 790 const size_t num_spatial_layers = 791 svc_params_ ? svc_params_->number_spatial_layers : 1; 792 auto next_layer_frame = layer_frames.begin(); 793 std::vector<std::pair<EncodedImage, CodecSpecificInfo>> encoded_images; 794 for (size_t i = 0; i < num_spatial_layers; ++i) { 795 // The libaom AV1 encoder requires that `aom_codec_encode` is called for 796 // every spatial layer, even if the configured bitrate for that layer is 797 // zero. For zero bitrate spatial layers no frames will be produced. 798 std::optional<ScalableVideoController::LayerFrameConfig> 799 non_encoded_layer_frame; 800 ScalableVideoController::LayerFrameConfig* layer_frame; 801 if (next_layer_frame != layer_frames.end() && 802 next_layer_frame->SpatialId() == static_cast<int>(i)) { 803 layer_frame = &*next_layer_frame; 804 ++next_layer_frame; 805 } else { 806 // For layers that are not encoded only the spatial id matters. 807 non_encoded_layer_frame.emplace().S(i); 808 layer_frame = &*non_encoded_layer_frame; 809 } 810 const bool end_of_picture = (next_layer_frame == layer_frames.end()); 811 812 aom_enc_frame_flags_t flags = 813 layer_frame->IsKeyframe() ? AOM_EFLAG_FORCE_KF : 0; 814 #if defined(WEBRTC_ENCODER_PSNR_STATS) && defined(AOM_EFLAG_CALCULATE_PSNR) 815 if (calculate_psnr_ && psnr_frame_sampler_.ShouldBeSampled(frame)) { 816 flags |= AOM_EFLAG_CALCULATE_PSNR; 817 } 818 #endif 819 820 if (SvcEnabled()) { 821 SetSvcLayerId(*layer_frame); 822 SetSvcRefFrameConfig(*layer_frame); 823 } 824 825 EncodeResult result = DoEncode(duration, flags, layer_frame); 826 if (aom_codec_err_t* status = std::get_if<aom_codec_err_t>(&result); 827 status != nullptr) { 828 if (*status == AOM_CODEC_OK) { 829 // AOM_CODEC_OK means success with no image, so do nothing. 830 continue; 831 } else { 832 RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::Encode returned " << status 833 << " on aom_codec_encode."; 834 return WEBRTC_VIDEO_CODEC_ERROR; 835 } 836 } 837 838 if (non_encoded_layer_frame) { 839 continue; 840 } 841 842 RTC_DCHECK(std::holds_alternative<EncodedImage>(result)); 843 EncodedImage encoded_image = std::get<EncodedImage>(std::move(result)); 844 845 RTC_DCHECK_GT(encoded_image.size(), 0u); 846 PopulateEncodedImageFromVideoFrame(frame, encoded_image); 847 CodecSpecificInfo codec_specifics = 848 CreateCodecSpecificInfo(encoded_image, *layer_frame, end_of_picture); 849 850 encoded_images.emplace_back(std::move(encoded_image), 851 std::move(codec_specifics)); 852 } 853 854 if (!encoded_images.empty()) { 855 encoded_images.back().second.end_of_picture = true; 856 } 857 for (auto& [encoded_image, codec_specifics] : encoded_images) { 858 encoded_image_callback_->OnEncodedImage(encoded_image, &codec_specifics); 859 if (encoded_image.SpatialIndex().has_value()) { 860 last_encoded_timestamp_by_sid_[*encoded_image.SpatialIndex()] = 861 frame.rtp_timestamp(); 862 } 863 } 864 865 return WEBRTC_VIDEO_CODEC_OK; 866 } 867 868 LibaomAv1Encoder::EncodeResult LibaomAv1Encoder::DoEncode( 869 uint32_t duration, 870 aom_enc_frame_flags_t flags, 871 ScalableVideoController::LayerFrameConfig* layer_frame) { 872 // Encode a frame. The presentation timestamp `pts` should not use real 873 // timestamps from frames or the wall clock, as that can cause the rate 874 // controller to misbehave. 875 aom_codec_err_t ret = 876 aom_codec_encode(&ctx_, frame_for_encode_, timestamp_, duration, flags); 877 if (ret != AOM_CODEC_OK) { 878 return ret; 879 } 880 881 // Get encoded image data. 882 aom_codec_iter_t iter = nullptr; 883 int data_pkt_count = 0; 884 EncodedImage encoded_image; 885 const aom_codec_cx_pkt_t* pkt = nullptr; 886 while ((pkt = aom_codec_get_cx_data(&ctx_, &iter)) != nullptr) { 887 if (pkt->kind == AOM_CODEC_CX_FRAME_PKT && pkt->data.frame.sz > 0) { 888 if (data_pkt_count > 0) { 889 RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::Encoder returned more than " 890 "one data packet for an input video frame."; 891 Release(); 892 return AOM_CODEC_ERROR; 893 } 894 encoded_image.SetEncodedData(EncodedImageBuffer::Create( 895 /*data=*/static_cast<const uint8_t*>(pkt->data.frame.buf), 896 /*size=*/pkt->data.frame.sz)); 897 898 if ((pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0) { 899 layer_frame->Keyframe(); 900 } 901 902 encoded_image._frameType = layer_frame->IsKeyframe() 903 ? VideoFrameType::kVideoFrameKey 904 : VideoFrameType::kVideoFrameDelta; 905 906 encoded_image.content_type_ = VideoContentType::UNSPECIFIED; 907 // If encoded image width/height info are added to aom_codec_cx_pkt_t, 908 // use those values in lieu of the values in frame. 909 if (svc_params_) { 910 int n = scaling_factors_num_[layer_frame->SpatialId()]; 911 int d = scaling_factors_den_[layer_frame->SpatialId()]; 912 encoded_image._encodedWidth = encoder_settings_.width * n / d; 913 encoded_image._encodedHeight = encoder_settings_.height * n / d; 914 encoded_image.SetSpatialIndex(layer_frame->SpatialId()); 915 encoded_image.SetTemporalIndex(layer_frame->TemporalId()); 916 } else { 917 encoded_image._encodedWidth = cfg_.g_w; 918 encoded_image._encodedHeight = cfg_.g_h; 919 } 920 encoded_image.timing_.flags = VideoSendTiming::kInvalid; 921 922 if (!SetEncoderControlParameters(AOME_GET_LAST_QUANTIZER, 923 &encoded_image.qp_)) { 924 RTC_LOG(LS_WARNING) << "Unable to fetch QP for frame."; 925 return AOM_CODEC_ERROR; 926 } 927 928 ++data_pkt_count; 929 } else if (pkt->kind == AOM_CODEC_PSNR_PKT) { 930 // PSNR index: 0: total, 1: Y, 2: U, 3: V 931 encoded_image.set_psnr(EncodedImage::Psnr({.y = pkt->data.psnr.psnr[1], 932 .u = pkt->data.psnr.psnr[2], 933 .v = pkt->data.psnr.psnr[3]})); 934 } 935 } 936 937 if (encoded_image.size() == 0) { 938 // Encode success, but no image produced. 939 return AOM_CODEC_OK; 940 } 941 942 return encoded_image; 943 } 944 945 CodecSpecificInfo LibaomAv1Encoder::CreateCodecSpecificInfo( 946 const EncodedImage& image, 947 const ScalableVideoController::LayerFrameConfig& layer_frame, 948 bool end_of_picture) { 949 CodecSpecificInfo codec_specific_info; 950 codec_specific_info.codecType = kVideoCodecAV1; 951 codec_specific_info.end_of_picture = end_of_picture; 952 codec_specific_info.scalability_mode = scalability_mode_; 953 bool is_keyframe = layer_frame.IsKeyframe(); 954 codec_specific_info.generic_frame_info = 955 svc_controller_->OnEncodeDone(layer_frame); 956 if (is_keyframe && codec_specific_info.generic_frame_info) { 957 codec_specific_info.template_structure = 958 svc_controller_->DependencyStructure(); 959 auto& resolutions = codec_specific_info.template_structure->resolutions; 960 if (SvcEnabled()) { 961 resolutions.resize(svc_params_->number_spatial_layers); 962 for (int sid = 0; sid < svc_params_->number_spatial_layers; ++sid) { 963 int n = scaling_factors_num_[sid]; 964 int d = scaling_factors_den_[sid]; 965 resolutions[sid] = RenderResolution(encoder_settings_.width * n / d, 966 encoder_settings_.height * n / d); 967 } 968 } else { 969 resolutions = {RenderResolution(cfg_.g_w, cfg_.g_h)}; 970 } 971 } 972 return codec_specific_info; 973 } 974 975 void LibaomAv1Encoder::SetRates(const RateControlParameters& parameters) { 976 if (!inited_) { 977 RTC_LOG(LS_WARNING) << "SetRates() while encoder is not initialized"; 978 return; 979 } 980 if (parameters.framerate_fps < kMinFrameRateFps) { 981 RTC_LOG(LS_WARNING) << "Unsupported framerate (must be >= " 982 << kMinFrameRateFps 983 << " ): " << parameters.framerate_fps; 984 return; 985 } 986 if (parameters.bitrate.get_sum_bps() == 0) { 987 RTC_LOG(LS_WARNING) << "Attempt to set target bit rate to zero"; 988 return; 989 } 990 991 // The bitrates caluclated internally in libaom when `AV1E_SET_SVC_PARAMS` is 992 // called depends on the currently configured `rc_target_bitrate`. If the 993 // total target bitrate is not updated first a division by zero could happen. 994 svc_controller_->OnRatesUpdated(parameters.bitrate); 995 cfg_.rc_target_bitrate = parameters.bitrate.get_sum_kbps(); 996 997 if (SvcEnabled()) { 998 for (int sid = 0; sid < svc_params_->number_spatial_layers; ++sid) { 999 // libaom bitrate for spatial id S and temporal id T means bitrate 1000 // of frames with spatial_id=S and temporal_id<=T. 1001 for (int tid = 0; tid < svc_params_->number_temporal_layers; ++tid) { 1002 int layer_index = sid * svc_params_->number_temporal_layers + tid; 1003 // `svc_params_->layer_target_bitrate` expects bitrate in kbps. 1004 svc_params_->layer_target_bitrate[layer_index] = 1005 parameters.bitrate.GetTemporalLayerSum(sid, tid) / 1000; 1006 } 1007 } 1008 AdjustScalingFactorsForTopActiveLayer(); 1009 SetEncoderControlParameters(AV1E_SET_SVC_PARAMS, &*svc_params_); 1010 } 1011 1012 // AdjustScalingFactorsForTopActiveLayer() may update `cfg_`. 1013 aom_codec_err_t error_code = aom_codec_enc_config_set(&ctx_, &cfg_); 1014 if (error_code != AOM_CODEC_OK) { 1015 RTC_LOG(LS_WARNING) << "Error configuring encoder, error code: " 1016 << error_code; 1017 } 1018 1019 framerate_fps_ = parameters.framerate_fps; 1020 1021 rates_configured_ = true; 1022 } 1023 1024 VideoEncoder::EncoderInfo LibaomAv1Encoder::GetEncoderInfo() const { 1025 EncoderInfo info; 1026 info.supports_native_handle = false; 1027 info.implementation_name = "libaom"; 1028 info.has_trusted_rate_controller = true; 1029 info.is_hardware_accelerated = false; 1030 info.scaling_settings = 1031 (inited_ && !encoder_settings_.AV1().automatic_resize_on) 1032 ? VideoEncoder::ScalingSettings::kOff 1033 : VideoEncoder::ScalingSettings(kLowQindex, kHighQindex); 1034 info.preferred_pixel_formats = {VideoFrameBuffer::Type::kI420, 1035 VideoFrameBuffer::Type::kNV12}; 1036 if (inited_) { 1037 info.mapped_resolution = VideoEncoder::Resolution(cfg_.g_w, cfg_.g_h); 1038 } 1039 if (SvcEnabled()) { 1040 for (int sid = 0; sid < svc_params_->number_spatial_layers; ++sid) { 1041 info.fps_allocation[sid].resize(svc_params_->number_temporal_layers); 1042 for (int tid = 0; tid < svc_params_->number_temporal_layers; ++tid) { 1043 info.fps_allocation[sid][tid] = EncoderInfo::kMaxFramerateFraction / 1044 svc_params_->framerate_factor[tid]; 1045 } 1046 } 1047 } 1048 if (!encoder_info_override_.resolution_bitrate_limits().empty()) { 1049 info.resolution_bitrate_limits = 1050 encoder_info_override_.resolution_bitrate_limits(); 1051 } 1052 1053 info.min_qp = kMinQindex; 1054 return info; 1055 } 1056 1057 } // namespace 1058 1059 absl_nonnull std::unique_ptr<VideoEncoder> CreateLibaomAv1Encoder( 1060 const Environment& env, 1061 LibaomAv1EncoderSettings settings) { 1062 return std::make_unique<LibaomAv1Encoder>(env, std::move(settings)); 1063 } 1064 1065 } // namespace webrtc