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:
parent
43800f95bf
commit
23c5a99381
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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] /
|
||||
|
||||
@ -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_;
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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_;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user