1 /*
2  *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.h"
12 
13 #include "api/video/video_layers_allocation.h"
14 #include "rtc_base/bit_buffer.h"
15 #include "rtc_base/buffer.h"
16 
17 #include "test/gmock.h"
18 
19 namespace webrtc {
20 namespace {
21 
TEST(RtpVideoLayersAllocationExtension,WriteEmptyLayersAllocationReturnsTrue)22 TEST(RtpVideoLayersAllocationExtension, WriteEmptyLayersAllocationReturnsTrue) {
23   VideoLayersAllocation written_allocation;
24   rtc::Buffer buffer(
25       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
26   EXPECT_TRUE(
27       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
28 }
29 
TEST(RtpVideoLayersAllocationExtension,CanWriteAndParseLayersAllocationWithZeroSpatialLayers)30 TEST(RtpVideoLayersAllocationExtension,
31      CanWriteAndParseLayersAllocationWithZeroSpatialLayers) {
32   // We require the resolution_and_frame_rate_is_valid to be set to true in
33   // order to send an "empty" allocation.
34   VideoLayersAllocation written_allocation;
35   written_allocation.resolution_and_frame_rate_is_valid = true;
36   written_allocation.rtp_stream_index = 0;
37 
38   rtc::Buffer buffer(
39       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
40   EXPECT_TRUE(
41       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
42 
43   VideoLayersAllocation parsed_allocation;
44   EXPECT_TRUE(
45       RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
46   EXPECT_EQ(written_allocation, parsed_allocation);
47 }
48 
TEST(RtpVideoLayersAllocationExtension,CanWriteAndParse2SpatialWith2TemporalLayers)49 TEST(RtpVideoLayersAllocationExtension,
50      CanWriteAndParse2SpatialWith2TemporalLayers) {
51   VideoLayersAllocation written_allocation;
52   written_allocation.rtp_stream_index = 1;
53   written_allocation.active_spatial_layers = {
54       {
55           /*rtp_stream_index*/ 0,
56           /*spatial_id*/ 0,
57           /*target_bitrate_per_temporal_layer*/
58           {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)},
59           /*width*/ 0,
60           /*height*/ 0,
61           /*frame_rate_fps*/ 0,
62       },
63       {
64           /*rtp_stream_index*/ 1,
65           /*spatial_id*/ 0,
66           /*target_bitrate_per_temporal_layer*/
67           {DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200)},
68           /*width*/ 0,
69           /*height*/ 0,
70           /*frame_rate_fps*/ 0,
71       },
72   };
73   rtc::Buffer buffer(
74       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
75   EXPECT_TRUE(
76       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
77   VideoLayersAllocation parsed_allocation;
78   EXPECT_TRUE(
79       RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
80   EXPECT_EQ(written_allocation, parsed_allocation);
81 }
82 
TEST(RtpVideoLayersAllocationExtension,CanWriteAndParseAllocationWithDifferentNumerOfSpatialLayers)83 TEST(RtpVideoLayersAllocationExtension,
84      CanWriteAndParseAllocationWithDifferentNumerOfSpatialLayers) {
85   VideoLayersAllocation written_allocation;
86   written_allocation.rtp_stream_index = 1;
87   written_allocation.active_spatial_layers = {
88       {/*rtp_stream_index*/ 0,
89        /*spatial_id*/ 0,
90        /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)},
91        /*width*/ 0,
92        /*height*/ 0,
93        /*frame_rate_fps*/ 0},
94       {/*rtp_stream_index*/ 1,
95        /*spatial_id*/ 0,
96        /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(100)},
97        /*width*/ 0,
98        /*height*/ 0,
99        /*frame_rate_fps*/ 0},
100       {/*rtp_stream_index*/ 1,
101        /*spatial_id*/ 1,
102        /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)},
103        /*width*/ 0,
104        /*height*/ 0,
105        /*frame_rate_fps*/ 0},
106   };
107   rtc::Buffer buffer(
108       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
109   EXPECT_TRUE(
110       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
111   VideoLayersAllocation parsed_allocation;
112   EXPECT_TRUE(
113       RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
114   EXPECT_EQ(written_allocation, parsed_allocation);
115 }
116 
TEST(RtpVideoLayersAllocationExtension,CanWriteAndParseAllocationWithSkippedLowerSpatialLayer)117 TEST(RtpVideoLayersAllocationExtension,
118      CanWriteAndParseAllocationWithSkippedLowerSpatialLayer) {
119   VideoLayersAllocation written_allocation;
120   written_allocation.rtp_stream_index = 1;
121   written_allocation.active_spatial_layers = {
122       {/*rtp_stream_index*/ 0,
123        /*spatial_id*/ 0,
124        /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)},
125        /*width*/ 0,
126        /*height*/ 0,
127        /*frame_rate_fps*/ 0},
128       {/*rtp_stream_index*/ 1,
129        /*spatial_id*/ 1,
130        /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)},
131        /*width*/ 0,
132        /*height*/ 0,
133        /*frame_rate_fps*/ 0},
134   };
135   rtc::Buffer buffer(
136       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
137   EXPECT_TRUE(
138       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
139   VideoLayersAllocation parsed_allocation;
140   EXPECT_TRUE(
141       RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
142   EXPECT_EQ(written_allocation, parsed_allocation);
143 }
144 
TEST(RtpVideoLayersAllocationExtension,CanWriteAndParseAllocationWithSkippedRtpStreamIds)145 TEST(RtpVideoLayersAllocationExtension,
146      CanWriteAndParseAllocationWithSkippedRtpStreamIds) {
147   VideoLayersAllocation written_allocation;
148   written_allocation.rtp_stream_index = 2;
149   written_allocation.active_spatial_layers = {
150       {/*rtp_stream_index*/ 0,
151        /*spatial_id*/ 0,
152        /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)},
153        /*width*/ 0,
154        /*height*/ 0,
155        /*frame_rate_fps*/ 0},
156       {/*rtp_stream_index*/ 2,
157        /*spatial_id*/ 0,
158        /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)},
159        /*width*/ 0,
160        /*height*/ 0,
161        /*frame_rate_fps*/ 0},
162   };
163   rtc::Buffer buffer(
164       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
165   EXPECT_TRUE(
166       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
167   VideoLayersAllocation parsed_allocation;
168   EXPECT_TRUE(
169       RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
170   EXPECT_EQ(written_allocation, parsed_allocation);
171 }
172 
TEST(RtpVideoLayersAllocationExtension,CanWriteAndParseAllocationWithDifferentNumerOfTemporalLayers)173 TEST(RtpVideoLayersAllocationExtension,
174      CanWriteAndParseAllocationWithDifferentNumerOfTemporalLayers) {
175   VideoLayersAllocation written_allocation;
176   written_allocation.rtp_stream_index = 1;
177   written_allocation.active_spatial_layers = {
178       {
179           /*rtp_stream_index*/ 0,
180           /*spatial_id*/ 0,
181           /*target_bitrate_per_temporal_layer*/
182           {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)},
183           /*width*/ 0,
184           /*height*/ 0,
185           /*frame_rate_fps*/ 0,
186       },
187       {
188           /*rtp_stream_index*/ 1,
189           /*spatial_id*/ 0,
190           /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(100)},
191           /*width*/ 0,
192           /*height*/ 0,
193           /*frame_rate_fps*/ 0,
194       },
195   };
196   rtc::Buffer buffer(
197       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
198   EXPECT_TRUE(
199       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
200   VideoLayersAllocation parsed_allocation;
201   EXPECT_TRUE(
202       RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
203   EXPECT_EQ(written_allocation, parsed_allocation);
204 }
205 
TEST(RtpVideoLayersAllocationExtension,CanWriteAndParseAllocationWithResolution)206 TEST(RtpVideoLayersAllocationExtension,
207      CanWriteAndParseAllocationWithResolution) {
208   VideoLayersAllocation written_allocation;
209   written_allocation.rtp_stream_index = 1;
210   written_allocation.resolution_and_frame_rate_is_valid = true;
211   written_allocation.active_spatial_layers = {
212       {
213           /*rtp_stream_index*/ 0,
214           /*spatial_id*/ 0,
215           /*target_bitrate_per_temporal_layer*/
216           {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)},
217           /*width*/ 320,
218           /*height*/ 240,
219           /*frame_rate_fps*/ 8,
220       },
221       {
222           /*rtp_stream_index*/ 1,
223           /*spatial_id*/ 1,
224           /*target_bitrate_per_temporal_layer*/
225           {DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200)},
226           /*width*/ 640,
227           /*height*/ 320,
228           /*frame_rate_fps*/ 30,
229       },
230   };
231 
232   rtc::Buffer buffer(
233       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
234   EXPECT_TRUE(
235       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
236   VideoLayersAllocation parsed_allocation;
237   EXPECT_TRUE(
238       RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
239   EXPECT_EQ(written_allocation, parsed_allocation);
240 }
241 
TEST(RtpVideoLayersAllocationExtension,WriteEmptyAllocationCanHaveAnyRtpStreamIndex)242 TEST(RtpVideoLayersAllocationExtension,
243      WriteEmptyAllocationCanHaveAnyRtpStreamIndex) {
244   VideoLayersAllocation written_allocation;
245   written_allocation.rtp_stream_index = 1;
246   rtc::Buffer buffer(
247       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
248   EXPECT_TRUE(
249       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
250 }
251 
TEST(RtpVideoLayersAllocationExtension,DiscardsOverLargeDataRate)252 TEST(RtpVideoLayersAllocationExtension, DiscardsOverLargeDataRate) {
253   constexpr uint8_t buffer[] = {0x4b, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
254                                 0xff, 0xcb, 0x78, 0xeb, 0x8d, 0xb5, 0x31};
255   VideoLayersAllocation allocation;
256   EXPECT_FALSE(RtpVideoLayersAllocationExtension::Parse(buffer, &allocation));
257 }
258 
TEST(RtpVideoLayersAllocationExtension,DiscardsInvalidHeight)259 TEST(RtpVideoLayersAllocationExtension, DiscardsInvalidHeight) {
260   VideoLayersAllocation written_allocation;
261   written_allocation.rtp_stream_index = 0;
262   written_allocation.resolution_and_frame_rate_is_valid = true;
263   written_allocation.active_spatial_layers = {
264       {
265           /*rtp_stream_index*/ 0,
266           /*spatial_id*/ 0,
267           /*target_bitrate_per_temporal_layer*/
268           {DataRate::KilobitsPerSec(25), DataRate::KilobitsPerSec(50)},
269           /*width*/ 320,
270           /*height*/ 240,
271           /*frame_rate_fps*/ 8,
272       },
273   };
274   rtc::Buffer buffer(
275       RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
276   ASSERT_TRUE(
277       RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
278 
279   // Modify the height to be invalid.
280   buffer[buffer.size() - 3] = 0xff;
281   buffer[buffer.size() - 2] = 0xff;
282   VideoLayersAllocation allocation;
283   EXPECT_FALSE(RtpVideoLayersAllocationExtension::Parse(buffer, &allocation));
284 }
285 
286 }  // namespace
287 }  // namespace webrtc
288