• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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