Skip to content

Commit 2e73a3d

Browse files
Ilya NikolaevskiyCommit Bot
Ilya Nikolaevskiy
authored and
Commit Bot
committed
[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}
1 parent 670af26 commit 2e73a3d

File tree

6 files changed

+91
-1
lines changed

6 files changed

+91
-1
lines changed

call/rtp_payload_params.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void PopulateRtpWithCodecSpecifics(const CodecSpecificInfo& info,
6161
info.codecSpecific.VP9.inter_layer_predicted;
6262
vp9_header.gof_idx = info.codecSpecific.VP9.gof_idx;
6363
vp9_header.num_spatial_layers = info.codecSpecific.VP9.num_spatial_layers;
64+
vp9_header.first_active_layer = info.codecSpecific.VP9.first_active_layer;
6465
if (vp9_header.num_spatial_layers > 1) {
6566
vp9_header.spatial_idx = spatial_index.value_or(kNoSpatialIdx);
6667
} else {

modules/rtp_rtcp/source/rtp_format_vp9.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,15 +280,42 @@ bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) {
280280
}
281281
return true;
282282
}
283+
284+
// TODO(https://bugs.webrtc.org/11319):
285+
// Workaround for switching off spatial layers on the fly.
286+
// Sent layers must start from SL0 on RTP layer, but can start from any
287+
// spatial layer because WebRTC-SVC api isn't implemented yet and
288+
// current API to invoke SVC is not flexible enough.
289+
RTPVideoHeaderVP9 RemoveInactiveSpatialLayers(
290+
const RTPVideoHeaderVP9& original_header) {
291+
RTPVideoHeaderVP9 hdr(original_header);
292+
if (original_header.first_active_layer == 0)
293+
return hdr;
294+
for (size_t i = hdr.first_active_layer; i < hdr.num_spatial_layers; ++i) {
295+
hdr.width[i - hdr.first_active_layer] = hdr.width[i];
296+
hdr.height[i - hdr.first_active_layer] = hdr.height[i];
297+
}
298+
for (size_t i = hdr.num_spatial_layers - hdr.first_active_layer;
299+
i < hdr.num_spatial_layers; ++i) {
300+
hdr.width[i] = 0;
301+
hdr.height[i] = 0;
302+
}
303+
hdr.num_spatial_layers -= hdr.first_active_layer;
304+
hdr.spatial_idx -= hdr.first_active_layer;
305+
hdr.first_active_layer = 0;
306+
return hdr;
307+
}
283308
} // namespace
284309

285310
RtpPacketizerVp9::RtpPacketizerVp9(rtc::ArrayView<const uint8_t> payload,
286311
PayloadSizeLimits limits,
287312
const RTPVideoHeaderVP9& hdr)
288-
: hdr_(hdr),
313+
: hdr_(RemoveInactiveSpatialLayers(hdr)),
289314
header_size_(PayloadDescriptorLengthMinusSsData(hdr_)),
290315
first_packet_extra_header_size_(SsDataLength(hdr_)),
291316
remaining_payload_(payload) {
317+
RTC_DCHECK_EQ(hdr_.first_active_layer, 0);
318+
292319
limits.max_payload_len -= header_size_;
293320
limits.first_packet_reduction_len += first_packet_extra_header_size_;
294321
limits.single_packet_reduction_len += first_packet_extra_header_size_;

modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,21 @@ class RtpPacketizerVp9Test : public ::testing::Test {
169169
expected_.ss_data_available = false;
170170
}
171171
}
172+
173+
void CreateParseAndCheckPacketsLayers(size_t num_spatial_layers,
174+
size_t expected_layer) {
175+
ASSERT_TRUE(packetizer_ != nullptr);
176+
for (size_t i = 0; i < num_packets_; ++i) {
177+
EXPECT_TRUE(packetizer_->NextPacket(&packet_));
178+
RTPVideoHeader video_header;
179+
VideoRtpDepacketizerVp9::ParseRtpPayload(packet_.payload(),
180+
&video_header);
181+
const auto& vp9_header =
182+
absl::get<RTPVideoHeaderVP9>(video_header.video_type_header);
183+
EXPECT_EQ(vp9_header.spatial_idx, expected_layer);
184+
EXPECT_EQ(vp9_header.num_spatial_layers, num_spatial_layers);
185+
}
186+
}
172187
};
173188

