Allow empty video layer allocation extension

This patch adds support for sending zero video layer allocations
header extensions. This can be used to signal that a stream is
turned off.

Bug: webrtc:12000
Change-Id: Id18fbbff2216ca23179c58ef7bbe2ebea5e242af
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212743
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33541}
This commit is contained in:
Jonas Oreland
2021-03-23 11:11:56 +01:00
committed by Commit Bot
parent fa4db49532
commit 93ee168671
3 changed files with 41 additions and 9 deletions

View File

@ -201,17 +201,21 @@ SpatialLayersBitmasks SpatialLayersBitmasksPerRtpStream(
// Encoded (width - 1), 16-bit, (height - 1), 16-bit, max frame rate 8-bit
// per spatial layer per RTP stream.
// Values are stored in (RTP stream id, spatial id) ascending order.
//
// An empty layer allocation (i.e nothing sent on ssrc) is encoded as
// special case with a single 0 byte.
bool RtpVideoLayersAllocationExtension::Write(
rtc::ArrayView<uint8_t> data,
const VideoLayersAllocation& allocation) {
if (allocation.active_spatial_layers.empty()) {
return false;
}
RTC_DCHECK(AllocationIsValid(allocation));
RTC_DCHECK_GE(data.size(), ValueSize(allocation));
if (allocation.active_spatial_layers.empty()) {
data[0] = 0;
return true;
}
SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);
uint8_t* write_at = data.data();
// First half of the header byte.
@ -276,10 +280,18 @@ bool RtpVideoLayersAllocationExtension::Parse(
if (data.empty() || allocation == nullptr) {
return false;
}
allocation->active_spatial_layers.clear();
const uint8_t* read_at = data.data();
const uint8_t* const end = data.data() + data.size();
allocation->active_spatial_layers.clear();
if (data.size() == 1 && *read_at == 0) {
allocation->rtp_stream_index = 0;
allocation->resolution_and_frame_rate_is_valid = true;
return true;
}
// Header byte.
allocation->rtp_stream_index = *read_at >> 6;
int num_rtp_streams = 1 + ((*read_at >> 4) & 0b11);
@ -374,7 +386,7 @@ bool RtpVideoLayersAllocationExtension::Parse(
size_t RtpVideoLayersAllocationExtension::ValueSize(
const VideoLayersAllocation& allocation) {
if (allocation.active_spatial_layers.empty()) {
return 0;
return 1;
}
size_t result = 1; // header
SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);

View File

@ -19,15 +19,33 @@
namespace webrtc {
namespace {
TEST(RtpVideoLayersAllocationExtension,
WriteEmptyLayersAllocationReturnsFalse) {
TEST(RtpVideoLayersAllocationExtension, WriteEmptyLayersAllocationReturnsTrue) {
VideoLayersAllocation written_allocation;
rtc::Buffer buffer(
RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
EXPECT_FALSE(
EXPECT_TRUE(
RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
}
TEST(RtpVideoLayersAllocationExtension,
CanWriteAndParseLayersAllocationWithZeroSpatialLayers) {
// We require the resolution_and_frame_rate_is_valid to be set to true in
// order to send an "empty" allocation.
VideoLayersAllocation written_allocation;
written_allocation.resolution_and_frame_rate_is_valid = true;
written_allocation.rtp_stream_index = 0;
rtc::Buffer buffer(
RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
EXPECT_TRUE(
RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
VideoLayersAllocation parsed_allocation;
EXPECT_TRUE(
RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
EXPECT_EQ(written_allocation, parsed_allocation);
}
TEST(RtpVideoLayersAllocationExtension,
CanWriteAndParse2SpatialWith2TemporalLayers) {
VideoLayersAllocation written_allocation;