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