blob: 49afa148e9842f9d69bb2a2158f964c1d46307c2 [file] [log] [blame]
philipelc707ab72016-04-01 02:01:54 -07001/*
2 * Copyright (c) 2016 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 */
Danil Chapovalov05269ec2019-10-17 19:06:46 +020010#include "modules/video_coding/packet_buffer.h"
philipelc707ab72016-04-01 02:01:54 -070011
12#include <cstring>
Danil Chapovalov05269ec2019-10-17 19:06:46 +020013#include <limits>
Danil Chapovalov1dac7072019-10-24 12:44:23 +020014#include <ostream>
Danil Chapovalov05269ec2019-10-17 19:06:46 +020015#include <string>
philipela1059872016-05-09 11:41:48 +020016#include <utility>
philipelc707ab72016-04-01 02:01:54 -070017
Danil Chapovalov1dac7072019-10-24 12:44:23 +020018#include "api/array_view.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "common_video/h264/h264_common.h"
20#include "modules/video_coding/frame_object.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/random.h"
Rasmus Brandtedf4ff72017-10-24 10:07:48 +020022#include "test/field_trial.h"
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020023#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "test/gtest.h"
philipelc707ab72016-04-01 02:01:54 -070025
26namespace webrtc {
27namespace video_coding {
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020028namespace {
philipelc707ab72016-04-01 02:01:54 -070029
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020030using ::testing::ElementsAre;
Danil Chapovalov1dac7072019-10-24 12:44:23 +020031using ::testing::ElementsAreArray;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020032using ::testing::IsEmpty;
Danil Chapovalov1dac7072019-10-24 12:44:23 +020033using ::testing::Matches;
34using ::testing::Pointee;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020035using ::testing::SizeIs;
36
Danil Chapovalov1dac7072019-10-24 12:44:23 +020037constexpr int kStartSize = 16;
38constexpr int kMaxSize = 64;
39
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020040void IgnoreResult(PacketBuffer::InsertResult /*result*/) {}
41
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010042// Validates frame boundaries are valid and returns first sequence_number for
43// each frame.
Danil Chapovalov1dac7072019-10-24 12:44:23 +020044std::vector<uint16_t> StartSeqNums(
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010045 rtc::ArrayView<const std::unique_ptr<PacketBuffer::Packet>> packets) {
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020046 std::vector<uint16_t> result;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010047 bool frame_boundary = true;
48 for (const auto& packet : packets) {
49 EXPECT_EQ(frame_boundary, packet->is_first_packet_in_frame());
50 if (packet->is_first_packet_in_frame()) {
51 result.push_back(packet->seq_num);
52 }
53 frame_boundary = packet->is_last_packet_in_frame();
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020054 }
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010055 EXPECT_TRUE(frame_boundary);
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020056 return result;
57}
58
Danil Chapovalov1dac7072019-10-24 12:44:23 +020059MATCHER_P(StartSeqNumsAre, seq_num, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010060 return Matches(ElementsAre(seq_num))(StartSeqNums(arg.packets));
Danil Chapovalov1dac7072019-10-24 12:44:23 +020061}
62
63MATCHER_P2(StartSeqNumsAre, seq_num1, seq_num2, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010064 return Matches(ElementsAre(seq_num1, seq_num2))(StartSeqNums(arg.packets));
Danil Chapovalov1dac7072019-10-24 12:44:23 +020065}
66
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020067MATCHER(KeyFrame, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010068 return arg->is_first_packet_in_frame() &&
69 arg->video_header.frame_type == VideoFrameType::kVideoFrameKey;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020070}
71
72MATCHER(DeltaFrame, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010073 return arg->is_first_packet_in_frame() &&
74 arg->video_header.frame_type == VideoFrameType::kVideoFrameDelta;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020075}
76
Danil Chapovalov1dac7072019-10-24 12:44:23 +020077struct PacketBufferInsertResult : public PacketBuffer::InsertResult {
78 explicit PacketBufferInsertResult(PacketBuffer::InsertResult result)
79 : InsertResult(std::move(result)) {}
80};
81
82void PrintTo(const PacketBufferInsertResult& result, std::ostream* os) {
83 *os << "frames: { ";
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010084 for (const auto& packet : result.packets) {
85 if (packet->is_first_packet_in_frame() &&
86 packet->is_last_packet_in_frame()) {
87 *os << "{sn: " << packet->seq_num << " }";
88 } else if (packet->is_first_packet_in_frame()) {
89 *os << "{sn: [" << packet->seq_num << "-";
90 } else if (packet->is_last_packet_in_frame()) {
91 *os << packet->seq_num << "] }, ";
Danil Chapovalov1dac7072019-10-24 12:44:23 +020092 }
Danil Chapovalov1dac7072019-10-24 12:44:23 +020093 }
94 *os << " }";
95 if (result.buffer_cleared) {
96 *os << ", buffer_cleared";
97 }
98}
99
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200100class PacketBufferTest : public ::testing::Test {
philipelc707ab72016-04-01 02:01:54 -0700101 protected:
philipelce423ce2021-04-12 13:42:03 +0200102 PacketBufferTest() : rand_(0x7732213), packet_buffer_(kStartSize, kMaxSize) {}
philipelc707ab72016-04-01 02:01:54 -0700103
philipel17deeb42016-08-11 15:09:26 +0200104 uint16_t Rand() { return rand_.Rand<uint16_t>(); }
philipelc707ab72016-04-01 02:01:54 -0700105
philipel17deeb42016-08-11 15:09:26 +0200106 enum IsKeyFrame { kKeyFrame, kDeltaFrame };
107 enum IsFirst { kFirst, kNotFirst };
108 enum IsLast { kLast, kNotLast };
philipelc707ab72016-04-01 02:01:54 -0700109
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200110 PacketBufferInsertResult Insert(uint16_t seq_num, // packet sequence number
111 IsKeyFrame keyframe, // is keyframe
112 IsFirst first, // is first packet of frame
113 IsLast last, // is last packet of frame
Danil Chapovalove3c48842019-12-02 15:54:27 +0100114 rtc::ArrayView<const uint8_t> data = {},
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200115 uint32_t timestamp = 123u) { // rtp timestamp
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100116 auto packet = std::make_unique<PacketBuffer::Packet>();
117 packet->video_header.codec = kVideoCodecGeneric;
118 packet->timestamp = timestamp;
119 packet->seq_num = seq_num;
120 packet->video_header.frame_type = keyframe == kKeyFrame
121 ? VideoFrameType::kVideoFrameKey
122 : VideoFrameType::kVideoFrameDelta;
123 packet->video_header.is_first_packet_in_frame = first == kFirst;
124 packet->video_header.is_last_packet_in_frame = last == kLast;
125 packet->video_payload.SetData(data.data(), data.size());
philipelf4139332016-04-20 10:26:34 +0200126
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100127 return PacketBufferInsertResult(
128 packet_buffer_.InsertPacket(std::move(packet)));
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200129 }
130
philipelc707ab72016-04-01 02:01:54 -0700131 Random rand_;
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200132 PacketBuffer packet_buffer_;
philipelc707ab72016-04-01 02:01:54 -0700133};
134
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200135TEST_F(PacketBufferTest, InsertOnePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100136 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100137 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
philipelc707ab72016-04-01 02:01:54 -0700138}
139
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200140TEST_F(PacketBufferTest, InsertMultiplePackets) {
philipelaee3e0e2016-11-01 11:45:34 +0100141 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100142 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
143 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
144 EXPECT_THAT(Insert(seq_num + 2, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
145 EXPECT_THAT(Insert(seq_num + 3, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
philipelc707ab72016-04-01 02:01:54 -0700146}
147
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200148TEST_F(PacketBufferTest, InsertDuplicatePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100149 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100150 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
151 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
152 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast).packets,
153 SizeIs(2));
philipelaee3e0e2016-11-01 11:45:34 +0100154}
155
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200156TEST_F(PacketBufferTest, SeqNumWrapOneFrame) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200157 Insert(0xFFFF, kKeyFrame, kFirst, kNotLast);
158 EXPECT_THAT(Insert(0x0, kKeyFrame, kNotFirst, kLast),
159 StartSeqNumsAre(0xFFFF));
philipel2c2f34c2017-01-03 05:55:34 -0800160}
161
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200162TEST_F(PacketBufferTest, SeqNumWrapTwoFrames) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200163 EXPECT_THAT(Insert(0xFFFF, kKeyFrame, kFirst, kLast),
164 StartSeqNumsAre(0xFFFF));
165 EXPECT_THAT(Insert(0x0, kKeyFrame, kFirst, kLast), StartSeqNumsAre(0x0));
philipelaee3e0e2016-11-01 11:45:34 +0100166}
167
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200168TEST_F(PacketBufferTest, InsertOldPackets) {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100169 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
170 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
171 EXPECT_THAT(Insert(101, kKeyFrame, kNotFirst, kLast).packets, SizeIs(2));
philipelaee3e0e2016-11-01 11:45:34 +0100172
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100173 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
174 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
175 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipelaee3e0e2016-11-01 11:45:34 +0100176
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200177 packet_buffer_.ClearTo(102);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100178 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, IsEmpty());
179 EXPECT_THAT(Insert(103, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipel5ceaaae2016-05-24 10:20:47 +0200180}
181
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200182TEST_F(PacketBufferTest, FrameSize) {
philipelaee3e0e2016-11-01 11:45:34 +0100183 const uint16_t seq_num = Rand();
Danil Chapovalove3c48842019-12-02 15:54:27 +0100184 uint8_t data1[5] = {};
185 uint8_t data2[5] = {};
186 uint8_t data3[5] = {};
187 uint8_t data4[5] = {};
philipel5ceaaae2016-05-24 10:20:47 +0200188
Danil Chapovalove3c48842019-12-02 15:54:27 +0100189 Insert(seq_num, kKeyFrame, kFirst, kNotLast, data1);
190 Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast, data2);
191 Insert(seq_num + 2, kKeyFrame, kNotFirst, kNotLast, data3);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100192 auto packets =
193 Insert(seq_num + 3, kKeyFrame, kNotFirst, kLast, data4).packets;
194 // Expect one frame of 4 packets.
195 EXPECT_THAT(StartSeqNums(packets), ElementsAre(seq_num));
196 EXPECT_THAT(packets, SizeIs(4));
philipel5ceaaae2016-05-24 10:20:47 +0200197}
198
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200199TEST_F(PacketBufferTest, ExpandBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100200 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700201
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200202 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
Johannes Krona3705562019-08-26 16:37:11 +0200203 for (int i = 1; i < kStartSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200204 EXPECT_FALSE(
205 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200206
207 // Already inserted kStartSize number of packets, inserting the last packet
208 // should increase the buffer size and also result in an assembled frame.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200209 EXPECT_FALSE(
210 Insert(seq_num + kStartSize, kKeyFrame, kNotFirst, kLast).buffer_cleared);
philipelc707ab72016-04-01 02:01:54 -0700211}
212
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200213TEST_F(PacketBufferTest, SingleFrameExpandsBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100214 const uint16_t seq_num = Rand();
215
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200216 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
philipelaee3e0e2016-11-01 11:45:34 +0100217 for (int i = 1; i < kStartSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200218 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast);
219 EXPECT_THAT(Insert(seq_num + kStartSize, kKeyFrame, kNotFirst, kLast),
220 StartSeqNumsAre(seq_num));
philipelaee3e0e2016-11-01 11:45:34 +0100221}
222
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200223TEST_F(PacketBufferTest, ExpandBufferOverflow) {
philipelaee3e0e2016-11-01 11:45:34 +0100224 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700225
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200226 EXPECT_FALSE(Insert(seq_num, kKeyFrame, kFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200227 for (int i = 1; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200228 EXPECT_FALSE(
229 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200230
231 // Already inserted kMaxSize number of packets, inserting the last packet
232 // should overflow the buffer and result in false being returned.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200233 EXPECT_TRUE(
234 Insert(seq_num + kMaxSize, kKeyFrame, kNotFirst, kLast).buffer_cleared);
philipelc707ab72016-04-01 02:01:54 -0700235}
236
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200237TEST_F(PacketBufferTest, OnePacketOneFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100238 const uint16_t seq_num = Rand();
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200239 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
240 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700241}
242
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200243TEST_F(PacketBufferTest, TwoPacketsTwoFrames) {
philipelaee3e0e2016-11-01 11:45:34 +0100244 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200245
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200246 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
247 StartSeqNumsAre(seq_num));
248 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kFirst, kLast),
249 StartSeqNumsAre(seq_num + 1));
philipelc707ab72016-04-01 02:01:54 -0700250}
251
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200252TEST_F(PacketBufferTest, TwoPacketsOneFrames) {
philipelaee3e0e2016-11-01 11:45:34 +0100253 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200254
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100255 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200256 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast),
257 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700258}
259
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200260TEST_F(PacketBufferTest, ThreePacketReorderingOneFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100261 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700262
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100263 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
264 EXPECT_THAT(Insert(seq_num + 2, kKeyFrame, kNotFirst, kLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200265 IsEmpty());
266 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast),
267 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700268}
269
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200270TEST_F(PacketBufferTest, Frames) {
philipelaee3e0e2016-11-01 11:45:34 +0100271 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200272
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200273 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
274 StartSeqNumsAre(seq_num));
275 EXPECT_THAT(Insert(seq_num + 1, kDeltaFrame, kFirst, kLast),
276 StartSeqNumsAre(seq_num + 1));
277 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast),
278 StartSeqNumsAre(seq_num + 2));
279 EXPECT_THAT(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast),
280 StartSeqNumsAre(seq_num + 3));
philipelf4139332016-04-20 10:26:34 +0200281}
282
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200283TEST_F(PacketBufferTest, ClearSinglePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100284 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200285
philipelaee3e0e2016-11-01 11:45:34 +0100286 for (int i = 0; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200287 Insert(seq_num + i, kDeltaFrame, kFirst, kLast);
philipelaee3e0e2016-11-01 11:45:34 +0100288
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200289 packet_buffer_.ClearTo(seq_num);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200290 EXPECT_FALSE(
291 Insert(seq_num + kMaxSize, kDeltaFrame, kFirst, kLast).buffer_cleared);
philipelaee3e0e2016-11-01 11:45:34 +0100292}
293
philipel90623e12022-04-28 14:31:55 +0200294TEST_F(PacketBufferTest, ClearPacketBeforeFullyReceivedFrame) {
295 Insert(0, kKeyFrame, kFirst, kNotLast);
296 Insert(1, kKeyFrame, kNotFirst, kNotLast);
297 packet_buffer_.ClearTo(0);
298 EXPECT_THAT(Insert(2, kKeyFrame, kNotFirst, kLast).packets, IsEmpty());
299}
300
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200301TEST_F(PacketBufferTest, ClearFullBuffer) {
philipelc5fb4682017-08-02 04:28:57 -0700302 for (int i = 0; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200303 Insert(i, kDeltaFrame, kFirst, kLast);
philipelc5fb4682017-08-02 04:28:57 -0700304
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200305 packet_buffer_.ClearTo(kMaxSize - 1);
philipelc5fb4682017-08-02 04:28:57 -0700306
307 for (int i = kMaxSize; i < 2 * kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200308 EXPECT_FALSE(Insert(i, kDeltaFrame, kFirst, kLast).buffer_cleared);
philipelc5fb4682017-08-02 04:28:57 -0700309}
310
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200311TEST_F(PacketBufferTest, DontClearNewerPacket) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200312 EXPECT_THAT(Insert(0, kKeyFrame, kFirst, kLast), StartSeqNumsAre(0));
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200313 packet_buffer_.ClearTo(0);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200314 EXPECT_THAT(Insert(2 * kStartSize, kKeyFrame, kFirst, kLast),
315 StartSeqNumsAre(2 * kStartSize));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100316 EXPECT_THAT(Insert(3 * kStartSize + 1, kKeyFrame, kFirst, kNotLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200317 IsEmpty());
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200318 packet_buffer_.ClearTo(2 * kStartSize);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200319 EXPECT_THAT(Insert(3 * kStartSize + 2, kKeyFrame, kNotFirst, kLast),
320 StartSeqNumsAre(3 * kStartSize + 1));
philipelc5fb4682017-08-02 04:28:57 -0700321}
322
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200323TEST_F(PacketBufferTest, OneIncompleteFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100324 const uint16_t seq_num = Rand();
325
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100326 EXPECT_THAT(Insert(seq_num, kDeltaFrame, kFirst, kNotLast).packets,
327 IsEmpty());
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200328 EXPECT_THAT(Insert(seq_num + 1, kDeltaFrame, kNotFirst, kLast),
329 StartSeqNumsAre(seq_num));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100330 EXPECT_THAT(Insert(seq_num - 1, kDeltaFrame, kNotFirst, kLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200331 IsEmpty());
philipelaee3e0e2016-11-01 11:45:34 +0100332}
333
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200334TEST_F(PacketBufferTest, TwoIncompleteFramesFullBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100335 const uint16_t seq_num = Rand();
336
337 for (int i = 1; i < kMaxSize - 1; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200338 Insert(seq_num + i, kDeltaFrame, kNotFirst, kNotLast);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100339 EXPECT_THAT(Insert(seq_num, kDeltaFrame, kFirst, kNotLast).packets,
340 IsEmpty());
341 EXPECT_THAT(Insert(seq_num - 1, kDeltaFrame, kNotFirst, kLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200342 IsEmpty());
philipelaee3e0e2016-11-01 11:45:34 +0100343}
344
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200345TEST_F(PacketBufferTest, FramesReordered) {
philipelaee3e0e2016-11-01 11:45:34 +0100346 const uint16_t seq_num = Rand();
347
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200348 EXPECT_THAT(Insert(seq_num + 1, kDeltaFrame, kFirst, kLast),
349 StartSeqNumsAre(seq_num + 1));
350 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
351 StartSeqNumsAre(seq_num));
352 EXPECT_THAT(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast),
353 StartSeqNumsAre(seq_num + 3));
354 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast),
355 StartSeqNumsAre(seq_num + 2));
philipelf4139332016-04-20 10:26:34 +0200356}
357
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200358TEST_F(PacketBufferTest, InsertPacketAfterSequenceNumberWrapAround) {
Johannes Kron957c62e2018-10-01 14:53:01 +0200359 uint16_t kFirstSeqNum = 0;
360 uint32_t kTimestampDelta = 100;
361 uint32_t timestamp = 10000;
362 uint16_t seq_num = kFirstSeqNum;
363
364 // Loop until seq_num wraps around.
Philip Eliasson1f850a62019-03-19 12:15:00 +0000365 SeqNumUnwrapper<uint16_t> unwrapper;
Johannes Kron957c62e2018-10-01 14:53:01 +0200366 while (unwrapper.Unwrap(seq_num) < std::numeric_limits<uint16_t>::max()) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100367 Insert(seq_num++, kKeyFrame, kFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200368 for (int i = 0; i < 5; ++i) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100369 Insert(seq_num++, kKeyFrame, kNotFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200370 }
Danil Chapovalove3c48842019-12-02 15:54:27 +0100371 Insert(seq_num++, kKeyFrame, kNotFirst, kLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200372 timestamp += kTimestampDelta;
373 }
374
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200375 // Receive frame with overlapping sequence numbers.
Danil Chapovalove3c48842019-12-02 15:54:27 +0100376 Insert(seq_num++, kKeyFrame, kFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200377 for (int i = 0; i < 5; ++i) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100378 Insert(seq_num++, kKeyFrame, kNotFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200379 }
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100380 auto packets =
381 Insert(seq_num++, kKeyFrame, kNotFirst, kLast, {}, timestamp).packets;
382 // One frame of 7 packets.
383 EXPECT_THAT(StartSeqNums(packets), SizeIs(1));
384 EXPECT_THAT(packets, SizeIs(7));
Johannes Kron957c62e2018-10-01 14:53:01 +0200385}
386
Artem Titovdcd7fc72021-08-09 13:02:57 +0200387// If `sps_pps_idr_is_keyframe` is true, we require keyframes to contain
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100388// SPS/PPS/IDR and the keyframes we create as part of the test do contain
Artem Titovdcd7fc72021-08-09 13:02:57 +0200389// SPS/PPS/IDR. If `sps_pps_idr_is_keyframe` is false, we only require and
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100390// create keyframes containing only IDR.
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200391class PacketBufferH264Test : public PacketBufferTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200392 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200393 explicit PacketBufferH264Test(bool sps_pps_idr_is_keyframe)
Eldar Rello2127aaa2020-08-07 12:08:14 +0300394 : PacketBufferTest(), sps_pps_idr_is_keyframe_(sps_pps_idr_is_keyframe) {
395 if (sps_pps_idr_is_keyframe) {
396 packet_buffer_.ForceSpsPpsIdrIsH264Keyframe();
397 }
398 }
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200399
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200400 PacketBufferInsertResult InsertH264(
Danil Chapovalove3c48842019-12-02 15:54:27 +0100401 uint16_t seq_num, // packet sequence number
402 IsKeyFrame keyframe, // is keyframe
403 IsFirst first, // is first packet of frame
404 IsLast last, // is last packet of frame
405 uint32_t timestamp, // rtp timestamp
406 rtc::ArrayView<const uint8_t> data = {},
407 uint32_t width = 0, // width of frame (SPS/IDR)
408 uint32_t height = 0) { // height of frame (SPS/IDR)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100409 auto packet = std::make_unique<PacketBuffer::Packet>();
410 packet->video_header.codec = kVideoCodecH264;
philipel7d745e52018-08-02 14:03:53 +0200411 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100412 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
413 packet->seq_num = seq_num;
414 packet->timestamp = timestamp;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200415 if (keyframe == kKeyFrame) {
416 if (sps_pps_idr_is_keyframe_) {
philipel7d745e52018-08-02 14:03:53 +0200417 h264_header.nalus[0].type = H264::NaluType::kSps;
418 h264_header.nalus[1].type = H264::NaluType::kPps;
419 h264_header.nalus[2].type = H264::NaluType::kIdr;
420 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200421 } else {
philipel7d745e52018-08-02 14:03:53 +0200422 h264_header.nalus[0].type = H264::NaluType::kIdr;
423 h264_header.nalus_length = 1;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200424 }
425 }
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100426 packet->video_header.width = width;
427 packet->video_header.height = height;
428 packet->video_header.is_first_packet_in_frame = first == kFirst;
429 packet->video_header.is_last_packet_in_frame = last == kLast;
430 packet->video_payload.SetData(data.data(), data.size());
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200431
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100432 return PacketBufferInsertResult(
433 packet_buffer_.InsertPacket(std::move(packet)));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200434 }
435
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200436 PacketBufferInsertResult InsertH264KeyFrameWithAud(
Danil Chapovalove3c48842019-12-02 15:54:27 +0100437 uint16_t seq_num, // packet sequence number
438 IsKeyFrame keyframe, // is keyframe
439 IsFirst first, // is first packet of frame
440 IsLast last, // is last packet of frame
441 uint32_t timestamp, // rtp timestamp
442 rtc::ArrayView<const uint8_t> data = {},
443 uint32_t width = 0, // width of frame (SPS/IDR)
444 uint32_t height = 0) { // height of frame (SPS/IDR)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100445 auto packet = std::make_unique<PacketBuffer::Packet>();
446 packet->video_header.codec = kVideoCodecH264;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700447 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100448 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
449 packet->seq_num = seq_num;
450 packet->timestamp = timestamp;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700451
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200452 // this should be the start of frame.
453 RTC_CHECK(first == kFirst);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700454
455 // Insert a AUD NALU / packet without width/height.
456 h264_header.nalus[0].type = H264::NaluType::kAud;
457 h264_header.nalus_length = 1;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100458 packet->video_header.is_first_packet_in_frame = true;
459 packet->video_header.is_last_packet_in_frame = false;
460 IgnoreResult(packet_buffer_.InsertPacket(std::move(packet)));
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200461 // insert IDR
Danil Chapovalove3c48842019-12-02 15:54:27 +0100462 return InsertH264(seq_num + 1, keyframe, kNotFirst, last, timestamp, data,
463 width, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700464 }
465
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200466 const bool sps_pps_idr_is_keyframe_;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100467};
468
469// This fixture is used to test the general behaviour of the packet buffer
470// in both configurations.
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200471class PacketBufferH264ParameterizedTest
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100472 : public ::testing::WithParamInterface<bool>,
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200473 public PacketBufferH264Test {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100474 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200475 PacketBufferH264ParameterizedTest() : PacketBufferH264Test(GetParam()) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200476};
477
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100478INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200479 PacketBufferH264ParameterizedTest,
480 ::testing::Bool());
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200481
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200482TEST_P(PacketBufferH264ParameterizedTest, DontRemoveMissingPacketOnClearTo) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200483 InsertH264(0, kKeyFrame, kFirst, kLast, 0);
484 InsertH264(2, kDeltaFrame, kFirst, kNotLast, 2);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200485 packet_buffer_.ClearTo(0);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200486 // Expect no frame because of missing of packet #1
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100487 EXPECT_THAT(InsertH264(3, kDeltaFrame, kNotFirst, kLast, 2).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200488 IsEmpty());
philipelbc5a4082017-12-06 10:41:08 +0100489}
490
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200491TEST_P(PacketBufferH264ParameterizedTest, GetBitstreamOneFrameFullBuffer) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100492 uint8_t data_arr[kStartSize][1];
philipel227f8b92017-08-04 06:39:31 -0700493 uint8_t expected[kStartSize];
philipel227f8b92017-08-04 06:39:31 -0700494
495 for (uint8_t i = 0; i < kStartSize; ++i) {
philipel227f8b92017-08-04 06:39:31 -0700496 data_arr[i][0] = i;
497 expected[i] = i;
498 }
499
Danil Chapovalove3c48842019-12-02 15:54:27 +0100500 InsertH264(0, kKeyFrame, kFirst, kNotLast, 1, data_arr[0]);
philipel227f8b92017-08-04 06:39:31 -0700501 for (uint8_t i = 1; i < kStartSize - 1; ++i) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100502 InsertH264(i, kKeyFrame, kNotFirst, kNotLast, 1, data_arr[i]);
philipel227f8b92017-08-04 06:39:31 -0700503 }
philipel227f8b92017-08-04 06:39:31 -0700504
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100505 auto packets = InsertH264(kStartSize - 1, kKeyFrame, kNotFirst, kLast, 1,
506 data_arr[kStartSize - 1])
507 .packets;
508 ASSERT_THAT(StartSeqNums(packets), ElementsAre(0));
509 EXPECT_THAT(packets, SizeIs(kStartSize));
510 for (size_t i = 0; i < packets.size(); ++i) {
511 EXPECT_THAT(packets[i]->video_payload, SizeIs(1)) << "Packet #" << i;
512 }
philipel227f8b92017-08-04 06:39:31 -0700513}
514
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200515TEST_P(PacketBufferH264ParameterizedTest, GetBitstreamBufferPadding) {
philipel36928452016-11-07 10:42:36 +0100516 uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100517 rtc::CopyOnWriteBuffer data = "some plain old data";
philipel36928452016-11-07 10:42:36 +0100518
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100519 auto packet = std::make_unique<PacketBuffer::Packet>();
philipel7d745e52018-08-02 14:03:53 +0200520 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100521 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200522 h264_header.nalus_length = 1;
523 h264_header.nalus[0].type = H264::NaluType::kIdr;
524 h264_header.packetization_type = kH264SingleNalu;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100525 packet->seq_num = seq_num;
526 packet->video_header.codec = kVideoCodecH264;
527 packet->video_payload = data;
528 packet->video_header.is_first_packet_in_frame = true;
529 packet->video_header.is_last_packet_in_frame = true;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100530 auto frames = packet_buffer_.InsertPacket(std::move(packet)).packets;
philipel36928452016-11-07 10:42:36 +0100531
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200532 ASSERT_THAT(frames, SizeIs(1));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100533 EXPECT_EQ(frames[0]->seq_num, seq_num);
534 EXPECT_EQ(frames[0]->video_payload, data);
philipel36928452016-11-07 10:42:36 +0100535}
536
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200537TEST_P(PacketBufferH264ParameterizedTest, FrameResolution) {
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700538 uint16_t seq_num = 100;
Danil Chapovalove3c48842019-12-02 15:54:27 +0100539 uint8_t data[] = "some plain old data";
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700540 uint32_t width = 640;
541 uint32_t height = 360;
542 uint32_t timestamp = 1000;
543
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100544 auto packets = InsertH264(seq_num, kKeyFrame, kFirst, kLast, timestamp, data,
545 width, height)
546 .packets;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700547
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100548 ASSERT_THAT(packets, SizeIs(1));
549 EXPECT_EQ(packets[0]->video_header.width, width);
550 EXPECT_EQ(packets[0]->video_header.height, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700551}
552
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200553TEST_P(PacketBufferH264ParameterizedTest, FrameResolutionNaluBeforeSPS) {
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700554 uint16_t seq_num = 100;
Danil Chapovalove3c48842019-12-02 15:54:27 +0100555 uint8_t data[] = "some plain old data";
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700556 uint32_t width = 640;
557 uint32_t height = 360;
558 uint32_t timestamp = 1000;
559
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100560 auto packets = InsertH264KeyFrameWithAud(seq_num, kKeyFrame, kFirst, kLast,
561 timestamp, data, width, height)
562 .packets;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700563
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100564 ASSERT_THAT(StartSeqNums(packets), ElementsAre(seq_num));
565 EXPECT_EQ(packets[0]->video_header.width, width);
566 EXPECT_EQ(packets[0]->video_header.height, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700567}
568
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200569TEST_F(PacketBufferTest, FreeSlotsOnFrameCreation) {
philipelaee3e0e2016-11-01 11:45:34 +0100570 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200571
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200572 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
573 Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast);
574 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast),
575 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700576
philipel17deeb42016-08-11 15:09:26 +0200577 // Insert frame that fills the whole buffer.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200578 Insert(seq_num + 3, kKeyFrame, kFirst, kNotLast);
philipel17deeb42016-08-11 15:09:26 +0200579 for (int i = 0; i < kMaxSize - 2; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200580 Insert(seq_num + i + 4, kDeltaFrame, kNotFirst, kNotLast);
581 EXPECT_THAT(Insert(seq_num + kMaxSize + 2, kKeyFrame, kNotFirst, kLast),
582 StartSeqNumsAre(seq_num + 3));
philipelc707ab72016-04-01 02:01:54 -0700583}
584
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200585TEST_F(PacketBufferTest, Clear) {
philipelaee3e0e2016-11-01 11:45:34 +0100586 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200587
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200588 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
589 Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast);
590 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast),
591 StartSeqNumsAre(seq_num));
philipelf4139332016-04-20 10:26:34 +0200592
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200593 packet_buffer_.Clear();
philipelf4139332016-04-20 10:26:34 +0200594
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200595 Insert(seq_num + kStartSize, kKeyFrame, kFirst, kNotLast);
596 Insert(seq_num + kStartSize + 1, kDeltaFrame, kNotFirst, kNotLast);
597 EXPECT_THAT(Insert(seq_num + kStartSize + 2, kDeltaFrame, kNotFirst, kLast),
598 StartSeqNumsAre(seq_num + kStartSize));
philipelc707ab72016-04-01 02:01:54 -0700599}
600
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200601TEST_F(PacketBufferTest, FramesAfterClear) {
philipel20dce342016-11-28 16:14:57 +0100602 Insert(9025, kDeltaFrame, kFirst, kLast);
603 Insert(9024, kKeyFrame, kFirst, kLast);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200604 packet_buffer_.ClearTo(9025);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100605 EXPECT_THAT(Insert(9057, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
606 EXPECT_THAT(Insert(9026, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipel20dce342016-11-28 16:14:57 +0100607}
608
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200609TEST_F(PacketBufferTest, SameFrameDifferentTimestamps) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100610 Insert(0, kKeyFrame, kFirst, kNotLast, {}, 1000);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100611 EXPECT_THAT(Insert(1, kKeyFrame, kNotFirst, kLast, {}, 1001).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200612 IsEmpty());
philipel8b6995b2019-01-09 12:39:18 +0100613}
614
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200615TEST_F(PacketBufferTest, ContinuousSeqNumDoubleMarkerBit) {
philipelea142f82017-01-11 02:01:56 -0800616 Insert(2, kKeyFrame, kNotFirst, kNotLast);
617 Insert(1, kKeyFrame, kFirst, kLast);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100618 EXPECT_THAT(Insert(3, kKeyFrame, kNotFirst, kLast).packets, IsEmpty());
philipelea142f82017-01-11 02:01:56 -0800619}
620
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200621TEST_F(PacketBufferTest, IncomingCodecChange) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100622 auto packet = std::make_unique<PacketBuffer::Packet>();
623 packet->video_header.is_first_packet_in_frame = true;
624 packet->video_header.is_last_packet_in_frame = true;
625 packet->video_header.codec = kVideoCodecVP8;
626 packet->video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
627 packet->timestamp = 1;
628 packet->seq_num = 1;
629 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100630 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
631 SizeIs(1));
philipel09133af2018-05-17 14:11:09 +0200632
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100633 packet = std::make_unique<PacketBuffer::Packet>();
634 packet->video_header.is_first_packet_in_frame = true;
635 packet->video_header.is_last_packet_in_frame = true;
636 packet->video_header.codec = kVideoCodecH264;
philipel7d745e52018-08-02 14:03:53 +0200637 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100638 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200639 h264_header.nalus_length = 1;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100640 packet->timestamp = 3;
641 packet->seq_num = 3;
642 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100643 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
644 IsEmpty());
philipel09133af2018-05-17 14:11:09 +0200645
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100646 packet = std::make_unique<PacketBuffer::Packet>();
647 packet->video_header.is_first_packet_in_frame = true;
648 packet->video_header.is_last_packet_in_frame = true;
649 packet->video_header.codec = kVideoCodecVP8;
650 packet->video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
651 packet->timestamp = 2;
652 packet->seq_num = 2;
653 packet->video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100654 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
655 SizeIs(2));
philipel09133af2018-05-17 14:11:09 +0200656}
657
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200658TEST_F(PacketBufferTest, TooManyNalusInPacket) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100659 auto packet = std::make_unique<PacketBuffer::Packet>();
660 packet->video_header.codec = kVideoCodecH264;
661 packet->timestamp = 1;
662 packet->seq_num = 1;
663 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
664 packet->video_header.is_first_packet_in_frame = true;
665 packet->video_header.is_last_packet_in_frame = true;
philipel7d745e52018-08-02 14:03:53 +0200666 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100667 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200668 h264_header.nalus_length = kMaxNalusPerPacket;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100669 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
670 IsEmpty());
philipel09133af2018-05-17 14:11:09 +0200671}
672
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200673TEST_P(PacketBufferH264ParameterizedTest, OneFrameFillBuffer) {
philipel2c9f9f22017-06-13 02:47:28 -0700674 InsertH264(0, kKeyFrame, kFirst, kNotLast, 1000);
675 for (int i = 1; i < kStartSize - 1; ++i)
676 InsertH264(i, kKeyFrame, kNotFirst, kNotLast, 1000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200677 EXPECT_THAT(InsertH264(kStartSize - 1, kKeyFrame, kNotFirst, kLast, 1000),
678 StartSeqNumsAre(0));
philipel2c9f9f22017-06-13 02:47:28 -0700679}
680
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200681TEST_P(PacketBufferH264ParameterizedTest, CreateFramesAfterFilledBuffer) {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100682 EXPECT_THAT(InsertH264(kStartSize - 2, kKeyFrame, kFirst, kLast, 0).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200683 SizeIs(1));
philipel227f8b92017-08-04 06:39:31 -0700684
685 InsertH264(kStartSize, kDeltaFrame, kFirst, kNotLast, 2000);
686 for (int i = 1; i < kStartSize; ++i)
687 InsertH264(kStartSize + i, kDeltaFrame, kNotFirst, kNotLast, 2000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200688 EXPECT_THAT(
689 InsertH264(kStartSize + kStartSize, kDeltaFrame, kNotFirst, kLast, 2000)
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100690 .packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200691 IsEmpty());
philipel227f8b92017-08-04 06:39:31 -0700692
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200693 EXPECT_THAT(InsertH264(kStartSize - 1, kKeyFrame, kFirst, kLast, 1000),
694 StartSeqNumsAre(kStartSize - 1, kStartSize));
philipel227f8b92017-08-04 06:39:31 -0700695}
696
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200697TEST_P(PacketBufferH264ParameterizedTest, OneFrameMaxSeqNum) {
philipel2c9f9f22017-06-13 02:47:28 -0700698 InsertH264(65534, kKeyFrame, kFirst, kNotLast, 1000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200699 EXPECT_THAT(InsertH264(65535, kKeyFrame, kNotFirst, kLast, 1000),
700 StartSeqNumsAre(65534));
philipel2c9f9f22017-06-13 02:47:28 -0700701}
702
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200703TEST_P(PacketBufferH264ParameterizedTest, ClearMissingPacketsOnKeyframe) {
philipel2c9f9f22017-06-13 02:47:28 -0700704 InsertH264(0, kKeyFrame, kFirst, kLast, 1000);
705 InsertH264(2, kKeyFrame, kFirst, kLast, 3000);
706 InsertH264(3, kDeltaFrame, kFirst, kNotLast, 4000);
707 InsertH264(4, kDeltaFrame, kNotFirst, kLast, 4000);
708
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200709 EXPECT_THAT(InsertH264(kStartSize + 1, kKeyFrame, kFirst, kLast, 18000),
710 StartSeqNumsAre(kStartSize + 1));
philipel2c9f9f22017-06-13 02:47:28 -0700711}
712
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200713TEST_P(PacketBufferH264ParameterizedTest, FindFramesOnPadding) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200714 EXPECT_THAT(InsertH264(0, kKeyFrame, kFirst, kLast, 1000),
715 StartSeqNumsAre(0));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100716 EXPECT_THAT(InsertH264(2, kDeltaFrame, kFirst, kLast, 1000).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200717 IsEmpty());
philipel2c9f9f22017-06-13 02:47:28 -0700718
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200719 EXPECT_THAT(packet_buffer_.InsertPadding(1), StartSeqNumsAre(2));
philipel2c9f9f22017-06-13 02:47:28 -0700720}
721
Jared Siskin3f659b12022-06-22 06:35:38 -0700722TEST_P(PacketBufferH264ParameterizedTest, FindFramesOnReorderedPadding) {
723 EXPECT_THAT(InsertH264(0, kKeyFrame, kFirst, kLast, 1001),
724 StartSeqNumsAre(0));
725 EXPECT_THAT(InsertH264(1, kDeltaFrame, kFirst, kNotLast, 1002).packets,
726 IsEmpty());
727 EXPECT_THAT(packet_buffer_.InsertPadding(3).packets, IsEmpty());
728 EXPECT_THAT(InsertH264(4, kDeltaFrame, kFirst, kLast, 1003).packets,
729 IsEmpty());
730 EXPECT_THAT(InsertH264(2, kDeltaFrame, kNotFirst, kLast, 1002),
731 StartSeqNumsAre(1, 4));
732}
733
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200734class PacketBufferH264XIsKeyframeTest : public PacketBufferH264Test {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200735 protected:
736 const uint16_t kSeqNum = 5;
737
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200738 explicit PacketBufferH264XIsKeyframeTest(bool sps_pps_idr_is_keyframe)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100739 : PacketBufferH264Test(sps_pps_idr_is_keyframe) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200740
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100741 std::unique_ptr<PacketBuffer::Packet> CreatePacket() {
742 auto packet = std::make_unique<PacketBuffer::Packet>();
743 packet->video_header.codec = kVideoCodecH264;
744 packet->seq_num = kSeqNum;
745
746 packet->video_header.is_first_packet_in_frame = true;
747 packet->video_header.is_last_packet_in_frame = true;
748 return packet;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200749 }
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200750};
751
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200752class PacketBufferH264IdrIsKeyframeTest
753 : public PacketBufferH264XIsKeyframeTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200754 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200755 PacketBufferH264IdrIsKeyframeTest()
756 : PacketBufferH264XIsKeyframeTest(false) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200757};
758
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200759TEST_F(PacketBufferH264IdrIsKeyframeTest, IdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100760 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200761 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100762 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200763 h264_header.nalus[0].type = H264::NaluType::kIdr;
764 h264_header.nalus_length = 1;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100765 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200766 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200767}
768
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200769TEST_F(PacketBufferH264IdrIsKeyframeTest, SpsPpsIdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100770 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200771 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100772 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200773 h264_header.nalus[0].type = H264::NaluType::kSps;
774 h264_header.nalus[1].type = H264::NaluType::kPps;
775 h264_header.nalus[2].type = H264::NaluType::kIdr;
776 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200777
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100778 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200779 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200780}
781
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200782class PacketBufferH264SpsPpsIdrIsKeyframeTest
783 : public PacketBufferH264XIsKeyframeTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200784 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200785 PacketBufferH264SpsPpsIdrIsKeyframeTest()
786 : PacketBufferH264XIsKeyframeTest(true) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200787};
788
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200789TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, IdrIsNotKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100790 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200791 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100792 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200793 h264_header.nalus[0].type = H264::NaluType::kIdr;
794 h264_header.nalus_length = 1;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200795
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100796 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200797 ElementsAre(DeltaFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200798}
799
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200800TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIsNotKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100801 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200802 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100803 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200804 h264_header.nalus[0].type = H264::NaluType::kSps;
805 h264_header.nalus[1].type = H264::NaluType::kPps;
806 h264_header.nalus_length = 2;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200807
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100808 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200809 ElementsAre(DeltaFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200810}
811
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200812TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100813 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200814 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100815 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200816 h264_header.nalus[0].type = H264::NaluType::kSps;
817 h264_header.nalus[1].type = H264::NaluType::kPps;
818 h264_header.nalus[2].type = H264::NaluType::kIdr;
819 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200820
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100821 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200822 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200823}
824
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200825} // namespace
philipelc707ab72016-04-01 02:01:54 -0700826} // namespace video_coding
827} // namespace webrtc