xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_vp8_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 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/video_rtp_depacketizer_vp8.h"
12 
13 #include "api/array_view.h"
14 #include "modules/rtp_rtcp/source/rtp_format_vp8.h"
15 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
16 #include "rtc_base/copy_on_write_buffer.h"
17 #include "test/gmock.h"
18 #include "test/gtest.h"
19 
20 // VP8 payload descriptor
21 // https://datatracker.ietf.org/doc/html/rfc7741#section-4.2
22 //
23 //       0 1 2 3 4 5 6 7
24 //      +-+-+-+-+-+-+-+-+
25 //      |X|R|N|S|R| PID | (REQUIRED)
26 //      +-+-+-+-+-+-+-+-+
27 // X:   |I|L|T|K| RSV   | (OPTIONAL)
28 //      +-+-+-+-+-+-+-+-+
29 // I:   |M| PictureID   | (OPTIONAL)
30 //      +-+-+-+-+-+-+-+-+
31 //      |   PictureID   |
32 //      +-+-+-+-+-+-+-+-+
33 // L:   |   TL0PICIDX   | (OPTIONAL)
34 //      +-+-+-+-+-+-+-+-+
35 // T/K: |TID|Y| KEYIDX  | (OPTIONAL)
36 //      +-+-+-+-+-+-+-+-+
37 //
38 // VP8 payload header. Considered part of the actual payload, sent to decoder.
39 // https://datatracker.ietf.org/doc/html/rfc7741#section-4.3
40 //
41 //       0 1 2 3 4 5 6 7
42 //      +-+-+-+-+-+-+-+-+
43 //      |Size0|H| VER |P|
44 //      +-+-+-+-+-+-+-+-+
45 //      :      ...      :
46 //      +-+-+-+-+-+-+-+-+
47 
48 namespace webrtc {
49 namespace {
50 
TEST(VideoRtpDepacketizerVp8Test,BasicHeader)51 TEST(VideoRtpDepacketizerVp8Test, BasicHeader) {
52   uint8_t packet[4] = {0};
53   packet[0] = 0b0001'0100;  // S = 1, partition ID = 4.
54   packet[1] = 0x01;         // P frame.
55 
56   RTPVideoHeader video_header;
57   int offset = VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &video_header);
58 
59   EXPECT_EQ(offset, 1);
60   EXPECT_EQ(video_header.frame_type, VideoFrameType::kVideoFrameDelta);
61   EXPECT_EQ(video_header.codec, kVideoCodecVP8);
62   const auto& vp8_header =
63       absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
64   EXPECT_FALSE(vp8_header.nonReference);
65   EXPECT_TRUE(vp8_header.beginningOfPartition);
66   EXPECT_EQ(vp8_header.partitionId, 4);
67   EXPECT_EQ(vp8_header.pictureId, kNoPictureId);
68   EXPECT_EQ(vp8_header.tl0PicIdx, kNoTl0PicIdx);
69   EXPECT_EQ(vp8_header.temporalIdx, kNoTemporalIdx);
70   EXPECT_EQ(vp8_header.keyIdx, kNoKeyIdx);
71 }
72 
TEST(VideoRtpDepacketizerVp8Test,OneBytePictureID)73 TEST(VideoRtpDepacketizerVp8Test, OneBytePictureID) {
74   const uint8_t kPictureId = 17;
75   uint8_t packet[10] = {0};
76   packet[0] = 0b1010'0000;
77   packet[1] = 0b1000'0000;
78   packet[2] = kPictureId;
79 
80   RTPVideoHeader video_header;
81   int offset = VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &video_header);
82 
83   EXPECT_EQ(offset, 3);
84   const auto& vp8_header =
85       absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
86   EXPECT_EQ(vp8_header.pictureId, kPictureId);
87 }
88 
TEST(VideoRtpDepacketizerVp8Test,TwoBytePictureID)89 TEST(VideoRtpDepacketizerVp8Test, TwoBytePictureID) {
90   const uint16_t kPictureId = 0x1234;
91   uint8_t packet[10] = {0};
92   packet[0] = 0b1010'0000;
93   packet[1] = 0b1000'0000;
94   packet[2] = 0x80 | 0x12;
95   packet[3] = 0x34;
96 
97   RTPVideoHeader video_header;
98   int offset = VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &video_header);
99 
100   EXPECT_EQ(offset, 4);
101   const auto& vp8_header =
102       absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
103   EXPECT_EQ(vp8_header.pictureId, kPictureId);
104 }
105 
TEST(VideoRtpDepacketizerVp8Test,Tl0PicIdx)106 TEST(VideoRtpDepacketizerVp8Test, Tl0PicIdx) {
107   const uint8_t kTl0PicIdx = 17;
108   uint8_t packet[13] = {0};
109   packet[0] = 0b1000'0000;
110   packet[1] = 0b0100'0000;
111   packet[2] = kTl0PicIdx;
112 
113   RTPVideoHeader video_header;
114   int offset = VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &video_header);
115 
116   EXPECT_EQ(offset, 3);
117   const auto& vp8_header =
118       absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
119   EXPECT_EQ(vp8_header.tl0PicIdx, kTl0PicIdx);
120 }
121 
TEST(VideoRtpDepacketizerVp8Test,TIDAndLayerSync)122 TEST(VideoRtpDepacketizerVp8Test, TIDAndLayerSync) {
123   uint8_t packet[10] = {0};
124   packet[0] = 0b1000'0000;
125   packet[1] = 0b0010'0000;
126   packet[2] = 0b10'0'00000;  // TID(2) + LayerSync(false)
127 
128   RTPVideoHeader video_header;
129   int offset = VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &video_header);
130 
131   EXPECT_EQ(offset, 3);
132   const auto& vp8_header =
133       absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
134   EXPECT_EQ(vp8_header.temporalIdx, 2);
135   EXPECT_FALSE(vp8_header.layerSync);
136 }
137 
TEST(VideoRtpDepacketizerVp8Test,KeyIdx)138 TEST(VideoRtpDepacketizerVp8Test, KeyIdx) {
139   const uint8_t kKeyIdx = 17;
140   uint8_t packet[10] = {0};
141   packet[0] = 0b1000'0000;
142   packet[1] = 0b0001'0000;
143   packet[2] = kKeyIdx;
144 
145   RTPVideoHeader video_header;
146   int offset = VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &video_header);
147 
148   EXPECT_EQ(offset, 3);
149   const auto& vp8_header =
150       absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
151   EXPECT_EQ(vp8_header.keyIdx, kKeyIdx);
152 }
153 
TEST(VideoRtpDepacketizerVp8Test,MultipleExtensions)154 TEST(VideoRtpDepacketizerVp8Test, MultipleExtensions) {
155   uint8_t packet[10] = {0};
156   packet[0] = 0b1010'0110;  // X and N bit set, partition ID = 6
157   packet[1] = 0b1111'0000;
158   packet[2] = 0x80 | 0x12;  // PictureID, high 7 bits.
159   packet[3] = 0x34;         // PictureID, low 8 bits.
160   packet[4] = 42;           // Tl0PicIdx.
161   packet[5] = 0b01'1'10001;
162 
163   RTPVideoHeader video_header;
164   int offset = VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &video_header);
165 
166   EXPECT_EQ(offset, 6);
167   const auto& vp8_header =
168       absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
169   EXPECT_TRUE(vp8_header.nonReference);
170   EXPECT_EQ(vp8_header.partitionId, 0b0110);
171   EXPECT_EQ(vp8_header.pictureId, 0x1234);
172   EXPECT_EQ(vp8_header.tl0PicIdx, 42);
173   EXPECT_EQ(vp8_header.temporalIdx, 1);
174   EXPECT_TRUE(vp8_header.layerSync);
175   EXPECT_EQ(vp8_header.keyIdx, 0b10001);
176 }
177 
TEST(VideoRtpDepacketizerVp8Test,TooShortHeader)178 TEST(VideoRtpDepacketizerVp8Test, TooShortHeader) {
179   uint8_t packet[4] = {0};
180   packet[0] = 0b1000'0000;
181   packet[1] = 0b1111'0000;  // All extensions are enabled...
182   packet[2] = 0x80 | 17;    // ... but only 2 bytes PictureID is provided.
183   packet[3] = 17;           // PictureID, low 8 bits.
184 
185   RTPVideoHeader unused;
186   EXPECT_EQ(VideoRtpDepacketizerVp8::ParseRtpPayload(packet, &unused), 0);
187 }
188 
TEST(VideoRtpDepacketizerVp8Test,WithPacketizer)189 TEST(VideoRtpDepacketizerVp8Test, WithPacketizer) {
190   uint8_t data[10] = {0};
191   RtpPacketToSend packet(/*extenions=*/nullptr);
192   RTPVideoHeaderVP8 input_header;
193   input_header.nonReference = true;
194   input_header.pictureId = 300;
195   input_header.temporalIdx = 1;
196   input_header.layerSync = false;
197   input_header.tl0PicIdx = kNoTl0PicIdx;  // Disable.
198   input_header.keyIdx = 31;
199   RtpPacketizerVp8 packetizer(data, /*limits=*/{}, input_header);
200   EXPECT_EQ(packetizer.NumPackets(), 1u);
201   ASSERT_TRUE(packetizer.NextPacket(&packet));
202 
203   VideoRtpDepacketizerVp8 depacketizer;
204   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
205       depacketizer.Parse(packet.PayloadBuffer());
206   ASSERT_TRUE(parsed);
207 
208   EXPECT_EQ(parsed->video_header.codec, kVideoCodecVP8);
209   const auto& vp8_header =
210       absl::get<RTPVideoHeaderVP8>(parsed->video_header.video_type_header);
211   EXPECT_EQ(vp8_header.nonReference, input_header.nonReference);
212   EXPECT_EQ(vp8_header.pictureId, input_header.pictureId);
213   EXPECT_EQ(vp8_header.tl0PicIdx, input_header.tl0PicIdx);
214   EXPECT_EQ(vp8_header.temporalIdx, input_header.temporalIdx);
215   EXPECT_EQ(vp8_header.layerSync, input_header.layerSync);
216   EXPECT_EQ(vp8_header.keyIdx, input_header.keyIdx);
217 }
218 
TEST(VideoRtpDepacketizerVp8Test,ReferencesInputCopyOnWriteBuffer)219 TEST(VideoRtpDepacketizerVp8Test, ReferencesInputCopyOnWriteBuffer) {
220   constexpr size_t kHeaderSize = 5;
221   uint8_t packet[16] = {0};
222   packet[0] = 0b1000'0000;
223   packet[1] = 0b1111'0000;  // with all extensions,
224   packet[2] = 15;           // and one-byte picture id.
225 
226   rtc::CopyOnWriteBuffer rtp_payload(packet);
227   VideoRtpDepacketizerVp8 depacketizer;
228   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
229       depacketizer.Parse(rtp_payload);
230   ASSERT_TRUE(parsed);
231 
232   EXPECT_EQ(parsed->video_payload.size(), rtp_payload.size() - kHeaderSize);
233   // Compare pointers to check there was no copy on write buffer unsharing.
234   EXPECT_EQ(parsed->video_payload.cdata(), rtp_payload.cdata() + kHeaderSize);
235 }
236 
TEST(VideoRtpDepacketizerVp8Test,FailsOnEmptyPayload)237 TEST(VideoRtpDepacketizerVp8Test, FailsOnEmptyPayload) {
238   rtc::ArrayView<const uint8_t> empty;
239   RTPVideoHeader video_header;
240   EXPECT_EQ(VideoRtpDepacketizerVp8::ParseRtpPayload(empty, &video_header), 0);
241 }
242 
243 }  // namespace
244 }  // namespace webrtc
245