With Svc controller do not produce frame that will be dropped anyway

This cover scenario where target bitrate is changed in a middle of
of group of frame after spatial upswitch.
This change should avoid wasting encoder resources to produce those
frames, reduce number of errors
"Encoder produced a frame for layer that wasn't requested"

Bug: webrtc:11999
Change-Id: I06045259b1cee2c21bfdabbafff3892b57c82a84
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/230543
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34969}
This commit is contained in:
Danil Chapovalov
2021-09-10 12:30:09 +02:00
committed by WebRTC LUCI CQ
parent 5d3bf6ae2a
commit 32b917ac41
2 changed files with 61 additions and 4 deletions

View File

@ -399,22 +399,72 @@ bool LibvpxVp9Encoder::SetSvcRates(
} }
if (svc_controller_) { if (svc_controller_) {
VideoBitrateAllocation allocation;
for (int sid = 0; sid < num_spatial_layers_; ++sid) { for (int sid = 0; sid < num_spatial_layers_; ++sid) {
for (int tid = 0; tid < num_temporal_layers_; ++tid) { for (int tid = 0; tid < num_temporal_layers_; ++tid) {
allocation.SetBitrate( current_bitrate_allocation_.SetBitrate(
sid, tid, sid, tid,
config_->layer_target_bitrate[sid * num_temporal_layers_ + tid] * config_->layer_target_bitrate[sid * num_temporal_layers_ + tid] *
1000); 1000);
} }
} }
svc_controller_->OnRatesUpdated(allocation); svc_controller_->OnRatesUpdated(current_bitrate_allocation_);
} } else {
current_bitrate_allocation_ = bitrate_allocation; current_bitrate_allocation_ = bitrate_allocation;
}
config_changed_ = true; config_changed_ = true;
return true; return true;
} }
void LibvpxVp9Encoder::DisableSpatialLayer(int sid) {
RTC_DCHECK_LT(sid, num_spatial_layers_);
if (config_->ss_target_bitrate[sid] == 0) {
return;
}
config_->ss_target_bitrate[sid] = 0;
for (int tid = 0; tid < num_temporal_layers_; ++tid) {
config_->layer_target_bitrate[sid * num_temporal_layers_ + tid] = 0;
}
config_changed_ = true;
}
void LibvpxVp9Encoder::EnableSpatialLayer(int sid) {
RTC_DCHECK_LT(sid, num_spatial_layers_);
if (config_->ss_target_bitrate[sid] > 0) {
return;
}
for (int tid = 0; tid < num_temporal_layers_; ++tid) {
config_->layer_target_bitrate[sid * num_temporal_layers_ + tid] =
current_bitrate_allocation_.GetBitrate(sid, tid) / 1000;
}
config_->ss_target_bitrate[sid] =
current_bitrate_allocation_.GetSpatialLayerSum(sid) / 1000;
RTC_DCHECK_GT(config_->ss_target_bitrate[sid], 0);
config_changed_ = true;
}
void LibvpxVp9Encoder::SetActiveSpatialLayers() {
// Svc controller may decide to skip a frame at certain spatial layer even
// when bitrate for it is non-zero, however libvpx uses configured bitrate as
// a signal which layers should be produced.
RTC_DCHECK(svc_controller_);
RTC_DCHECK(!layer_frames_.empty());
RTC_DCHECK(absl::c_is_sorted(
layer_frames_, [](const ScalableVideoController::LayerFrameConfig& lhs,
const ScalableVideoController::LayerFrameConfig& rhs) {
return lhs.SpatialId() < rhs.SpatialId();
}));
auto frame_it = layer_frames_.begin();
for (int sid = 0; sid < num_spatial_layers_; ++sid) {
if (frame_it != layer_frames_.end() && frame_it->SpatialId() == sid) {
EnableSpatialLayer(sid);
++frame_it;
} else {
DisableSpatialLayer(sid);
}
}
}
void LibvpxVp9Encoder::SetRates(const RateControlParameters& parameters) { void LibvpxVp9Encoder::SetRates(const RateControlParameters& parameters) {
if (!inited_) { if (!inited_) {
RTC_LOG(LS_WARNING) << "SetRates() calll while uninitialzied."; RTC_LOG(LS_WARNING) << "SetRates() calll while uninitialzied.";
@ -978,6 +1028,7 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
layer_id.temporal_layer_id_per_spatial[layer.SpatialId()] = layer_id.temporal_layer_id_per_spatial[layer.SpatialId()] =
layer.TemporalId(); layer.TemporalId();
} }
SetActiveSpatialLayers();
} }
if (is_svc_ && performance_flags_.use_per_layer_speed) { if (is_svc_ && performance_flags_.use_per_layer_speed) {

View File

@ -82,6 +82,12 @@ class LibvpxVp9Encoder : public VP9Encoder {
bool ExplicitlyConfiguredSpatialLayers() const; bool ExplicitlyConfiguredSpatialLayers() const;
bool SetSvcRates(const VideoBitrateAllocation& bitrate_allocation); bool SetSvcRates(const VideoBitrateAllocation& bitrate_allocation);
// Configures which spatial layers libvpx should encode according to
// configuration provided by svc_controller_.
void EnableSpatialLayer(int sid);
void DisableSpatialLayer(int sid);
void SetActiveSpatialLayers();
void GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt); void GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt);
// Callback function for outputting packets per spatial layer. // Callback function for outputting packets per spatial layer.