mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-19 08:37:54 +01:00
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:
parent
fa4db49532
commit
93ee168671
3 changed files with 41 additions and 9 deletions
|
@ -80,3 +80,5 @@ extension size. 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
|
rate 8-bit per spatial layer per RTP stream. Values are stored in (RTP stream
|
||||||
id, spatial id) ascending order.
|
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.
|
||||||
|
|
|
@ -201,17 +201,21 @@ SpatialLayersBitmasks SpatialLayersBitmasksPerRtpStream(
|
||||||
// Encoded (width - 1), 16-bit, (height - 1), 16-bit, max frame rate 8-bit
|
// Encoded (width - 1), 16-bit, (height - 1), 16-bit, max frame rate 8-bit
|
||||||
// per spatial layer per RTP stream.
|
// per spatial layer per RTP stream.
|
||||||
// Values are stored in (RTP stream id, spatial id) ascending order.
|
// 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(
|
bool RtpVideoLayersAllocationExtension::Write(
|
||||||
rtc::ArrayView<uint8_t> data,
|
rtc::ArrayView<uint8_t> data,
|
||||||
const VideoLayersAllocation& allocation) {
|
const VideoLayersAllocation& allocation) {
|
||||||
if (allocation.active_spatial_layers.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RTC_DCHECK(AllocationIsValid(allocation));
|
RTC_DCHECK(AllocationIsValid(allocation));
|
||||||
RTC_DCHECK_GE(data.size(), ValueSize(allocation));
|
RTC_DCHECK_GE(data.size(), ValueSize(allocation));
|
||||||
|
|
||||||
|
if (allocation.active_spatial_layers.empty()) {
|
||||||
|
data[0] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);
|
SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);
|
||||||
uint8_t* write_at = data.data();
|
uint8_t* write_at = data.data();
|
||||||
// First half of the header byte.
|
// First half of the header byte.
|
||||||
|
@ -276,10 +280,18 @@ bool RtpVideoLayersAllocationExtension::Parse(
|
||||||
if (data.empty() || allocation == nullptr) {
|
if (data.empty() || allocation == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allocation->active_spatial_layers.clear();
|
||||||
|
|
||||||
const uint8_t* read_at = data.data();
|
const uint8_t* read_at = data.data();
|
||||||
const uint8_t* const end = data.data() + data.size();
|
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.
|
// Header byte.
|
||||||
allocation->rtp_stream_index = *read_at >> 6;
|
allocation->rtp_stream_index = *read_at >> 6;
|
||||||
int num_rtp_streams = 1 + ((*read_at >> 4) & 0b11);
|
int num_rtp_streams = 1 + ((*read_at >> 4) & 0b11);
|
||||||
|
@ -374,7 +386,7 @@ bool RtpVideoLayersAllocationExtension::Parse(
|
||||||
size_t RtpVideoLayersAllocationExtension::ValueSize(
|
size_t RtpVideoLayersAllocationExtension::ValueSize(
|
||||||
const VideoLayersAllocation& allocation) {
|
const VideoLayersAllocation& allocation) {
|
||||||
if (allocation.active_spatial_layers.empty()) {
|
if (allocation.active_spatial_layers.empty()) {
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
size_t result = 1; // header
|
size_t result = 1; // header
|
||||||
SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);
|
SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);
|
||||||
|
|
|
@ -19,15 +19,33 @@
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST(RtpVideoLayersAllocationExtension,
|
TEST(RtpVideoLayersAllocationExtension, WriteEmptyLayersAllocationReturnsTrue) {
|
||||||
WriteEmptyLayersAllocationReturnsFalse) {
|
|
||||||
VideoLayersAllocation written_allocation;
|
VideoLayersAllocation written_allocation;
|
||||||
rtc::Buffer buffer(
|
rtc::Buffer buffer(
|
||||||
RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
|
RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
|
||||||
EXPECT_FALSE(
|
EXPECT_TRUE(
|
||||||
RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
|
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,
|
TEST(RtpVideoLayersAllocationExtension,
|
||||||
CanWriteAndParse2SpatialWith2TemporalLayers) {
|
CanWriteAndParse2SpatialWith2TemporalLayers) {
|
||||||
VideoLayersAllocation written_allocation;
|
VideoLayersAllocation written_allocation;
|
||||||
|
|
Loading…
Reference in a new issue