32
32
#include " modules/video_coding/svc/scalable_video_controller_no_layering.h"
33
33
#include " modules/video_coding/utility/vp9_uncompressed_header_parser.h"
34
34
#include " rtc_base/checks.h"
35
+ #include " rtc_base/experiments/field_trial_list.h"
35
36
#include " rtc_base/experiments/field_trial_parser.h"
36
37
#include " rtc_base/experiments/rate_control_settings.h"
37
38
#include " rtc_base/keep_ref_until_done.h"
@@ -65,20 +66,6 @@ const int kMaxAllowedPidDiff = 30;
65
66
constexpr int kLowVp9QpThreshold = 149 ;
66
67
constexpr int kHighVp9QpThreshold = 205 ;
67
68
68
- // Only positive speeds, range for real-time coding currently is: 5 - 8.
69
- // Lower means slower/better quality, higher means fastest/lower quality.
70
- int GetCpuSpeed (int width, int height) {
71
- #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID)
72
- return 8 ;
73
- #else
74
- // For smaller resolutions, use lower speed setting (get some coding gain at
75
- // the cost of increased encoding complexity).
76
- if (width * height <= 352 * 288 )
77
- return 5 ;
78
- else
79
- return 7 ;
80
- #endif
81
- }
82
69
// Helper class for extracting VP9 colorspace.
83
70
ColorSpace ExtractVP9ColorSpace (vpx_color_space_t space_t ,
84
71
vpx_color_range_t range_t ,
@@ -281,7 +268,6 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec,
281
268
ParseSdpForVP9Profile (codec.params).value_or(VP9Profile::kProfile0 )),
282
269
inited_(false ),
283
270
timestamp_(0 ),
284
- cpu_speed_(3 ),
285
271
rc_max_intra_target_(0 ),
286
272
encoder_(nullptr ),
287
273
config_(nullptr ),
@@ -318,7 +304,7 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec,
318
304
external_ref_ctrl_(
319
305
!absl::StartsWith(trials.Lookup(" WebRTC-Vp9ExternalRefCtrl" ),
320
306
"Disabled")),
321
- per_layer_speed_(ParsePerLayerSpeed (trials)),
307
+ performance_flags_(ParsePerformanceFlagsFromTrials (trials)),
322
308
num_steady_state_frames_(0 ),
323
309
config_changed_(true ) {
324
310
codec_ = {};
@@ -455,8 +441,6 @@ bool VP9EncoderImpl::SetSvcRates(
455
441
first_active_layer_ = 0 ;
456
442
bool seen_active_layer = false ;
457
443
bool expect_no_more_active_layers = false ;
458
- int highest_active_width = 0 ;
459
- int highest_active_height = 0 ;
460
444
for (int i = 0 ; i < num_spatial_layers_; ++i) {
461
445
if (config_->ss_target_bitrate [i] > 0 ) {
462
446
RTC_DCHECK (!expect_no_more_active_layers) << " Only middle layer is "
@@ -466,12 +450,6 @@ bool VP9EncoderImpl::SetSvcRates(
466
450
}
467
451
num_active_spatial_layers_ = i + 1 ;
468
452
seen_active_layer = true ;
469
- highest_active_width =
470
- (svc_params_.scaling_factor_num [i] * config_->g_w ) /
471
- svc_params_.scaling_factor_den [i];
472
- highest_active_height =
473
- (svc_params_.scaling_factor_num [i] * config_->g_h ) /
474
- svc_params_.scaling_factor_den [i];
475
453
} else {
476
454
expect_no_more_active_layers = seen_active_layer;
477
455
}
@@ -499,7 +477,6 @@ bool VP9EncoderImpl::SetSvcRates(
499
477
svc_controller_->OnRatesUpdated (allocation);
500
478
}
501
479
current_bitrate_allocation_ = bitrate_allocation;
502
- cpu_speed_ = GetCpuSpeed (highest_active_width, highest_active_height);
503
480
config_changed_ = true ;
504
481
return true ;
505
482
}
@@ -570,6 +547,7 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
570
547
if (&codec_ != inst) {
571
548
codec_ = *inst;
572
549
}
550
+ memset (&svc_params_, 0 , sizeof (vpx_svc_extra_cfg_t ));
573
551
574
552
force_key_frame_ = true ;
575
553
pics_since_key_ = 0 ;
@@ -665,8 +643,6 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
665
643
config_->g_threads =
666
644
NumberOfThreads (config_->g_w , config_->g_h , settings.number_of_cores );
667
645
668
- cpu_speed_ = GetCpuSpeed (config_->g_w , config_->g_h );
669
-
670
646
is_flexible_mode_ = inst->VP9 ().flexibleMode ;
671
647
672
648
inter_layer_pred_ = inst->VP9 ().interLayerPred ;
@@ -827,22 +803,18 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) {
827
803
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
828
804
}
829
805
830
- if (per_layer_speed_.enabled ) {
831
- for (int i = 0 ; i < num_spatial_layers_; ++i) {
832
- if (codec_.spatialLayers [i].active ) {
833
- continue ;
834
- }
835
-
836
- if (per_layer_speed_.layers [i] != -1 ) {
837
- svc_params_.speed_per_layer [i] = per_layer_speed_.layers [i];
838
- } else {
839
- svc_params_.speed_per_layer [i] = GetCpuSpeed (
840
- codec_.spatialLayers [i].width , codec_.spatialLayers [i].height );
841
- }
806
+ UpdatePerformanceFlags ();
807
+ RTC_DCHECK_EQ (performance_flags_by_spatial_index_.size (),
808
+ static_cast <size_t >(num_spatial_layers_));
809
+ if (performance_flags_.use_per_layer_speed ) {
810
+ for (int si = 0 ; si < num_spatial_layers_; ++si) {
811
+ svc_params_.speed_per_layer [si] =
812
+ performance_flags_by_spatial_index_[si].base_layer_speed ;
813
+ svc_params_.loopfilter_ctrl [si] =
814
+ performance_flags_by_spatial_index_[si].deblock_mode ;
842
815
}
843
816
}
844
817
845
- vpx_codec_control (encoder_, VP8E_SET_CPUUSED, cpu_speed_);
846
818
vpx_codec_control (encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT,
847
819
rc_max_intra_target_);
848
820
vpx_codec_control (encoder_, VP9E_SET_AQ_MODE,
@@ -855,6 +827,11 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) {
855
827
vpx_codec_control (encoder_, VP9E_SET_SVC, 1 );
856
828
vpx_codec_control (encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
857
829
}
830
+ if (!performance_flags_.use_per_layer_speed ) {
831
+ vpx_codec_control (
832
+ encoder_, VP8E_SET_CPUUSED,
833
+ performance_flags_by_spatial_index_.rbegin ()->base_layer_speed );
834
+ }
858
835
859
836
if (num_spatial_layers_ > 1 ) {
860
837
switch (inter_layer_pred_) {
@@ -1068,6 +1045,24 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
1068
1045
}
1069
1046
}
1070
1047
1048
+ if (is_svc_ && performance_flags_.use_per_layer_speed ) {
1049
+ // Update speed settings that might depend on temporal index.
1050
+ bool speed_updated = false ;
1051
+ for (int sl_idx = 0 ; sl_idx < num_spatial_layers_; ++sl_idx) {
1052
+ const int target_speed =
1053
+ layer_id.temporal_layer_id_per_spatial [sl_idx] == 0
1054
+ ? performance_flags_by_spatial_index_[sl_idx].base_layer_speed
1055
+ : performance_flags_by_spatial_index_[sl_idx].high_layer_speed ;
1056
+ if (svc_params_.speed_per_layer [sl_idx] != target_speed) {
1057
+ svc_params_.speed_per_layer [sl_idx] = target_speed;
1058
+ speed_updated = true ;
1059
+ }
1060
+ }
1061
+ if (speed_updated) {
1062
+ vpx_codec_control (encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
1063
+ }
1064
+ }
1065
+
1071
1066
vpx_codec_control (encoder_, VP9E_SET_SVC_LAYER_ID, &layer_id);
1072
1067
1073
1068
if (num_spatial_layers_ > 1 ) {
@@ -1080,7 +1075,25 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
1080
1075
if (vpx_codec_enc_config_set (encoder_, config_)) {
1081
1076
return WEBRTC_VIDEO_CODEC_ERROR;
1082
1077
}
1083
- vpx_codec_control (encoder_, VP8E_SET_CPUUSED, cpu_speed_);
1078
+
1079
+ if (!performance_flags_.use_per_layer_speed ) {
1080
+ // Not setting individual speeds per layer, find the highest active
1081
+ // resolution instead and base the speed on that.
1082
+ for (int i = num_spatial_layers_ - 1 ; i >= 0 ; --i) {
1083
+ if (config_->ss_target_bitrate [i] > 0 ) {
1084
+ int width = (svc_params_.scaling_factor_num [i] * config_->g_w ) /
1085
+ svc_params_.scaling_factor_den [i];
1086
+ int height = (svc_params_.scaling_factor_num [i] * config_->g_h ) /
1087
+ svc_params_.scaling_factor_den [i];
1088
+ int speed =
1089
+ std::prev (performance_flags_.settings_by_resolution .lower_bound (
1090
+ width * height))
1091
+ ->second .base_layer_speed ;
1092
+ vpx_codec_control (encoder_, VP8E_SET_CPUUSED, speed);
1093
+ break ;
1094
+ }
1095
+ }
1096
+ }
1084
1097
config_changed_ = false ;
1085
1098
}
1086
1099
@@ -1826,18 +1839,92 @@ VP9EncoderImpl::ParseQualityScalerConfig(const WebRtcKeyValueConfig& trials) {
1826
1839
return config;
1827
1840
}
1828
1841
1842
+ void VP9EncoderImpl::UpdatePerformanceFlags () {
1843
+ const auto find_speed = [&](int min_pixel_count) {
1844
+ RTC_DCHECK (!performance_flags_.settings_by_resolution .empty ());
1845
+ auto it =
1846
+ performance_flags_.settings_by_resolution .upper_bound (min_pixel_count);
1847
+ return std::prev (it)->second ;
1848
+ };
1849
+
1850
+ performance_flags_by_spatial_index_.clear ();
1851
+ if (is_svc_) {
1852
+ for (int si = 0 ; si < num_spatial_layers_; ++si) {
1853
+ performance_flags_by_spatial_index_.push_back (find_speed (
1854
+ codec_.spatialLayers [si].width * codec_.spatialLayers [si].height ));
1855
+ }
1856
+ } else {
1857
+ performance_flags_by_spatial_index_.push_back (
1858
+ find_speed (codec_.width * codec_.height ));
1859
+ }
1860
+ }
1861
+
1829
1862
// static
1830
- VP9EncoderImpl::SpeedSettings VP9EncoderImpl::ParsePerLayerSpeed (
1863
+ VP9EncoderImpl::PerformanceFlags
1864
+ VP9EncoderImpl::ParsePerformanceFlagsFromTrials (
1831
1865
const WebRtcKeyValueConfig& trials) {
1832
- FieldTrialFlag enabled (" enabled" );
1833
- FieldTrialParameter<int > speeds[kMaxSpatialLayers ]{
1834
- {" s0" , -1 }, {" s1" , -1 }, {" s2" , -1 }, {" s3" , -1 }, {" s4" , -1 }};
1835
- ParseFieldTrial (
1836
- {&enabled, &speeds[0 ], &speeds[1 ], &speeds[2 ], &speeds[3 ], &speeds[4 ]},
1837
- trials.Lookup (" WebRTC-VP9-PerLayerSpeed" ));
1838
- return SpeedSettings{enabled.Get (),
1839
- {speeds[0 ].Get (), speeds[1 ].Get (), speeds[2 ].Get (),
1840
- speeds[3 ].Get (), speeds[4 ].Get ()}};
1866
+ struct Params : public PerformanceFlags ::ParameterSet {
1867
+ int min_pixel_count = 0 ;
1868
+ };
1869
+
1870
+ FieldTrialStructList<Params> trials_list (
1871
+ {FieldTrialStructMember (" min_pixel_count" ,
1872
+ [](Params* p) { return &p->min_pixel_count ; }),
1873
+ FieldTrialStructMember (" high_layer_speed" ,
1874
+ [](Params* p) { return &p->high_layer_speed ; }),
1875
+ FieldTrialStructMember (" base_layer_speed" ,
1876
+ [](Params* p) { return &p->base_layer_speed ; }),
1877
+ FieldTrialStructMember (" deblock_mode" ,
1878
+ [](Params* p) { return &p->deblock_mode ; })},
1879
+ {});
1880
+
1881
+ FieldTrialFlag per_layer_speed (" use_per_layer_speed" );
1882
+
1883
+ ParseFieldTrial ({&trials_list, &per_layer_speed},
1884
+ trials.Lookup (" WebRTC-VP9-PerformanceFlags" ));
1885
+
1886
+ PerformanceFlags flags;
1887
+ flags.use_per_layer_speed = per_layer_speed.Get ();
1888
+
1889
+ constexpr int kMinSpeed = 1 ;
1890
+ constexpr int kMaxSpeed = 9 ;
1891
+ for (auto & f : trials_list.Get ()) {
1892
+ if (f.base_layer_speed < kMinSpeed || f.base_layer_speed > kMaxSpeed ||
1893
+ f.high_layer_speed < kMinSpeed || f.high_layer_speed > kMaxSpeed ||
1894
+ f.deblock_mode < 0 || f.deblock_mode > 2 ) {
1895
+ RTC_LOG (LS_WARNING) << " Ignoring invalid performance flags: "
1896
+ << " min_pixel_count = " << f.min_pixel_count
1897
+ << " , high_layer_speed = " << f.high_layer_speed
1898
+ << " , base_layer_speed = " << f.base_layer_speed
1899
+ << " , deblock_mode = " << f.deblock_mode ;
1900
+ continue ;
1901
+ }
1902
+ flags.settings_by_resolution [f.min_pixel_count ] = f;
1903
+ }
1904
+
1905
+ if (flags.settings_by_resolution .empty ()) {
1906
+ return GetDefaultPerformanceFlags ();
1907
+ }
1908
+
1909
+ return flags;
1910
+ }
1911
+
1912
+ // static
1913
+ VP9EncoderImpl::PerformanceFlags VP9EncoderImpl::GetDefaultPerformanceFlags () {
1914
+ PerformanceFlags flags;
1915
+ flags.use_per_layer_speed = false ;
1916
+ #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID)
1917
+ // Speed 8 on all layers for all resolutions.
1918
+ flags.settings_by_resolution [0 ] = {8 , 8 , 0 };
1919
+ #else
1920
+ // For smaller resolutions, use lower speed setting (get some coding gain at
1921
+ // the cost of increased encoding complexity).
1922
+ flags.settings_by_resolution [0 ] = {5 , 5 , 0 };
1923
+
1924
+ // Use speed 7 for QCIF and above.
1925
+ flags.settings_by_resolution [352 * 288 ] = {7 , 7 , 0 };
1926
+ #endif
1927
+ return flags;
1841
1928
}
1842
1929
1843
1930
void VP9EncoderImpl::MaybeRewrapRawWithFormat (const vpx_img_fmt fmt) {
0 commit comments