/* * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.h" #include "api/video/video_layers_allocation.h" #include "rtc_base/bit_buffer.h" #include "rtc_base/buffer.h" #include "test/gmock.h" namespace webrtc { namespace { TEST(RtpVideoLayersAllocationExtension, WriteEmptyLayersAllocationReturnsTrue) { VideoLayersAllocation written_allocation; rtc::Buffer buffer( RtpVideoLayersAllocationExtension::ValueSize(written_allocation)); 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; written_allocation.rtp_stream_index = 1; written_allocation.active_spatial_layers = { { /*rtp_stream_index*/ 0, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 0, }, { /*rtp_stream_index*/ 1, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 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, CanWriteAndParseAllocationWithDifferentNumerOfSpatialLayers) { VideoLayersAllocation written_allocation; written_allocation.rtp_stream_index = 1; written_allocation.active_spatial_layers = { {/*rtp_stream_index*/ 0, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 0}, {/*rtp_stream_index*/ 1, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(100)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 0}, {/*rtp_stream_index*/ 1, /*spatial_id*/ 1, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 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, CanWriteAndParseAllocationWithSkippedLowerSpatialLayer) { VideoLayersAllocation written_allocation; written_allocation.rtp_stream_index = 1; written_allocation.active_spatial_layers = { {/*rtp_stream_index*/ 0, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 0}, {/*rtp_stream_index*/ 1, /*spatial_id*/ 1, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 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, CanWriteAndParseAllocationWithSkippedRtpStreamIds) { VideoLayersAllocation written_allocation; written_allocation.rtp_stream_index = 2; written_allocation.active_spatial_layers = { {/*rtp_stream_index*/ 0, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 0}, {/*rtp_stream_index*/ 2, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 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, CanWriteAndParseAllocationWithDifferentNumerOfTemporalLayers) { VideoLayersAllocation written_allocation; written_allocation.rtp_stream_index = 1; written_allocation.active_spatial_layers = { { /*rtp_stream_index*/ 0, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 0, }, { /*rtp_stream_index*/ 1, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(100)}, /*width*/ 0, /*height*/ 0, /*frame_rate_fps*/ 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, CanWriteAndParseAllocationWithResolution) { VideoLayersAllocation written_allocation; written_allocation.rtp_stream_index = 1; written_allocation.resolution_and_frame_rate_is_valid = true; written_allocation.active_spatial_layers = { { /*rtp_stream_index*/ 0, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)}, /*width*/ 320, /*height*/ 240, /*frame_rate_fps*/ 8, }, { /*rtp_stream_index*/ 1, /*spatial_id*/ 1, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200)}, /*width*/ 640, /*height*/ 320, /*frame_rate_fps*/ 30, }, }; 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, WriteEmptyAllocationCanHaveAnyRtpStreamIndex) { VideoLayersAllocation written_allocation; written_allocation.rtp_stream_index = 1; rtc::Buffer buffer( RtpVideoLayersAllocationExtension::ValueSize(written_allocation)); EXPECT_TRUE( RtpVideoLayersAllocationExtension::Write(buffer, written_allocation)); } TEST(RtpVideoLayersAllocationExtension, DiscardsOverLargeDataRate) { constexpr uint8_t buffer[] = {0x4b, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0x78, 0xeb, 0x8d, 0xb5, 0x31}; VideoLayersAllocation allocation; EXPECT_FALSE(RtpVideoLayersAllocationExtension::Parse(buffer, &allocation)); } TEST(RtpVideoLayersAllocationExtension, DiscardsInvalidHeight) { VideoLayersAllocation written_allocation; written_allocation.rtp_stream_index = 0; written_allocation.resolution_and_frame_rate_is_valid = true; written_allocation.active_spatial_layers = { { /*rtp_stream_index*/ 0, /*spatial_id*/ 0, /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)}, /*width*/ 320, /*height*/ 240, /*frame_rate_fps*/ 8, }, }; rtc::Buffer buffer( RtpVideoLayersAllocationExtension::ValueSize(written_allocation)); ASSERT_TRUE( RtpVideoLayersAllocationExtension::Write(buffer, written_allocation)); // Modify the height to be invalid. buffer[buffer.size() - 3] = 0xff; buffer[buffer.size() - 2] = 0xff; VideoLayersAllocation allocation; EXPECT_FALSE(RtpVideoLayersAllocationExtension::Parse(buffer, &allocation)); } } // namespace } // namespace webrtc