Fix for VP9 K-SVC video freeze frame when send bandwidth is restricted.

Added distinction between number of configured and number of actively
encoded spatial layers and include number of actively encoded spatial
layers in ssData.  Modified layer_filtering_transport.cc test to
parse from the RTP header and use the number of actively encoded
spatial layers for filtering spatial video layers.

Bug: webrtc:9425
Change-Id: Ic9f8895ab08b0626f9bb53a75ec33d8e7eb8706e
Reviewed-on: https://webrtc-review.googlesource.com/84243
Commit-Queue: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23716}
This commit is contained in:
“Michael 2018-06-21 11:07:21 -05:00 committed by Commit Bot
parent 43800f95bf
commit 23c5a99381
5 changed files with 34 additions and 14 deletions

View File

@ -310,7 +310,7 @@ TEST_F(TestVp9Impl, EndOfPicture) {
encoder_->Encode(*NextInputFrame(), nullptr, nullptr));
ASSERT_TRUE(WaitForEncodedFrames(&frames, &codec_specific));
EXPECT_EQ(codec_specific[0].codecSpecific.VP9.spatial_idx, 0);
EXPECT_EQ(codec_specific[0].codecSpecific.VP9.spatial_idx, kNoSpatialIdx);
EXPECT_TRUE(codec_specific[0].codecSpecific.VP9.end_of_picture);
}

View File

@ -134,6 +134,12 @@ bool VP9EncoderImpl::SetSvcRates(
config_->rc_target_bitrate = bitrate_allocation.get_sum_kbps();
num_active_spatial_layers_ = 0;
for (i = 0; i < num_spatial_layers_; ++i)
num_active_spatial_layers_ += bitrate_allocation.IsSpatialLayerUsed(i);
RTC_DCHECK_GT(num_active_spatial_layers_, 0);
RTC_DCHECK_LE(num_active_spatial_layers_, num_spatial_layers_);
if (ExplicitlyConfiguredSpatialLayers()) {
for (size_t sl_idx = 0; sl_idx < num_spatial_layers_; ++sl_idx) {
const bool was_layer_enabled = (config_->ss_target_bitrate[sl_idx] > 0);
@ -157,8 +163,7 @@ bool VP9EncoderImpl::SetSvcRates(
} else {
float rate_ratio[VPX_MAX_LAYERS] = {0};
float total = 0;
for (i = 0; i < num_spatial_layers_; ++i) {
for (i = 0; i < num_active_spatial_layers_; ++i) {
if (svc_params_.scaling_factor_num[i] <= 0 ||
svc_params_.scaling_factor_den[i] <= 0) {
RTC_LOG(LS_ERROR) << "Scaling factors not specified!";
@ -169,7 +174,7 @@ bool VP9EncoderImpl::SetSvcRates(
total += rate_ratio[i];
}
for (i = 0; i < num_spatial_layers_; ++i) {
for (i = 0; i < num_active_spatial_layers_; ++i) {
config_->ss_target_bitrate[i] = static_cast<unsigned int>(
config_->rc_target_bitrate * rate_ratio[i] / total);
if (num_temporal_layers_ == 1) {
@ -645,14 +650,14 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
RTC_CHECK_GT(num_temporal_layers_, 0);
RTC_CHECK_GT(num_spatial_layers_, 0);
RTC_CHECK_GT(num_active_spatial_layers_, 0);
if (num_temporal_layers_ == 1) {
RTC_CHECK_EQ(layer_id.temporal_layer_id, 0);
vp9_info->temporal_idx = kNoTemporalIdx;
} else {
vp9_info->temporal_idx = layer_id.temporal_layer_id;
}
if (num_spatial_layers_ == 1) {
if (num_active_spatial_layers_ == 1) {
RTC_CHECK_EQ(layer_id.spatial_layer_id, 0);
vp9_info->spatial_idx = kNoSpatialIdx;
} else {
@ -686,13 +691,13 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
first_frame_in_picture ? false : is_inter_layer_pred_allowed;
const bool is_last_layer =
(layer_id.spatial_layer_id + 1 == num_spatial_layers_);
(layer_id.spatial_layer_id + 1 == num_active_spatial_layers_);
vp9_info->non_ref_for_inter_layer_pred =
is_last_layer ? true : !is_inter_layer_pred_allowed;
// Always populate this, so that the packetizer can properly set the marker
// bit.
vp9_info->num_spatial_layers = num_spatial_layers_;
vp9_info->num_spatial_layers = num_active_spatial_layers_;
RTC_DCHECK(!vp9_info->flexible_mode);
@ -710,11 +715,9 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
vp9_info->inter_pic_predicted = (!is_key_pic && vp9_info->num_ref_pics > 0);
vp9_info->num_spatial_layers = num_spatial_layers_;
if (vp9_info->ss_data_available) {
vp9_info->spatial_layer_resolution_present = true;
for (size_t i = 0; i < vp9_info->num_spatial_layers; ++i) {
for (size_t i = 0; i < num_active_spatial_layers_; ++i) {
vp9_info->width[i] = codec_.width * svc_params_.scaling_factor_num[i] /
svc_params_.scaling_factor_den[i];
vp9_info->height[i] = codec_.height * svc_params_.scaling_factor_num[i] /

View File

@ -108,7 +108,8 @@ class VP9EncoderImpl : public VP9Encoder {
bool force_key_frame_;
size_t pics_since_key_;
uint8_t num_temporal_layers_;
uint8_t num_spatial_layers_;
uint8_t num_spatial_layers_; // Number of configured SLs
uint8_t num_active_spatial_layers_; // Number of actively encoded SLs
bool is_svc_;
InterLayerPredMode inter_layer_pred_;

View File

@ -145,7 +145,20 @@ bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
is_vp8 ? false
: parsed_payload.type.Video.codecHeader.VP9
.non_ref_for_inter_layer_pred;
if (selected_sl_ >= 0 && spatial_idx == selected_sl_ &&
// The number of spatial layers is sent in ssData, which is included only
// in the first packet of the first spatial layer of a key frame.
if (!parsed_payload.type.Video.codecHeader.VP9.inter_pic_predicted &&
parsed_payload.type.Video.codecHeader.VP9.beginning_of_frame == 1 &&
spatial_idx == 0) {
num_active_spatial_layers_ =
parsed_payload.type.Video.codecHeader.VP9.num_spatial_layers;
} else if (spatial_idx == kNoSpatialIdx)
num_active_spatial_layers_ = 1;
RTC_CHECK_GT(num_active_spatial_layers_, 0);
if (selected_sl_ >= 0 &&
spatial_idx ==
std::min(num_active_spatial_layers_ - 1, selected_sl_) &&
parsed_payload.type.Video.codecHeader.VP9.end_of_frame) {
// This layer is now the last in the superframe.
set_marker_bit = true;
@ -162,7 +175,9 @@ bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
// needed for decoding of target spatial layer.
const bool lower_non_ref_spatial_layer =
(selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
spatial_idx < selected_sl_ && non_ref_for_inter_layer_pred);
spatial_idx <
std::min(num_active_spatial_layers_ - 1, selected_sl_) &&
non_ref_for_inter_layer_pred);
if (higher_temporal_layer || higher_spatial_layer ||
lower_non_ref_spatial_layer) {

View File

@ -73,6 +73,7 @@ class LayerFilteringTransport : public test::DirectTransport {
const int selected_tl_;
const int selected_sl_;
bool discarded_last_packet_;
int num_active_spatial_layers_;
const uint32_t ssrc_to_filter_min_;
const uint32_t ssrc_to_filter_max_;
};