Reland "[VP9] Shift spatial layers on RTP level to always start from 0."

This reverts commit 2181228624d1be60903c4e3352629290b9c3b27a.

Reason for revert: Reland without changes as it's not the root cause.

Original change's description:
> Revert "[VP9] Shift spatial layers on RTP level to always start from 0."
> 
> This reverts commit 2e73a3d1e9298da6a010cd638f08f36abeba11e2.
> 
> Reason for revert: Fuzzer found some issues.
> 
> Original change's description:
> > [VP9] Shift spatial layers on RTP level to always start from 0.
> > 
> > This CL uses |width| and |height| in RTPVideoHeaderVP9 to pass information
> > about enabled layers from encoder to packetizer.
> > 
> > Bug: webrtc:11319
> > Change-Id: Idc1c337f8dfb3f7631506acb784d2a634b41b955
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/167724
> > Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> > Reviewed-by: Niels Moller <nisse@webrtc.org>
> > Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#30428}
> 
> TBR=danilchap@webrtc.org,ilnik@webrtc.org,nisse@webrtc.org
> 
> # Not skipping CQ checks because original CL landed > 1 day ago.
> 
> Bug: webrtc:11319
> Change-Id: I27a7e82737fa604b8ab769ce6503fa93e46f4e86
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168123
> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#30448}

TBR=danilchap@webrtc.org,ilnik@webrtc.org,nisse@webrtc.org

Change-Id: Ibcd9b6a075ee08c9402de8b0b9d99d77bf59d0ef
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:11319
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168185
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30450}
This commit is contained in:
Ilya Nikolaevskiy
2020-02-04 10:06:33 +00:00
committed by Commit Bot
parent 3fa2b80e14
commit f5d877847f
6 changed files with 91 additions and 1 deletions

View File

@ -61,6 +61,7 @@ void PopulateRtpWithCodecSpecifics(const CodecSpecificInfo& info,
info.codecSpecific.VP9.inter_layer_predicted; info.codecSpecific.VP9.inter_layer_predicted;
vp9_header.gof_idx = info.codecSpecific.VP9.gof_idx; vp9_header.gof_idx = info.codecSpecific.VP9.gof_idx;
vp9_header.num_spatial_layers = info.codecSpecific.VP9.num_spatial_layers; vp9_header.num_spatial_layers = info.codecSpecific.VP9.num_spatial_layers;
vp9_header.first_active_layer = info.codecSpecific.VP9.first_active_layer;
if (vp9_header.num_spatial_layers > 1) { if (vp9_header.num_spatial_layers > 1) {
vp9_header.spatial_idx = spatial_index.value_or(kNoSpatialIdx); vp9_header.spatial_idx = spatial_index.value_or(kNoSpatialIdx);
} else { } else {

View File

@ -280,15 +280,42 @@ bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) {
} }
return true; return true;
} }
// TODO(https://bugs.webrtc.org/11319):
// Workaround for switching off spatial layers on the fly.
// Sent layers must start from SL0 on RTP layer, but can start from any
// spatial layer because WebRTC-SVC api isn't implemented yet and
// current API to invoke SVC is not flexible enough.
RTPVideoHeaderVP9 RemoveInactiveSpatialLayers(
const RTPVideoHeaderVP9& original_header) {
RTPVideoHeaderVP9 hdr(original_header);
if (original_header.first_active_layer == 0)
return hdr;
for (size_t i = hdr.first_active_layer; i < hdr.num_spatial_layers; ++i) {
hdr.width[i - hdr.first_active_layer] = hdr.width[i];
hdr.height[i - hdr.first_active_layer] = hdr.height[i];
}
for (size_t i = hdr.num_spatial_layers - hdr.first_active_layer;
i < hdr.num_spatial_layers; ++i) {
hdr.width[i] = 0;
hdr.height[i] = 0;
}
hdr.num_spatial_layers -= hdr.first_active_layer;
hdr.spatial_idx -= hdr.first_active_layer;
hdr.first_active_layer = 0;
return hdr;
}
} // namespace } // namespace
RtpPacketizerVp9::RtpPacketizerVp9(rtc::ArrayView<const uint8_t> payload, RtpPacketizerVp9::RtpPacketizerVp9(rtc::ArrayView<const uint8_t> payload,
PayloadSizeLimits limits, PayloadSizeLimits limits,
const RTPVideoHeaderVP9& hdr) const RTPVideoHeaderVP9& hdr)
: hdr_(hdr), : hdr_(RemoveInactiveSpatialLayers(hdr)),
header_size_(PayloadDescriptorLengthMinusSsData(hdr_)), header_size_(PayloadDescriptorLengthMinusSsData(hdr_)),
first_packet_extra_header_size_(SsDataLength(hdr_)), first_packet_extra_header_size_(SsDataLength(hdr_)),
remaining_payload_(payload) { remaining_payload_(payload) {
RTC_DCHECK_EQ(hdr_.first_active_layer, 0);
limits.max_payload_len -= header_size_; limits.max_payload_len -= header_size_;
limits.first_packet_reduction_len += first_packet_extra_header_size_; limits.first_packet_reduction_len += first_packet_extra_header_size_;
limits.single_packet_reduction_len += first_packet_extra_header_size_; limits.single_packet_reduction_len += first_packet_extra_header_size_;

View File

@ -169,6 +169,21 @@ class RtpPacketizerVp9Test : public ::testing::Test {
expected_.ss_data_available = false; expected_.ss_data_available = false;
} }
} }
void CreateParseAndCheckPacketsLayers(size_t num_spatial_layers,
size_t expected_layer) {
ASSERT_TRUE(packetizer_ != nullptr);
for (size_t i = 0; i < num_packets_; ++i) {
EXPECT_TRUE(packetizer_->NextPacket(&packet_));
RTPVideoHeader video_header;
VideoRtpDepacketizerVp9::ParseRtpPayload(packet_.payload(),
&video_header);
const auto& vp9_header =
absl::get<RTPVideoHeaderVP9>(video_header.video_type_header);
EXPECT_EQ(vp9_header.spatial_idx, expected_layer);
EXPECT_EQ(vp9_header.num_spatial_layers, num_spatial_layers);
}
}
}; };
TEST_F(RtpPacketizerVp9Test, TestEqualSizedMode_OnePacket) { TEST_F(RtpPacketizerVp9Test, TestEqualSizedMode_OnePacket) {
@ -546,5 +561,48 @@ TEST_F(RtpPacketizerVp9Test, TestNonRefForInterLayerPred) {
CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes); CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes);
} }
TEST_F(RtpPacketizerVp9Test,
ShiftsSpatialLayersTowardZeroWhenFirstLayersAreDisabled) {
const size_t kFrameSize = 25;
const size_t kPacketSize = 1024;
expected_.width[0] = 0;
expected_.height[0] = 0;
expected_.width[1] = 640;
expected_.height[1] = 360;
expected_.width[2] = 1280;
expected_.height[2] = 720;
expected_.num_spatial_layers = 3;
expected_.first_active_layer = 1;
expected_.ss_data_available = true;
expected_.spatial_layer_resolution_present = true;
expected_.gof.num_frames_in_gof = 3;
expected_.gof.temporal_idx[0] = 0;
expected_.gof.temporal_idx[1] = 1;
expected_.gof.temporal_idx[2] = 2;
expected_.gof.temporal_up_switch[0] = true;
expected_.gof.temporal_up_switch[1] = true;
expected_.gof.temporal_up_switch[2] = false;
expected_.gof.num_ref_pics[0] = 0;
expected_.gof.num_ref_pics[1] = 3;
expected_.gof.num_ref_pics[2] = 2;
expected_.gof.pid_diff[1][0] = 5;
expected_.gof.pid_diff[1][1] = 6;
expected_.gof.pid_diff[1][2] = 7;
expected_.gof.pid_diff[2][0] = 8;
expected_.gof.pid_diff[2][1] = 9;
expected_.spatial_idx = 1;
Init(kFrameSize, kPacketSize);
CreateParseAndCheckPacketsLayers(/*num_spatial_layers=*/2,
/*expected_layer=*/0);
// Now check for SL 2;
expected_.spatial_idx = 2;
Init(kFrameSize, kPacketSize);
CreateParseAndCheckPacketsLayers(/*num_spatial_layers=*/2,
/*expected_layer=*/1);
}
} // namespace } // namespace
} // namespace webrtc } // namespace webrtc

