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