blob: b147977ab67105a9cb9e9997fc0d8100cbafe0ce [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"
Evan Shrubsole097fc342023-01-09 10:21:43 +000021#include "rtc_base/numerics/sequence_number_unwrapper.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "rtc_base/random.h"
Rasmus Brandtedf4ff72017-10-24 10:07:48 +020023#include "test/field_trial.h"
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020024#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "test/gtest.h"
philipelc707ab72016-04-01 02:01:54 -070026
27namespace webrtc {
28namespace video_coding {
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020029namespace {
philipelc707ab72016-04-01 02:01:54 -070030
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020031using ::testing::ElementsAre;
Danil Chapovalov1dac7072019-10-24 12:44:23 +020032using ::testing::ElementsAreArray;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020033using ::testing::IsEmpty;
Danil Chapovalov1dac7072019-10-24 12:44:23 +020034using ::testing::Matches;
35using ::testing::Pointee;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020036using ::testing::SizeIs;
37
Danil Chapovalov1dac7072019-10-24 12:44:23 +020038constexpr int kStartSize = 16;
39constexpr int kMaxSize = 64;
40
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020041void IgnoreResult(PacketBuffer::InsertResult /*result*/) {}
42
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010043// Validates frame boundaries are valid and returns first sequence_number for
44// each frame.
Danil Chapovalov1dac7072019-10-24 12:44:23 +020045std::vector<uint16_t> StartSeqNums(
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010046 rtc::ArrayView<const std::unique_ptr<PacketBuffer::Packet>> packets) {
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020047 std::vector<uint16_t> result;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010048 bool frame_boundary = true;
49 for (const auto& packet : packets) {
50 EXPECT_EQ(frame_boundary, packet->is_first_packet_in_frame());
51 if (packet->is_first_packet_in_frame()) {
52 result.push_back(packet->seq_num);
53 }
54 frame_boundary = packet->is_last_packet_in_frame();
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020055 }
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010056 EXPECT_TRUE(frame_boundary);
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020057 return result;
58}
59
Danil Chapovalov1dac7072019-10-24 12:44:23 +020060MATCHER_P(StartSeqNumsAre, seq_num, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010061 return Matches(ElementsAre(seq_num))(StartSeqNums(arg.packets));
Danil Chapovalov1dac7072019-10-24 12:44:23 +020062}
63
64MATCHER_P2(StartSeqNumsAre, seq_num1, seq_num2, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010065 return Matches(ElementsAre(seq_num1, seq_num2))(StartSeqNums(arg.packets));
Danil Chapovalov1dac7072019-10-24 12:44:23 +020066}
67
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020068MATCHER(KeyFrame, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010069 return arg->is_first_packet_in_frame() &&
70 arg->video_header.frame_type == VideoFrameType::kVideoFrameKey;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020071}
72
73MATCHER(DeltaFrame, "") {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010074 return arg->is_first_packet_in_frame() &&
75 arg->video_header.frame_type == VideoFrameType::kVideoFrameDelta;
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +020076}
77
Danil Chapovalov1dac7072019-10-24 12:44:23 +020078struct PacketBufferInsertResult : public PacketBuffer::InsertResult {
79 explicit PacketBufferInsertResult(PacketBuffer::InsertResult result)
80 : InsertResult(std::move(result)) {}
81};
82
83void PrintTo(const PacketBufferInsertResult& result, std::ostream* os) {
84 *os << "frames: { ";
Danil Chapovalov810b4ca2020-03-19 13:56:11 +010085 for (const auto& packet : result.packets) {
86 if (packet->is_first_packet_in_frame() &&
87 packet->is_last_packet_in_frame()) {
88 *os << "{sn: " << packet->seq_num << " }";
89 } else if (packet->is_first_packet_in_frame()) {
90 *os << "{sn: [" << packet->seq_num << "-";
91 } else if (packet->is_last_packet_in_frame()) {
92 *os << packet->seq_num << "] }, ";
Danil Chapovalov1dac7072019-10-24 12:44:23 +020093 }
Danil Chapovalov1dac7072019-10-24 12:44:23 +020094 }
95 *os << " }";
96 if (result.buffer_cleared) {
97 *os << ", buffer_cleared";
98 }
99}
100
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200101class PacketBufferTest : public ::testing::Test {
philipelc707ab72016-04-01 02:01:54 -0700102 protected:
philipelce423ce2021-04-12 13:42:03 +0200103 PacketBufferTest() : rand_(0x7732213), packet_buffer_(kStartSize, kMaxSize) {}
philipelc707ab72016-04-01 02:01:54 -0700104
philipel17deeb42016-08-11 15:09:26 +0200105 uint16_t Rand() { return rand_.Rand<uint16_t>(); }
philipelc707ab72016-04-01 02:01:54 -0700106
philipel17deeb42016-08-11 15:09:26 +0200107 enum IsKeyFrame { kKeyFrame, kDeltaFrame };
108 enum IsFirst { kFirst, kNotFirst };
109 enum IsLast { kLast, kNotLast };
philipelc707ab72016-04-01 02:01:54 -0700110
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200111 PacketBufferInsertResult Insert(uint16_t seq_num, // packet sequence number
112 IsKeyFrame keyframe, // is keyframe
113 IsFirst first, // is first packet of frame
114 IsLast last, // is last packet of frame
Danil Chapovalove3c48842019-12-02 15:54:27 +0100115 rtc::ArrayView<const uint8_t> data = {},
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200116 uint32_t timestamp = 123u) { // rtp timestamp
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100117 auto packet = std::make_unique<PacketBuffer::Packet>();
118 packet->video_header.codec = kVideoCodecGeneric;
119 packet->timestamp = timestamp;
120 packet->seq_num = seq_num;
121 packet->video_header.frame_type = keyframe == kKeyFrame
122 ? VideoFrameType::kVideoFrameKey
123 : VideoFrameType::kVideoFrameDelta;
124 packet->video_header.is_first_packet_in_frame = first == kFirst;
125 packet->video_header.is_last_packet_in_frame = last == kLast;
126 packet->video_payload.SetData(data.data(), data.size());
philipelf4139332016-04-20 10:26:34 +0200127
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100128 return PacketBufferInsertResult(
129 packet_buffer_.InsertPacket(std::move(packet)));
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200130 }
131
philipelc707ab72016-04-01 02:01:54 -0700132 Random rand_;
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200133 PacketBuffer packet_buffer_;
philipelc707ab72016-04-01 02:01:54 -0700134};
135
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200136TEST_F(PacketBufferTest, InsertOnePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100137 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100138 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
philipelc707ab72016-04-01 02:01:54 -0700139}
140
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200141TEST_F(PacketBufferTest, InsertMultiplePackets) {
philipelaee3e0e2016-11-01 11:45:34 +0100142 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100143 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
144 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
145 EXPECT_THAT(Insert(seq_num + 2, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
146 EXPECT_THAT(Insert(seq_num + 3, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
philipelc707ab72016-04-01 02:01:54 -0700147}
148
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200149TEST_F(PacketBufferTest, InsertDuplicatePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100150 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100151 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
152 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
153 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast).packets,
154 SizeIs(2));
philipelaee3e0e2016-11-01 11:45:34 +0100155}
156
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200157TEST_F(PacketBufferTest, SeqNumWrapOneFrame) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200158 Insert(0xFFFF, kKeyFrame, kFirst, kNotLast);
159 EXPECT_THAT(Insert(0x0, kKeyFrame, kNotFirst, kLast),
160 StartSeqNumsAre(0xFFFF));
philipel2c2f34c2017-01-03 05:55:34 -0800161}
162
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200163TEST_F(PacketBufferTest, SeqNumWrapTwoFrames) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200164 EXPECT_THAT(Insert(0xFFFF, kKeyFrame, kFirst, kLast),
165 StartSeqNumsAre(0xFFFF));
166 EXPECT_THAT(Insert(0x0, kKeyFrame, kFirst, kLast), StartSeqNumsAre(0x0));
philipelaee3e0e2016-11-01 11:45:34 +0100167}
168
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200169TEST_F(PacketBufferTest, InsertOldPackets) {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100170 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
171 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
172 EXPECT_THAT(Insert(101, kKeyFrame, kNotFirst, kLast).packets, SizeIs(2));
philipelaee3e0e2016-11-01 11:45:34 +0100173
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100174 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
175 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
176 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipelaee3e0e2016-11-01 11:45:34 +0100177
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200178 packet_buffer_.ClearTo(102);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100179 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, IsEmpty());
180 EXPECT_THAT(Insert(103, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipel5ceaaae2016-05-24 10:20:47 +0200181}
182
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200183TEST_F(PacketBufferTest, FrameSize) {
philipelaee3e0e2016-11-01 11:45:34 +0100184 const uint16_t seq_num = Rand();
Danil Chapovalove3c48842019-12-02 15:54:27 +0100185 uint8_t data1[5] = {};
186 uint8_t data2[5] = {};
187 uint8_t data3[5] = {};
188 uint8_t data4[5] = {};
philipel5ceaaae2016-05-24 10:20:47 +0200189
Danil Chapovalove3c48842019-12-02 15:54:27 +0100190 Insert(seq_num, kKeyFrame, kFirst, kNotLast, data1);
191 Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast, data2);
192 Insert(seq_num + 2, kKeyFrame, kNotFirst, kNotLast, data3);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100193 auto packets =
194 Insert(seq_num + 3, kKeyFrame, kNotFirst, kLast, data4).packets;
195 // Expect one frame of 4 packets.
196 EXPECT_THAT(StartSeqNums(packets), ElementsAre(seq_num));
197 EXPECT_THAT(packets, SizeIs(4));
philipel5ceaaae2016-05-24 10:20:47 +0200198}
199
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200200TEST_F(PacketBufferTest, ExpandBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100201 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700202
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200203 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
Johannes Krona3705562019-08-26 16:37:11 +0200204 for (int i = 1; i < kStartSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200205 EXPECT_FALSE(
206 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200207
208 // Already inserted kStartSize number of packets, inserting the last packet
209 // should increase the buffer size and also result in an assembled frame.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200210 EXPECT_FALSE(
211 Insert(seq_num + kStartSize, kKeyFrame, kNotFirst, kLast).buffer_cleared);
philipelc707ab72016-04-01 02:01:54 -0700212}
213
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200214TEST_F(PacketBufferTest, SingleFrameExpandsBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100215 const uint16_t seq_num = Rand();
216
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200217 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
philipelaee3e0e2016-11-01 11:45:34 +0100218 for (int i = 1; i < kStartSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200219 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast);
220 EXPECT_THAT(Insert(seq_num + kStartSize, kKeyFrame, kNotFirst, kLast),
221 StartSeqNumsAre(seq_num));
philipelaee3e0e2016-11-01 11:45:34 +0100222}
223
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200224TEST_F(PacketBufferTest, ExpandBufferOverflow) {
philipelaee3e0e2016-11-01 11:45:34 +0100225 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700226
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200227 EXPECT_FALSE(Insert(seq_num, kKeyFrame, kFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200228 for (int i = 1; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200229 EXPECT_FALSE(
230 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200231
232 // Already inserted kMaxSize number of packets, inserting the last packet
233 // should overflow the buffer and result in false being returned.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200234 EXPECT_TRUE(
235 Insert(seq_num + kMaxSize, kKeyFrame, kNotFirst, kLast).buffer_cleared);
philipelc707ab72016-04-01 02:01:54 -0700236}
237
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200238TEST_F(PacketBufferTest, OnePacketOneFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100239 const uint16_t seq_num = Rand();
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200240 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
241 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700242}
243
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200244TEST_F(PacketBufferTest, TwoPacketsTwoFrames) {
philipelaee3e0e2016-11-01 11:45:34 +0100245 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200246
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200247 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
248 StartSeqNumsAre(seq_num));
249 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kFirst, kLast),
250 StartSeqNumsAre(seq_num + 1));
philipelc707ab72016-04-01 02:01:54 -0700251}
252
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200253TEST_F(PacketBufferTest, TwoPacketsOneFrames) {
philipelaee3e0e2016-11-01 11:45:34 +0100254 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200255
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100256 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200257 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast),
258 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700259}
260
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200261TEST_F(PacketBufferTest, ThreePacketReorderingOneFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100262 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700263
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100264 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
265 EXPECT_THAT(Insert(seq_num + 2, kKeyFrame, kNotFirst, kLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200266 IsEmpty());
267 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast),
268 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700269}
270
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200271TEST_F(PacketBufferTest, Frames) {
philipelaee3e0e2016-11-01 11:45:34 +0100272 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200273
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200274 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
275 StartSeqNumsAre(seq_num));
276 EXPECT_THAT(Insert(seq_num + 1, kDeltaFrame, kFirst, kLast),
277 StartSeqNumsAre(seq_num + 1));
278 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast),
279 StartSeqNumsAre(seq_num + 2));
280 EXPECT_THAT(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast),
281 StartSeqNumsAre(seq_num + 3));
philipelf4139332016-04-20 10:26:34 +0200282}
283
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200284TEST_F(PacketBufferTest, ClearSinglePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100285 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200286
philipelaee3e0e2016-11-01 11:45:34 +0100287 for (int i = 0; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200288 Insert(seq_num + i, kDeltaFrame, kFirst, kLast);
philipelaee3e0e2016-11-01 11:45:34 +0100289
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200290 packet_buffer_.ClearTo(seq_num);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200291 EXPECT_FALSE(
292 Insert(seq_num + kMaxSize, kDeltaFrame, kFirst, kLast).buffer_cleared);
philipelaee3e0e2016-11-01 11:45:34 +0100293}
294
philipel90623e12022-04-28 14:31:55 +0200295TEST_F(PacketBufferTest, ClearPacketBeforeFullyReceivedFrame) {
296 Insert(0, kKeyFrame, kFirst, kNotLast);
297 Insert(1, kKeyFrame, kNotFirst, kNotLast);
298 packet_buffer_.ClearTo(0);
299 EXPECT_THAT(Insert(2, kKeyFrame, kNotFirst, kLast).packets, IsEmpty());
300}
301
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200302TEST_F(PacketBufferTest, ClearFullBuffer) {
philipelc5fb4682017-08-02 04:28:57 -0700303 for (int i = 0; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200304 Insert(i, kDeltaFrame, kFirst, kLast);
philipelc5fb4682017-08-02 04:28:57 -0700305
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200306 packet_buffer_.ClearTo(kMaxSize - 1);
philipelc5fb4682017-08-02 04:28:57 -0700307
308 for (int i = kMaxSize; i < 2 * kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200309 EXPECT_FALSE(Insert(i, kDeltaFrame, kFirst, kLast).buffer_cleared);
philipelc5fb4682017-08-02 04:28:57 -0700310}
311
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200312TEST_F(PacketBufferTest, DontClearNewerPacket) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200313 EXPECT_THAT(Insert(0, kKeyFrame, kFirst, kLast), StartSeqNumsAre(0));
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200314 packet_buffer_.ClearTo(0);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200315 EXPECT_THAT(Insert(2 * kStartSize, kKeyFrame, kFirst, kLast),
316 StartSeqNumsAre(2 * kStartSize));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100317 EXPECT_THAT(Insert(3 * kStartSize + 1, kKeyFrame, kFirst, kNotLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200318 IsEmpty());
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200319 packet_buffer_.ClearTo(2 * kStartSize);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200320 EXPECT_THAT(Insert(3 * kStartSize + 2, kKeyFrame, kNotFirst, kLast),
321 StartSeqNumsAre(3 * kStartSize + 1));
philipelc5fb4682017-08-02 04:28:57 -0700322}
323
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200324TEST_F(PacketBufferTest, OneIncompleteFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100325 const uint16_t seq_num = Rand();
326
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100327 EXPECT_THAT(Insert(seq_num, kDeltaFrame, kFirst, kNotLast).packets,
328 IsEmpty());
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200329 EXPECT_THAT(Insert(seq_num + 1, kDeltaFrame, kNotFirst, kLast),
330 StartSeqNumsAre(seq_num));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100331 EXPECT_THAT(Insert(seq_num - 1, kDeltaFrame, kNotFirst, kLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200332 IsEmpty());
philipelaee3e0e2016-11-01 11:45:34 +0100333}
334
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200335TEST_F(PacketBufferTest, TwoIncompleteFramesFullBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100336 const uint16_t seq_num = Rand();
337
338 for (int i = 1; i < kMaxSize - 1; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200339 Insert(seq_num + i, kDeltaFrame, kNotFirst, kNotLast);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100340 EXPECT_THAT(Insert(seq_num, kDeltaFrame, kFirst, kNotLast).packets,
341 IsEmpty());
342 EXPECT_THAT(Insert(seq_num - 1, kDeltaFrame, kNotFirst, kLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200343 IsEmpty());
philipelaee3e0e2016-11-01 11:45:34 +0100344}
345
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200346TEST_F(PacketBufferTest, FramesReordered) {
philipelaee3e0e2016-11-01 11:45:34 +0100347 const uint16_t seq_num = Rand();
348
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200349 EXPECT_THAT(Insert(seq_num + 1, kDeltaFrame, kFirst, kLast),
350 StartSeqNumsAre(seq_num + 1));
351 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
352 StartSeqNumsAre(seq_num));
353 EXPECT_THAT(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast),
354 StartSeqNumsAre(seq_num + 3));
355 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast),
356 StartSeqNumsAre(seq_num + 2));
philipelf4139332016-04-20 10:26:34 +0200357}
358
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200359TEST_F(PacketBufferTest, InsertPacketAfterSequenceNumberWrapAround) {
Johannes Kron957c62e2018-10-01 14:53:01 +0200360 uint16_t kFirstSeqNum = 0;
361 uint32_t kTimestampDelta = 100;
362 uint32_t timestamp = 10000;
363 uint16_t seq_num = kFirstSeqNum;
364
365 // Loop until seq_num wraps around.
Philip Eliasson1f850a62019-03-19 12:15:00 +0000366 SeqNumUnwrapper<uint16_t> unwrapper;
Johannes Kron957c62e2018-10-01 14:53:01 +0200367 while (unwrapper.Unwrap(seq_num) < std::numeric_limits<uint16_t>::max()) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100368 Insert(seq_num++, kKeyFrame, kFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200369 for (int i = 0; i < 5; ++i) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100370 Insert(seq_num++, kKeyFrame, kNotFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200371 }
Danil Chapovalove3c48842019-12-02 15:54:27 +0100372 Insert(seq_num++, kKeyFrame, kNotFirst, kLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200373 timestamp += kTimestampDelta;
374 }
375
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200376 // Receive frame with overlapping sequence numbers.
Danil Chapovalove3c48842019-12-02 15:54:27 +0100377 Insert(seq_num++, kKeyFrame, kFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200378 for (int i = 0; i < 5; ++i) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100379 Insert(seq_num++, kKeyFrame, kNotFirst, kNotLast, {}, timestamp);
Johannes Kron957c62e2018-10-01 14:53:01 +0200380 }
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100381 auto packets =
382 Insert(seq_num++, kKeyFrame, kNotFirst, kLast, {}, timestamp).packets;
383 // One frame of 7 packets.
384 EXPECT_THAT(StartSeqNums(packets), SizeIs(1));
385 EXPECT_THAT(packets, SizeIs(7));
Johannes Kron957c62e2018-10-01 14:53:01 +0200386}
387
Artem Titovdcd7fc72021-08-09 13:02:57 +0200388// If `sps_pps_idr_is_keyframe` is true, we require keyframes to contain
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100389// SPS/PPS/IDR and the keyframes we create as part of the test do contain
Artem Titovdcd7fc72021-08-09 13:02:57 +0200390// SPS/PPS/IDR. If `sps_pps_idr_is_keyframe` is false, we only require and
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100391// create keyframes containing only IDR.
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200392class PacketBufferH264Test : public PacketBufferTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200393 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200394 explicit PacketBufferH264Test(bool sps_pps_idr_is_keyframe)
Eldar Rello2127aaa2020-08-07 12:08:14 +0300395 : PacketBufferTest(), sps_pps_idr_is_keyframe_(sps_pps_idr_is_keyframe) {
396 if (sps_pps_idr_is_keyframe) {
397 packet_buffer_.ForceSpsPpsIdrIsH264Keyframe();
398 }
399 }
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200400
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200401 PacketBufferInsertResult InsertH264(
Danil Chapovalove3c48842019-12-02 15:54:27 +0100402 uint16_t seq_num, // packet sequence number
403 IsKeyFrame keyframe, // is keyframe
404 IsFirst first, // is first packet of frame
405 IsLast last, // is last packet of frame
406 uint32_t timestamp, // rtp timestamp
407 rtc::ArrayView<const uint8_t> data = {},
408 uint32_t width = 0, // width of frame (SPS/IDR)
409 uint32_t height = 0) { // height of frame (SPS/IDR)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100410 auto packet = std::make_unique<PacketBuffer::Packet>();
411 packet->video_header.codec = kVideoCodecH264;
philipel7d745e52018-08-02 14:03:53 +0200412 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100413 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
414 packet->seq_num = seq_num;
415 packet->timestamp = timestamp;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200416 if (keyframe == kKeyFrame) {
417 if (sps_pps_idr_is_keyframe_) {
philipel7d745e52018-08-02 14:03:53 +0200418 h264_header.nalus[0].type = H264::NaluType::kSps;
419 h264_header.nalus[1].type = H264::NaluType::kPps;
420 h264_header.nalus[2].type = H264::NaluType::kIdr;
421 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200422 } else {
philipel7d745e52018-08-02 14:03:53 +0200423 h264_header.nalus[0].type = H264::NaluType::kIdr;
424 h264_header.nalus_length = 1;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200425 }
426 }
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100427 packet->video_header.width = width;
428 packet->video_header.height = height;
429 packet->video_header.is_first_packet_in_frame = first == kFirst;
430 packet->video_header.is_last_packet_in_frame = last == kLast;
431 packet->video_payload.SetData(data.data(), data.size());
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200432
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100433 return PacketBufferInsertResult(
434 packet_buffer_.InsertPacket(std::move(packet)));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200435 }
436
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200437 PacketBufferInsertResult InsertH264KeyFrameWithAud(
Danil Chapovalove3c48842019-12-02 15:54:27 +0100438 uint16_t seq_num, // packet sequence number
439 IsKeyFrame keyframe, // is keyframe
440 IsFirst first, // is first packet of frame
441 IsLast last, // is last packet of frame
442 uint32_t timestamp, // rtp timestamp
443 rtc::ArrayView<const uint8_t> data = {},
444 uint32_t width = 0, // width of frame (SPS/IDR)
445 uint32_t height = 0) { // height of frame (SPS/IDR)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100446 auto packet = std::make_unique<PacketBuffer::Packet>();
447 packet->video_header.codec = kVideoCodecH264;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700448 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100449 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
450 packet->seq_num = seq_num;
451 packet->timestamp = timestamp;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700452
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200453 // this should be the start of frame.
454 RTC_CHECK(first == kFirst);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700455
456 // Insert a AUD NALU / packet without width/height.
457 h264_header.nalus[0].type = H264::NaluType::kAud;
458 h264_header.nalus_length = 1;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100459 packet->video_header.is_first_packet_in_frame = true;
460 packet->video_header.is_last_packet_in_frame = false;
461 IgnoreResult(packet_buffer_.InsertPacket(std::move(packet)));
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200462 // insert IDR
Danil Chapovalove3c48842019-12-02 15:54:27 +0100463 return InsertH264(seq_num + 1, keyframe, kNotFirst, last, timestamp, data,
464 width, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700465 }
466
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200467 const bool sps_pps_idr_is_keyframe_;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100468};
469
470// This fixture is used to test the general behaviour of the packet buffer
471// in both configurations.
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200472class PacketBufferH264ParameterizedTest
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100473 : public ::testing::WithParamInterface<bool>,
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200474 public PacketBufferH264Test {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100475 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200476 PacketBufferH264ParameterizedTest() : PacketBufferH264Test(GetParam()) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200477};
478
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100479INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200480 PacketBufferH264ParameterizedTest,
481 ::testing::Bool());
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200482
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200483TEST_P(PacketBufferH264ParameterizedTest, DontRemoveMissingPacketOnClearTo) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200484 InsertH264(0, kKeyFrame, kFirst, kLast, 0);
485 InsertH264(2, kDeltaFrame, kFirst, kNotLast, 2);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200486 packet_buffer_.ClearTo(0);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200487 // Expect no frame because of missing of packet #1
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100488 EXPECT_THAT(InsertH264(3, kDeltaFrame, kNotFirst, kLast, 2).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200489 IsEmpty());
philipelbc5a4082017-12-06 10:41:08 +0100490}
491
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200492TEST_P(PacketBufferH264ParameterizedTest, GetBitstreamOneFrameFullBuffer) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100493 uint8_t data_arr[kStartSize][1];
philipel227f8b92017-08-04 06:39:31 -0700494 uint8_t expected[kStartSize];
philipel227f8b92017-08-04 06:39:31 -0700495
496 for (uint8_t i = 0; i < kStartSize; ++i) {
philipel227f8b92017-08-04 06:39:31 -0700497 data_arr[i][0] = i;
498 expected[i] = i;
499 }
500
Danil Chapovalove3c48842019-12-02 15:54:27 +0100501 InsertH264(0, kKeyFrame, kFirst, kNotLast, 1, data_arr[0]);
philipel227f8b92017-08-04 06:39:31 -0700502 for (uint8_t i = 1; i < kStartSize - 1; ++i) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100503 InsertH264(i, kKeyFrame, kNotFirst, kNotLast, 1, data_arr[i]);
philipel227f8b92017-08-04 06:39:31 -0700504 }
philipel227f8b92017-08-04 06:39:31 -0700505
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100506 auto packets = InsertH264(kStartSize - 1, kKeyFrame, kNotFirst, kLast, 1,
507 data_arr[kStartSize - 1])
508 .packets;
509 ASSERT_THAT(StartSeqNums(packets), ElementsAre(0));
510 EXPECT_THAT(packets, SizeIs(kStartSize));
511 for (size_t i = 0; i < packets.size(); ++i) {
512 EXPECT_THAT(packets[i]->video_payload, SizeIs(1)) << "Packet #" << i;
513 }
philipel227f8b92017-08-04 06:39:31 -0700514}
515
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200516TEST_P(PacketBufferH264ParameterizedTest, GetBitstreamBufferPadding) {
philipel36928452016-11-07 10:42:36 +0100517 uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100518 rtc::CopyOnWriteBuffer data = "some plain old data";
philipel36928452016-11-07 10:42:36 +0100519
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100520 auto packet = std::make_unique<PacketBuffer::Packet>();
philipel7d745e52018-08-02 14:03:53 +0200521 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100522 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200523 h264_header.nalus_length = 1;
524 h264_header.nalus[0].type = H264::NaluType::kIdr;
525 h264_header.packetization_type = kH264SingleNalu;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100526 packet->seq_num = seq_num;
527 packet->video_header.codec = kVideoCodecH264;
528 packet->video_payload = data;
529 packet->video_header.is_first_packet_in_frame = true;
530 packet->video_header.is_last_packet_in_frame = true;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100531 auto frames = packet_buffer_.InsertPacket(std::move(packet)).packets;
philipel36928452016-11-07 10:42:36 +0100532
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200533 ASSERT_THAT(frames, SizeIs(1));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100534 EXPECT_EQ(frames[0]->seq_num, seq_num);
535 EXPECT_EQ(frames[0]->video_payload, data);
philipel36928452016-11-07 10:42:36 +0100536}
537
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200538TEST_P(PacketBufferH264ParameterizedTest, FrameResolution) {
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700539 uint16_t seq_num = 100;
Danil Chapovalove3c48842019-12-02 15:54:27 +0100540 uint8_t data[] = "some plain old data";
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700541 uint32_t width = 640;
542 uint32_t height = 360;
543 uint32_t timestamp = 1000;
544
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100545 auto packets = InsertH264(seq_num, kKeyFrame, kFirst, kLast, timestamp, data,
546 width, height)
547 .packets;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700548
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100549 ASSERT_THAT(packets, SizeIs(1));
550 EXPECT_EQ(packets[0]->video_header.width, width);
551 EXPECT_EQ(packets[0]->video_header.height, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700552}
553
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200554TEST_P(PacketBufferH264ParameterizedTest, FrameResolutionNaluBeforeSPS) {
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700555 uint16_t seq_num = 100;
Danil Chapovalove3c48842019-12-02 15:54:27 +0100556 uint8_t data[] = "some plain old data";
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700557 uint32_t width = 640;
558 uint32_t height = 360;
559 uint32_t timestamp = 1000;
560
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100561 auto packets = InsertH264KeyFrameWithAud(seq_num, kKeyFrame, kFirst, kLast,
562 timestamp, data, width, height)
563 .packets;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700564
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100565 ASSERT_THAT(StartSeqNums(packets), ElementsAre(seq_num));
566 EXPECT_EQ(packets[0]->video_header.width, width);
567 EXPECT_EQ(packets[0]->video_header.height, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700568}
569
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200570TEST_F(PacketBufferTest, FreeSlotsOnFrameCreation) {
philipelaee3e0e2016-11-01 11:45:34 +0100571 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200572
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200573 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
574 Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast);
575 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast),
576 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700577
philipel17deeb42016-08-11 15:09:26 +0200578 // Insert frame that fills the whole buffer.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200579 Insert(seq_num + 3, kKeyFrame, kFirst, kNotLast);
philipel17deeb42016-08-11 15:09:26 +0200580 for (int i = 0; i < kMaxSize - 2; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200581 Insert(seq_num + i + 4, kDeltaFrame, kNotFirst, kNotLast);
582 EXPECT_THAT(Insert(seq_num + kMaxSize + 2, kKeyFrame, kNotFirst, kLast),
583 StartSeqNumsAre(seq_num + 3));
philipelc707ab72016-04-01 02:01:54 -0700584}
585
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200586TEST_F(PacketBufferTest, Clear) {
philipelaee3e0e2016-11-01 11:45:34 +0100587 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200588
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200589 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
590 Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast);
591 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast),
592 StartSeqNumsAre(seq_num));
philipelf4139332016-04-20 10:26:34 +0200593
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200594 packet_buffer_.Clear();
philipelf4139332016-04-20 10:26:34 +0200595
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200596 Insert(seq_num + kStartSize, kKeyFrame, kFirst, kNotLast);
597 Insert(seq_num + kStartSize + 1, kDeltaFrame, kNotFirst, kNotLast);
598 EXPECT_THAT(Insert(seq_num + kStartSize + 2, kDeltaFrame, kNotFirst, kLast),
599 StartSeqNumsAre(seq_num + kStartSize));
philipelc707ab72016-04-01 02:01:54 -0700600}
601
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200602TEST_F(PacketBufferTest, FramesAfterClear) {
philipel20dce342016-11-28 16:14:57 +0100603 Insert(9025, kDeltaFrame, kFirst, kLast);
604 Insert(9024, kKeyFrame, kFirst, kLast);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200605 packet_buffer_.ClearTo(9025);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100606 EXPECT_THAT(Insert(9057, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
607 EXPECT_THAT(Insert(9026, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipel20dce342016-11-28 16:14:57 +0100608}
609
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200610TEST_F(PacketBufferTest, SameFrameDifferentTimestamps) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100611 Insert(0, kKeyFrame, kFirst, kNotLast, {}, 1000);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100612 EXPECT_THAT(Insert(1, kKeyFrame, kNotFirst, kLast, {}, 1001).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200613 IsEmpty());
philipel8b6995b2019-01-09 12:39:18 +0100614}
615
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200616TEST_F(PacketBufferTest, ContinuousSeqNumDoubleMarkerBit) {
philipelea142f82017-01-11 02:01:56 -0800617 Insert(2, kKeyFrame, kNotFirst, kNotLast);
618 Insert(1, kKeyFrame, kFirst, kLast);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100619 EXPECT_THAT(Insert(3, kKeyFrame, kNotFirst, kLast).packets, IsEmpty());
philipelea142f82017-01-11 02:01:56 -0800620}
621
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200622TEST_F(PacketBufferTest, IncomingCodecChange) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100623 auto packet = std::make_unique<PacketBuffer::Packet>();
624 packet->video_header.is_first_packet_in_frame = true;
625 packet->video_header.is_last_packet_in_frame = true;
626 packet->video_header.codec = kVideoCodecVP8;
627 packet->video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
628 packet->timestamp = 1;
629 packet->seq_num = 1;
630 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100631 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
632 SizeIs(1));
philipel09133af2018-05-17 14:11:09 +0200633
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100634 packet = std::make_unique<PacketBuffer::Packet>();
635 packet->video_header.is_first_packet_in_frame = true;
636 packet->video_header.is_last_packet_in_frame = true;
637 packet->video_header.codec = kVideoCodecH264;
philipel7d745e52018-08-02 14:03:53 +0200638 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100639 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200640 h264_header.nalus_length = 1;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100641 packet->timestamp = 3;
642 packet->seq_num = 3;
643 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100644 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
645 IsEmpty());
philipel09133af2018-05-17 14:11:09 +0200646
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100647 packet = std::make_unique<PacketBuffer::Packet>();
648 packet->video_header.is_first_packet_in_frame = true;
649 packet->video_header.is_last_packet_in_frame = true;
650 packet->video_header.codec = kVideoCodecVP8;
651 packet->video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
652 packet->timestamp = 2;
653 packet->seq_num = 2;
654 packet->video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100655 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
656 SizeIs(2));
philipel09133af2018-05-17 14:11:09 +0200657}
658
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200659TEST_F(PacketBufferTest, TooManyNalusInPacket) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100660 auto packet = std::make_unique<PacketBuffer::Packet>();
661 packet->video_header.codec = kVideoCodecH264;
662 packet->timestamp = 1;
663 packet->seq_num = 1;
664 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
665 packet->video_header.is_first_packet_in_frame = true;
666 packet->video_header.is_last_packet_in_frame = true;
philipel7d745e52018-08-02 14:03:53 +0200667 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100668 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200669 h264_header.nalus_length = kMaxNalusPerPacket;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100670 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
671 IsEmpty());
philipel09133af2018-05-17 14:11:09 +0200672}
673
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200674TEST_P(PacketBufferH264ParameterizedTest, OneFrameFillBuffer) {
philipel2c9f9f22017-06-13 02:47:28 -0700675 InsertH264(0, kKeyFrame, kFirst, kNotLast, 1000);
676 for (int i = 1; i < kStartSize - 1; ++i)
677 InsertH264(i, kKeyFrame, kNotFirst, kNotLast, 1000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200678 EXPECT_THAT(InsertH264(kStartSize - 1, kKeyFrame, kNotFirst, kLast, 1000),
679 StartSeqNumsAre(0));
philipel2c9f9f22017-06-13 02:47:28 -0700680}
681
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200682TEST_P(PacketBufferH264ParameterizedTest, CreateFramesAfterFilledBuffer) {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100683 EXPECT_THAT(InsertH264(kStartSize - 2, kKeyFrame, kFirst, kLast, 0).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200684 SizeIs(1));
philipel227f8b92017-08-04 06:39:31 -0700685
686 InsertH264(kStartSize, kDeltaFrame, kFirst, kNotLast, 2000);
687 for (int i = 1; i < kStartSize; ++i)
688 InsertH264(kStartSize + i, kDeltaFrame, kNotFirst, kNotLast, 2000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200689 EXPECT_THAT(
690 InsertH264(kStartSize + kStartSize, kDeltaFrame, kNotFirst, kLast, 2000)
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100691 .packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200692 IsEmpty());
philipel227f8b92017-08-04 06:39:31 -0700693
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200694 EXPECT_THAT(InsertH264(kStartSize - 1, kKeyFrame, kFirst, kLast, 1000),
695 StartSeqNumsAre(kStartSize - 1, kStartSize));
philipel227f8b92017-08-04 06:39:31 -0700696}
697
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200698TEST_P(PacketBufferH264ParameterizedTest, OneFrameMaxSeqNum) {
philipel2c9f9f22017-06-13 02:47:28 -0700699 InsertH264(65534, kKeyFrame, kFirst, kNotLast, 1000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200700 EXPECT_THAT(InsertH264(65535, kKeyFrame, kNotFirst, kLast, 1000),
701 StartSeqNumsAre(65534));
philipel2c9f9f22017-06-13 02:47:28 -0700702}
703
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200704TEST_P(PacketBufferH264ParameterizedTest, ClearMissingPacketsOnKeyframe) {
philipel2c9f9f22017-06-13 02:47:28 -0700705 InsertH264(0, kKeyFrame, kFirst, kLast, 1000);
706 InsertH264(2, kKeyFrame, kFirst, kLast, 3000);
707 InsertH264(3, kDeltaFrame, kFirst, kNotLast, 4000);
708 InsertH264(4, kDeltaFrame, kNotFirst, kLast, 4000);
709
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200710 EXPECT_THAT(InsertH264(kStartSize + 1, kKeyFrame, kFirst, kLast, 18000),
711 StartSeqNumsAre(kStartSize + 1));
philipel2c9f9f22017-06-13 02:47:28 -0700712}
713
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200714TEST_P(PacketBufferH264ParameterizedTest, FindFramesOnPadding) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200715 EXPECT_THAT(InsertH264(0, kKeyFrame, kFirst, kLast, 1000),
716 StartSeqNumsAre(0));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100717 EXPECT_THAT(InsertH264(2, kDeltaFrame, kFirst, kLast, 1000).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200718 IsEmpty());
philipel2c9f9f22017-06-13 02:47:28 -0700719
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200720 EXPECT_THAT(packet_buffer_.InsertPadding(1), StartSeqNumsAre(2));
philipel2c9f9f22017-06-13 02:47:28 -0700721}
722
Jared Siskin3f659b12022-06-22 06:35:38 -0700723TEST_P(PacketBufferH264ParameterizedTest, FindFramesOnReorderedPadding) {
724 EXPECT_THAT(InsertH264(0, kKeyFrame, kFirst, kLast, 1001),
725 StartSeqNumsAre(0));
726 EXPECT_THAT(InsertH264(1, kDeltaFrame, kFirst, kNotLast, 1002).packets,
727 IsEmpty());
728 EXPECT_THAT(packet_buffer_.InsertPadding(3).packets, IsEmpty());
729 EXPECT_THAT(InsertH264(4, kDeltaFrame, kFirst, kLast, 1003).packets,
730 IsEmpty());
731 EXPECT_THAT(InsertH264(2, kDeltaFrame, kNotFirst, kLast, 1002),
732 StartSeqNumsAre(1, 4));
733}
734
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200735class PacketBufferH264XIsKeyframeTest : public PacketBufferH264Test {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200736 protected:
737 const uint16_t kSeqNum = 5;
738
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200739 explicit PacketBufferH264XIsKeyframeTest(bool sps_pps_idr_is_keyframe)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100740 : PacketBufferH264Test(sps_pps_idr_is_keyframe) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200741
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100742 std::unique_ptr<PacketBuffer::Packet> CreatePacket() {
743 auto packet = std::make_unique<PacketBuffer::Packet>();
744 packet->video_header.codec = kVideoCodecH264;
745 packet->seq_num = kSeqNum;
746
747 packet->video_header.is_first_packet_in_frame = true;
748 packet->video_header.is_last_packet_in_frame = true;
749 return packet;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200750 }
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200751};
752
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200753class PacketBufferH264IdrIsKeyframeTest
754 : public PacketBufferH264XIsKeyframeTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200755 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200756 PacketBufferH264IdrIsKeyframeTest()
757 : PacketBufferH264XIsKeyframeTest(false) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200758};
759
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200760TEST_F(PacketBufferH264IdrIsKeyframeTest, IdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100761 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200762 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100763 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200764 h264_header.nalus[0].type = H264::NaluType::kIdr;
765 h264_header.nalus_length = 1;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100766 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200767 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200768}
769
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200770TEST_F(PacketBufferH264IdrIsKeyframeTest, SpsPpsIdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100771 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200772 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100773 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200774 h264_header.nalus[0].type = H264::NaluType::kSps;
775 h264_header.nalus[1].type = H264::NaluType::kPps;
776 h264_header.nalus[2].type = H264::NaluType::kIdr;
777 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200778
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100779 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200780 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200781}
782
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200783class PacketBufferH264SpsPpsIdrIsKeyframeTest
784 : public PacketBufferH264XIsKeyframeTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200785 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200786 PacketBufferH264SpsPpsIdrIsKeyframeTest()
787 : PacketBufferH264XIsKeyframeTest(true) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200788};
789
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200790TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, IdrIsNotKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100791 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200792 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100793 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200794 h264_header.nalus[0].type = H264::NaluType::kIdr;
795 h264_header.nalus_length = 1;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200796
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100797 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200798 ElementsAre(DeltaFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200799}
800
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200801TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIsNotKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100802 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200803 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100804 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200805 h264_header.nalus[0].type = H264::NaluType::kSps;
806 h264_header.nalus[1].type = H264::NaluType::kPps;
807 h264_header.nalus_length = 2;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200808
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100809 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200810 ElementsAre(DeltaFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200811}
812
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200813TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100814 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200815 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100816 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200817 h264_header.nalus[0].type = H264::NaluType::kSps;
818 h264_header.nalus[1].type = H264::NaluType::kPps;
819 h264_header.nalus[2].type = H264::NaluType::kIdr;
820 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200821
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100822 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200823 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200824}
825
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200826} // namespace
philipelc707ab72016-04-01 02:01:54 -0700827} // namespace video_coding
828} // namespace webrtc