View File

@ -173,6 +173,7 @@ struct RTPVideoHeaderVP9 {
gof_idx = kNoGofIdx; gof_idx = kNoGofIdx;
num_ref_pics = 0; num_ref_pics = 0;
num_spatial_layers = 1; num_spatial_layers = 1;
first_active_layer = 0;
end_of_picture = true; end_of_picture = true;
} }
@ -208,6 +209,7 @@ struct RTPVideoHeaderVP9 {
// SS data. // SS data.
size_t num_spatial_layers; // Always populated. size_t num_spatial_layers; // Always populated.
size_t first_active_layer; // Not sent on wire, used to adjust ss data.
bool spatial_layer_resolution_present; bool spatial_layer_resolution_present;
uint16_t width[kMaxVp9NumberOfSpatialLayers]; uint16_t width[kMaxVp9NumberOfSpatialLayers];
uint16_t height[kMaxVp9NumberOfSpatialLayers]; uint16_t height[kMaxVp9NumberOfSpatialLayers];

View File

@ -1113,6 +1113,7 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
// Always populate this, so that the packetizer can properly set the marker // Always populate this, so that the packetizer can properly set the marker
// bit. // bit.
vp9_info->num_spatial_layers = num_active_spatial_layers_; vp9_info->num_spatial_layers = num_active_spatial_layers_;
vp9_info->first_active_layer = first_active_layer_;
vp9_info->num_ref_pics = 0; vp9_info->num_ref_pics = 0;
FillReferenceIndices(pkt, pics_since_key_, vp9_info->inter_layer_predicted, FillReferenceIndices(pkt, pics_since_key_, vp9_info->inter_layer_predicted,

View File

@ -69,6 +69,7 @@ struct CodecSpecificInfoVP9 {
// SS data. // SS data.
size_t num_spatial_layers; // Always populated. size_t num_spatial_layers; // Always populated.
size_t first_active_layer;
bool spatial_layer_resolution_present; bool spatial_layer_resolution_present;
uint16_t width[kMaxVp9NumberOfSpatialLayers]; uint16_t width[kMaxVp9NumberOfSpatialLayers];
uint16_t height[kMaxVp9NumberOfSpatialLayers]; uint16_t height[kMaxVp9NumberOfSpatialLayers];