1 /*
2 * Copyright (c) 2012 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/video_coding/session_info.h"
12
13 #include <string.h>
14
15 #include "modules/video_coding/packet.h"
16 #include "test/gtest.h"
17
18 namespace webrtc {
19
20 class TestSessionInfo : public ::testing::Test {
21 protected:
SetUp()22 virtual void SetUp() {
23 memset(packet_buffer_, 0, sizeof(packet_buffer_));
24 memset(frame_buffer_, 0, sizeof(frame_buffer_));
25 session_.Reset();
26 packet_.video_header.frame_type = VideoFrameType::kVideoFrameDelta;
27 packet_.sizeBytes = packet_buffer_size();
28 packet_.dataPtr = packet_buffer_;
29 packet_.seqNum = 0;
30 packet_.timestamp = 0;
31 frame_data.rtt_ms = 0;
32 frame_data.rolling_average_packets_per_frame = -1;
33 }
34
FillPacket(uint8_t start_value)35 void FillPacket(uint8_t start_value) {
36 for (size_t i = 0; i < packet_buffer_size(); ++i)
37 packet_buffer_[i] = start_value + i;
38 }
39
VerifyPacket(uint8_t * start_ptr,uint8_t start_value)40 void VerifyPacket(uint8_t* start_ptr, uint8_t start_value) {
41 for (size_t j = 0; j < packet_buffer_size(); ++j) {
42 ASSERT_EQ(start_value + j, start_ptr[j]);
43 }
44 }
45
packet_buffer_size() const46 size_t packet_buffer_size() const {
47 return sizeof(packet_buffer_) / sizeof(packet_buffer_[0]);
48 }
frame_buffer_size() const49 size_t frame_buffer_size() const {
50 return sizeof(frame_buffer_) / sizeof(frame_buffer_[0]);
51 }
52
53 enum { kPacketBufferSize = 10 };
54
55 uint8_t packet_buffer_[kPacketBufferSize];
56 uint8_t frame_buffer_[10 * kPacketBufferSize];
57
58 VCMSessionInfo session_;
59 VCMPacket packet_;
60 FrameData frame_data;
61 };
62
63 class TestNalUnits : public TestSessionInfo {
64 protected:
SetUp()65 virtual void SetUp() {
66 TestSessionInfo::SetUp();
67 packet_.video_header.codec = kVideoCodecVP8;
68 }
69
VerifyNalu(int offset,int packets_expected,int start_value)70 bool VerifyNalu(int offset, int packets_expected, int start_value) {
71 EXPECT_GE(session_.SessionLength(),
72 packets_expected * packet_buffer_size());
73 for (int i = 0; i < packets_expected; ++i) {
74 int packet_index = (offset + i) * packet_buffer_size();
75 VerifyPacket(frame_buffer_ + packet_index, start_value + i);
76 }
77 return true;
78 }
79 };
80
81 class TestNackList : public TestSessionInfo {
82 protected:
83 static const size_t kMaxSeqNumListLength = 30;
84
SetUp()85 virtual void SetUp() {
86 TestSessionInfo::SetUp();
87 seq_num_list_length_ = 0;
88 memset(seq_num_list_, 0, sizeof(seq_num_list_));
89 }
90
BuildSeqNumList(uint16_t low,uint16_t high)91 void BuildSeqNumList(uint16_t low, uint16_t high) {
92 size_t i = 0;
93 while (low != high + 1) {
94 EXPECT_LT(i, kMaxSeqNumListLength);
95 if (i >= kMaxSeqNumListLength) {
96 seq_num_list_length_ = kMaxSeqNumListLength;
97 return;
98 }
99 seq_num_list_[i] = low;
100 low++;
101 i++;
102 }
103 seq_num_list_length_ = i;
104 }
105
VerifyAll(int value)106 void VerifyAll(int value) {
107 for (int i = 0; i < seq_num_list_length_; ++i)
108 EXPECT_EQ(seq_num_list_[i], value);
109 }
110
111 int seq_num_list_[kMaxSeqNumListLength];
112 int seq_num_list_length_;
113 };
114
TEST_F(TestSessionInfo,TestSimpleAPIs)115 TEST_F(TestSessionInfo, TestSimpleAPIs) {
116 packet_.video_header.is_first_packet_in_frame = true;
117 packet_.seqNum = 0xFFFE;
118 packet_.sizeBytes = packet_buffer_size();
119 packet_.video_header.frame_type = VideoFrameType::kVideoFrameKey;
120 FillPacket(0);
121 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
122 packet_, frame_buffer_, frame_data)));
123 EXPECT_FALSE(session_.HaveLastPacket());
124 EXPECT_EQ(VideoFrameType::kVideoFrameKey, session_.FrameType());
125
126 packet_.video_header.is_first_packet_in_frame = false;
127 packet_.markerBit = true;
128 packet_.seqNum += 1;
129 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
130 packet_, frame_buffer_, frame_data)));
131 EXPECT_TRUE(session_.HaveLastPacket());
132 EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
133 EXPECT_EQ(0xFFFE, session_.LowSequenceNumber());
134
135 // Insert empty packet which will be the new high sequence number.
136 // To make things more difficult we will make sure to have a wrap here.
137 packet_.video_header.is_first_packet_in_frame = false;
138 packet_.markerBit = true;
139 packet_.seqNum = 2;
140 packet_.sizeBytes = 0;
141 packet_.video_header.frame_type = VideoFrameType::kEmptyFrame;
142 EXPECT_EQ(0, session_.InsertPacket(packet_, frame_buffer_, frame_data));
143 EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
144 }
145
TEST_F(TestSessionInfo,NormalOperation)146 TEST_F(TestSessionInfo, NormalOperation) {
147 packet_.seqNum = 0xFFFF;
148 packet_.video_header.is_first_packet_in_frame = true;
149 packet_.markerBit = false;
150 FillPacket(0);
151 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
152 packet_, frame_buffer_, frame_data)));
153
154 packet_.video_header.is_first_packet_in_frame = false;
155 for (int i = 1; i < 9; ++i) {
156 packet_.seqNum += 1;
157 FillPacket(i);
158 ASSERT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
159 packet_, frame_buffer_, frame_data)));
160 }
161
162 packet_.seqNum += 1;
163 packet_.markerBit = true;
164 FillPacket(9);
165 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
166 packet_, frame_buffer_, frame_data)));
167
168 EXPECT_EQ(10 * packet_buffer_size(), session_.SessionLength());
169 for (int i = 0; i < 10; ++i) {
170 SCOPED_TRACE("Calling VerifyPacket");
171 VerifyPacket(frame_buffer_ + i * packet_buffer_size(), i);
172 }
173 }
174
TEST_F(TestSessionInfo,OutOfBoundsPackets1PacketFrame)175 TEST_F(TestSessionInfo, OutOfBoundsPackets1PacketFrame) {
176 packet_.seqNum = 0x0001;
177 packet_.video_header.is_first_packet_in_frame = true;
178 packet_.markerBit = true;
179 FillPacket(1);
180 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
181 packet_, frame_buffer_, frame_data)));
182
183 packet_.seqNum = 0x0004;
184 packet_.video_header.is_first_packet_in_frame = true;
185 packet_.markerBit = true;
186 FillPacket(1);
187 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
188 packet_.seqNum = 0x0000;
189 packet_.video_header.is_first_packet_in_frame = false;
190 packet_.markerBit = false;
191 FillPacket(1);
192 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
193 }
194
TEST_F(TestSessionInfo,SetMarkerBitOnce)195 TEST_F(TestSessionInfo, SetMarkerBitOnce) {
196 packet_.seqNum = 0x0005;
197 packet_.video_header.is_first_packet_in_frame = false;
198 packet_.markerBit = true;
199 FillPacket(1);
200 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
201 packet_, frame_buffer_, frame_data)));
202 ++packet_.seqNum;
203 packet_.video_header.is_first_packet_in_frame = true;
204 packet_.markerBit = true;
205 FillPacket(1);
206 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
207 }
208
TEST_F(TestSessionInfo,OutOfBoundsPacketsBase)209 TEST_F(TestSessionInfo, OutOfBoundsPacketsBase) {
210 // Allow packets in the range 5-6.
211 packet_.seqNum = 0x0005;
212 packet_.video_header.is_first_packet_in_frame = true;
213 packet_.markerBit = false;
214 FillPacket(1);
215 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
216 packet_, frame_buffer_, frame_data)));
217 // Insert an older packet with a first packet set.
218 packet_.seqNum = 0x0004;
219 packet_.video_header.is_first_packet_in_frame = true;
220 packet_.markerBit = true;
221 FillPacket(1);
222 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
223 packet_.seqNum = 0x0006;
224 packet_.video_header.is_first_packet_in_frame = true;
225 packet_.markerBit = true;
226 FillPacket(1);
227 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
228 packet_, frame_buffer_, frame_data)));
229 packet_.seqNum = 0x0008;
230 packet_.video_header.is_first_packet_in_frame = false;
231 packet_.markerBit = true;
232 FillPacket(1);
233 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
234 }
235
TEST_F(TestSessionInfo,OutOfBoundsPacketsWrap)236 TEST_F(TestSessionInfo, OutOfBoundsPacketsWrap) {
237 packet_.seqNum = 0xFFFE;
238 packet_.video_header.is_first_packet_in_frame = true;
239 packet_.markerBit = false;
240 FillPacket(1);
241 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
242 packet_, frame_buffer_, frame_data)));
243
244 packet_.seqNum = 0x0004;
245 packet_.video_header.is_first_packet_in_frame = false;
246 packet_.markerBit = true;
247 FillPacket(1);
248 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
249 packet_, frame_buffer_, frame_data)));
250 packet_.seqNum = 0x0002;
251 packet_.video_header.is_first_packet_in_frame = false;
252 packet_.markerBit = false;
253 FillPacket(1);
254 ASSERT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
255 packet_, frame_buffer_, frame_data)));
256 packet_.seqNum = 0xFFF0;
257 packet_.video_header.is_first_packet_in_frame = false;
258 packet_.markerBit = false;
259 FillPacket(1);
260 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
261 packet_.seqNum = 0x0006;
262 packet_.video_header.is_first_packet_in_frame = false;
263 packet_.markerBit = false;
264 FillPacket(1);
265 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
266 }
267
TEST_F(TestSessionInfo,OutOfBoundsOutOfOrder)268 TEST_F(TestSessionInfo, OutOfBoundsOutOfOrder) {
269 // Insert out of bound regular packets, and then the first and last packet.
270 // Verify that correct bounds are maintained.
271 packet_.seqNum = 0x0003;
272 packet_.video_header.is_first_packet_in_frame = false;
273 packet_.markerBit = false;
274 FillPacket(1);
275 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
276 packet_, frame_buffer_, frame_data)));
277 // Insert an older packet with a first packet set.
278 packet_.seqNum = 0x0005;
279 packet_.video_header.is_first_packet_in_frame = true;
280 packet_.markerBit = false;
281 FillPacket(1);
282 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
283 packet_, frame_buffer_, frame_data)));
284 packet_.seqNum = 0x0004;
285 packet_.video_header.is_first_packet_in_frame = false;
286 packet_.markerBit = false;
287 FillPacket(1);
288 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
289 packet_.seqNum = 0x0010;
290 packet_.video_header.is_first_packet_in_frame = false;
291 packet_.markerBit = false;
292 FillPacket(1);
293 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
294 packet_, frame_buffer_, frame_data)));
295 packet_.seqNum = 0x0008;
296 packet_.video_header.is_first_packet_in_frame = false;
297 packet_.markerBit = true;
298 FillPacket(1);
299 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
300 packet_, frame_buffer_, frame_data)));
301
302 packet_.seqNum = 0x0009;
303 packet_.video_header.is_first_packet_in_frame = false;
304 packet_.markerBit = false;
305 FillPacket(1);
306 EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
307 }
308
TEST_F(TestNalUnits,OnlyReceivedEmptyPacket)309 TEST_F(TestNalUnits, OnlyReceivedEmptyPacket) {
310 packet_.video_header.is_first_packet_in_frame = false;
311 packet_.completeNALU = kNaluComplete;
312 packet_.video_header.frame_type = VideoFrameType::kEmptyFrame;
313 packet_.sizeBytes = 0;
314 packet_.seqNum = 0;
315 packet_.markerBit = false;
316 EXPECT_EQ(0, session_.InsertPacket(packet_, frame_buffer_, frame_data));
317
318 EXPECT_EQ(0U, session_.MakeDecodable());
319 EXPECT_EQ(0U, session_.SessionLength());
320 }
321
TEST_F(TestNalUnits,OneIsolatedNaluLoss)322 TEST_F(TestNalUnits, OneIsolatedNaluLoss) {
323 packet_.video_header.is_first_packet_in_frame = true;
324 packet_.completeNALU = kNaluComplete;
325 packet_.seqNum = 0;
326 packet_.markerBit = false;
327 FillPacket(0);
328 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
329 packet_, frame_buffer_, frame_data)));
330
331 packet_.video_header.is_first_packet_in_frame = false;
332 packet_.completeNALU = kNaluComplete;
333 packet_.seqNum += 2;
334 packet_.markerBit = true;
335 FillPacket(2);
336 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
337 packet_, frame_buffer_, frame_data)));
338
339 EXPECT_EQ(0U, session_.MakeDecodable());
340 EXPECT_EQ(2 * packet_buffer_size(), session_.SessionLength());
341 SCOPED_TRACE("Calling VerifyNalu");
342 EXPECT_TRUE(VerifyNalu(0, 1, 0));
343 SCOPED_TRACE("Calling VerifyNalu");
344 EXPECT_TRUE(VerifyNalu(1, 1, 2));
345 }
346
TEST_F(TestNalUnits,LossInMiddleOfNalu)347 TEST_F(TestNalUnits, LossInMiddleOfNalu) {
348 packet_.video_header.is_first_packet_in_frame = true;
349 packet_.completeNALU = kNaluComplete;
350 packet_.seqNum = 0;
351 packet_.markerBit = false;
352 FillPacket(0);
353 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
354 packet_, frame_buffer_, frame_data)));
355
356 packet_.video_header.is_first_packet_in_frame = false;
357 packet_.completeNALU = kNaluEnd;
358 packet_.seqNum += 2;
359 packet_.markerBit = true;
360 FillPacket(2);
361 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
362 packet_, frame_buffer_, frame_data)));
363
364 EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
365 EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
366 SCOPED_TRACE("Calling VerifyNalu");
367 EXPECT_TRUE(VerifyNalu(0, 1, 0));
368 }
369
TEST_F(TestNalUnits,StartAndEndOfLastNalUnitLost)370 TEST_F(TestNalUnits, StartAndEndOfLastNalUnitLost) {
371 packet_.video_header.is_first_packet_in_frame = true;
372 packet_.completeNALU = kNaluComplete;
373 packet_.seqNum = 0;
374 packet_.markerBit = false;
375 FillPacket(0);
376 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
377 packet_, frame_buffer_, frame_data)));
378
379 packet_.video_header.is_first_packet_in_frame = false;
380 packet_.completeNALU = kNaluIncomplete;
381 packet_.seqNum += 2;
382 packet_.markerBit = false;
383 FillPacket(1);
384 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
385 packet_, frame_buffer_, frame_data)));
386
387 EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
388 EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
389 SCOPED_TRACE("Calling VerifyNalu");
390 EXPECT_TRUE(VerifyNalu(0, 1, 0));
391 }
392
TEST_F(TestNalUnits,ReorderWrapNoLoss)393 TEST_F(TestNalUnits, ReorderWrapNoLoss) {
394 packet_.seqNum = 0xFFFF;
395 packet_.video_header.is_first_packet_in_frame = false;
396 packet_.completeNALU = kNaluIncomplete;
397 packet_.seqNum += 1;
398 packet_.markerBit = false;
399 FillPacket(1);
400 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
401 packet_, frame_buffer_, frame_data)));
402
403 packet_.video_header.is_first_packet_in_frame = true;
404 packet_.completeNALU = kNaluComplete;
405 packet_.seqNum -= 1;
406 packet_.markerBit = false;
407 FillPacket(0);
408 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
409 packet_, frame_buffer_, frame_data)));
410
411 packet_.video_header.is_first_packet_in_frame = false;
412 packet_.completeNALU = kNaluEnd;
413 packet_.seqNum += 2;
414 packet_.markerBit = true;
415 FillPacket(2);
416 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
417 packet_, frame_buffer_, frame_data)));
418
419 EXPECT_EQ(0U, session_.MakeDecodable());
420 EXPECT_EQ(3 * packet_buffer_size(), session_.SessionLength());
421 SCOPED_TRACE("Calling VerifyNalu");
422 EXPECT_TRUE(VerifyNalu(0, 1, 0));
423 }
424
TEST_F(TestNalUnits,WrapLosses)425 TEST_F(TestNalUnits, WrapLosses) {
426 packet_.seqNum = 0xFFFF;
427 packet_.video_header.is_first_packet_in_frame = false;
428 packet_.completeNALU = kNaluIncomplete;
429 packet_.markerBit = false;
430 FillPacket(1);
431 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
432 packet_, frame_buffer_, frame_data)));
433
434 packet_.video_header.is_first_packet_in_frame = false;
435 packet_.completeNALU = kNaluEnd;
436 packet_.seqNum += 2;
437 packet_.markerBit = true;
438 FillPacket(2);
439 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
440 packet_, frame_buffer_, frame_data)));
441
442 EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
443 EXPECT_EQ(0U, session_.SessionLength());
444 }
445
TEST_F(TestNalUnits,ReorderWrapLosses)446 TEST_F(TestNalUnits, ReorderWrapLosses) {
447 packet_.seqNum = 0xFFFF;
448
449 packet_.video_header.is_first_packet_in_frame = false;
450 packet_.completeNALU = kNaluEnd;
451 packet_.seqNum += 2;
452 packet_.markerBit = true;
453 FillPacket(2);
454 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
455 packet_, frame_buffer_, frame_data)));
456
457 packet_.seqNum -= 2;
458 packet_.video_header.is_first_packet_in_frame = false;
459 packet_.completeNALU = kNaluIncomplete;
460 packet_.markerBit = false;
461 FillPacket(1);
462 EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
463 packet_, frame_buffer_, frame_data)));
464
465 EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
466 EXPECT_EQ(0U, session_.SessionLength());
467 }
468
469 } // namespace webrtc
470