174189
TEST_F(RtpPacketizerVp9Test, TestEqualSizedMode_OnePacket) {
@@ -546,5 +561,48 @@ TEST_F(RtpPacketizerVp9Test, TestNonRefForInterLayerPred) {
546561
CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes);
547562
}
548563

564+
TEST_F(RtpPacketizerVp9Test,
565+
ShiftsSpatialLayersTowardZeroWhenFirstLayersAreDisabled) {
566+
const size_t kFrameSize = 25;
567+
const size_t kPacketSize = 1024;
568+
569+
expected_.width[0] = 0;
570+
expected_.height[0] = 0;
571+
expected_.width[1] = 640;
572+
expected_.height[1] = 360;
573+
expected_.width[2] = 1280;
574+
expected_.height[2] = 720;
575+
expected_.num_spatial_layers = 3;
576+
expected_.first_active_layer = 1;
577+
expected_.ss_data_available = true;
578+
expected_.spatial_layer_resolution_present = true;
579+
expected_.gof.num_frames_in_gof = 3;
580+
expected_.gof.temporal_idx[0] = 0;
581+
expected_.gof.temporal_idx[1] = 1;
582+
expected_.gof.temporal_idx[2] = 2;
583+
expected_.gof.temporal_up_switch[0] = true;
584+
expected_.gof.temporal_up_switch[1] = true;
585+
expected_.gof.temporal_up_switch[2] = false;
586+
expected_.gof.num_ref_pics[0] = 0;
587+
expected_.gof.num_ref_pics[1] = 3;
588+
expected_.gof.num_ref_pics[2] = 2;
589+
expected_.gof.pid_diff[1][0] = 5;
590+
expected_.gof.pid_diff[1][1] = 6;
591+
expected_.gof.pid_diff[1][2] = 7;
592+
expected_.gof.pid_diff[2][0] = 8;
593+
expected_.gof.pid_diff[2][1] = 9;
594+
595+
expected_.spatial_idx = 1;
596+
Init(kFrameSize, kPacketSize);
597+
CreateParseAndCheckPacketsLayers(/*num_spatial_layers=*/2,
598+
/*expected_layer=*/0);
599+
600+
// Now check for SL 2;
601+
expected_.spatial_idx = 2;
602+
Init(kFrameSize, kPacketSize);
603+
CreateParseAndCheckPacketsLayers(/*num_spatial_layers=*/2,
604+
/*expected_layer=*/1);
605+
}
606+
549607
} // namespace
550608
} // namespace webrtc

modules/video_coding/codecs/vp9/include/vp9_globals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ struct RTPVideoHeaderVP9 {
173173
gof_idx = kNoGofIdx;
174174
num_ref_pics = 0;
175175
num_spatial_layers = 1;
176+
first_active_layer = 0;
176177
end_of_picture = true;
177178
}
178179

@@ -208,6 +209,7 @@ struct RTPVideoHeaderVP9 {
208209

209210
// SS data.
210211
size_t num_spatial_layers; // Always populated.
212+
size_t first_active_layer; // Not sent on wire, used to adjust ss data.
211213
bool spatial_layer_resolution_present;
212214
uint16_t width[kMaxVp9NumberOfSpatialLayers];
213215
uint16_t height[kMaxVp9NumberOfSpatialLayers];

modules/video_coding/codecs/vp9/vp9_impl.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,7 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
11131113
// Always populate this, so that the packetizer can properly set the marker
11141114
// bit.
11151115
vp9_info->num_spatial_layers = num_active_spatial_layers_;
1116+
vp9_info->first_active_layer = first_active_layer_;
11161117

11171118
vp9_info->num_ref_pics = 0;
11181119
FillReferenceIndices(pkt, pics_since_key_, vp9_info->inter_layer_predicted,

modules/video_coding/include/video_codec_interface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct CodecSpecificInfoVP9 {
6969

7070
// SS data.
7171
size_t num_spatial_layers; // Always populated.
72+
size_t first_active_layer;
7273
bool spatial_layer_resolution_present;
7374
uint16_t width[kMaxVp9NumberOfSpatialLayers];
7475
uint16_t height[kMaxVp9NumberOfSpatialLayers];

0 commit comments

Comments
 (0)