blob: 242fff25264cf4986e54f63101fadb0182158fd0 [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"
22#include "system_wrappers/include/clock.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:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200103 explicit PacketBufferTest(std::string field_trials = "")
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100104 : scoped_field_trials_(field_trials),
105 rand_(0x7732213),
Danil Chapovalove3c48842019-12-02 15:54:27 +0100106 clock_(0),
107 packet_buffer_(&clock_, kStartSize, kMaxSize) {}
philipelc707ab72016-04-01 02:01:54 -0700108
philipel17deeb42016-08-11 15:09:26 +0200109 uint16_t Rand() { return rand_.Rand<uint16_t>(); }
philipelc707ab72016-04-01 02:01:54 -0700110
philipel17deeb42016-08-11 15:09:26 +0200111 enum IsKeyFrame { kKeyFrame, kDeltaFrame };
112 enum IsFirst { kFirst, kNotFirst };
113 enum IsLast { kLast, kNotLast };
philipelc707ab72016-04-01 02:01:54 -0700114
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200115 PacketBufferInsertResult Insert(uint16_t seq_num, // packet sequence number
116 IsKeyFrame keyframe, // is keyframe
117 IsFirst first, // is first packet of frame
118 IsLast last, // is last packet of frame
Danil Chapovalove3c48842019-12-02 15:54:27 +0100119 rtc::ArrayView<const uint8_t> data = {},
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200120 uint32_t timestamp = 123u) { // rtp timestamp
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100121 auto packet = std::make_unique<PacketBuffer::Packet>();
122 packet->video_header.codec = kVideoCodecGeneric;
123 packet->timestamp = timestamp;
124 packet->seq_num = seq_num;
125 packet->video_header.frame_type = keyframe == kKeyFrame
126 ? VideoFrameType::kVideoFrameKey
127 : VideoFrameType::kVideoFrameDelta;
128 packet->video_header.is_first_packet_in_frame = first == kFirst;
129 packet->video_header.is_last_packet_in_frame = last == kLast;
130 packet->video_payload.SetData(data.data(), data.size());
philipelf4139332016-04-20 10:26:34 +0200131
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100132 return PacketBufferInsertResult(
133 packet_buffer_.InsertPacket(std::move(packet)));
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200134 }
135
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100136 const test::ScopedFieldTrials scoped_field_trials_;
philipelc707ab72016-04-01 02:01:54 -0700137 Random rand_;
Danil Chapovalove3c48842019-12-02 15:54:27 +0100138 SimulatedClock clock_;
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200139 PacketBuffer packet_buffer_;
philipelc707ab72016-04-01 02:01:54 -0700140};
141
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200142TEST_F(PacketBufferTest, InsertOnePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100143 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100144 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
philipelc707ab72016-04-01 02:01:54 -0700145}
146
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200147TEST_F(PacketBufferTest, InsertMultiplePackets) {
philipelaee3e0e2016-11-01 11:45:34 +0100148 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100149 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
150 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
151 EXPECT_THAT(Insert(seq_num + 2, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
152 EXPECT_THAT(Insert(seq_num + 3, kKeyFrame, kFirst, kLast).packets, SizeIs(1));
philipelc707ab72016-04-01 02:01:54 -0700153}
154
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200155TEST_F(PacketBufferTest, InsertDuplicatePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100156 const uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100157 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
158 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
159 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast).packets,
160 SizeIs(2));
philipelaee3e0e2016-11-01 11:45:34 +0100161}
162
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200163TEST_F(PacketBufferTest, SeqNumWrapOneFrame) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200164 Insert(0xFFFF, kKeyFrame, kFirst, kNotLast);
165 EXPECT_THAT(Insert(0x0, kKeyFrame, kNotFirst, kLast),
166 StartSeqNumsAre(0xFFFF));
philipel2c2f34c2017-01-03 05:55:34 -0800167}
168
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200169TEST_F(PacketBufferTest, SeqNumWrapTwoFrames) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200170 EXPECT_THAT(Insert(0xFFFF, kKeyFrame, kFirst, kLast),
171 StartSeqNumsAre(0xFFFF));
172 EXPECT_THAT(Insert(0x0, kKeyFrame, kFirst, kLast), StartSeqNumsAre(0x0));
philipelaee3e0e2016-11-01 11:45:34 +0100173}
174
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200175TEST_F(PacketBufferTest, InsertOldPackets) {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100176 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
177 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
178 EXPECT_THAT(Insert(101, kKeyFrame, kNotFirst, kLast).packets, SizeIs(2));
philipelaee3e0e2016-11-01 11:45:34 +0100179
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100180 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
181 EXPECT_THAT(Insert(100, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
182 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipelaee3e0e2016-11-01 11:45:34 +0100183
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200184 packet_buffer_.ClearTo(102);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100185 EXPECT_THAT(Insert(102, kDeltaFrame, kFirst, kLast).packets, IsEmpty());
186 EXPECT_THAT(Insert(103, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipel5ceaaae2016-05-24 10:20:47 +0200187}
188
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200189TEST_F(PacketBufferTest, FrameSize) {
philipelaee3e0e2016-11-01 11:45:34 +0100190 const uint16_t seq_num = Rand();
Danil Chapovalove3c48842019-12-02 15:54:27 +0100191 uint8_t data1[5] = {};
192 uint8_t data2[5] = {};
193 uint8_t data3[5] = {};
194 uint8_t data4[5] = {};
philipel5ceaaae2016-05-24 10:20:47 +0200195
Danil Chapovalove3c48842019-12-02 15:54:27 +0100196 Insert(seq_num, kKeyFrame, kFirst, kNotLast, data1);
197 Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast, data2);
198 Insert(seq_num + 2, kKeyFrame, kNotFirst, kNotLast, data3);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100199 auto packets =
200 Insert(seq_num + 3, kKeyFrame, kNotFirst, kLast, data4).packets;
201 // Expect one frame of 4 packets.
202 EXPECT_THAT(StartSeqNums(packets), ElementsAre(seq_num));
203 EXPECT_THAT(packets, SizeIs(4));
philipel5ceaaae2016-05-24 10:20:47 +0200204}
205
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200206TEST_F(PacketBufferTest, ExpandBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100207 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700208
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200209 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
Johannes Krona3705562019-08-26 16:37:11 +0200210 for (int i = 1; i < kStartSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200211 EXPECT_FALSE(
212 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200213
214 // Already inserted kStartSize number of packets, inserting the last packet
215 // should increase the buffer size and also result in an assembled frame.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200216 EXPECT_FALSE(
217 Insert(seq_num + kStartSize, kKeyFrame, kNotFirst, kLast).buffer_cleared);
philipelc707ab72016-04-01 02:01:54 -0700218}
219
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200220TEST_F(PacketBufferTest, SingleFrameExpandsBuffer) {
philipelaee3e0e2016-11-01 11:45:34 +0100221 const uint16_t seq_num = Rand();
222
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200223 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
philipelaee3e0e2016-11-01 11:45:34 +0100224 for (int i = 1; i < kStartSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200225 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast);
226 EXPECT_THAT(Insert(seq_num + kStartSize, kKeyFrame, kNotFirst, kLast),
227 StartSeqNumsAre(seq_num));
philipelaee3e0e2016-11-01 11:45:34 +0100228}
229
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200230TEST_F(PacketBufferTest, ExpandBufferOverflow) {
philipelaee3e0e2016-11-01 11:45:34 +0100231 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700232
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200233 EXPECT_FALSE(Insert(seq_num, kKeyFrame, kFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200234 for (int i = 1; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200235 EXPECT_FALSE(
236 Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast).buffer_cleared);
Johannes Krona3705562019-08-26 16:37:11 +0200237
238 // Already inserted kMaxSize number of packets, inserting the last packet
239 // should overflow the buffer and result in false being returned.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200240 EXPECT_TRUE(
241 Insert(seq_num + kMaxSize, kKeyFrame, kNotFirst, kLast).buffer_cleared);
philipelc707ab72016-04-01 02:01:54 -0700242}
243
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200244TEST_F(PacketBufferTest, OnePacketOneFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100245 const uint16_t seq_num = Rand();
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200246 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
247 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700248}
249
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200250TEST_F(PacketBufferTest, TwoPacketsTwoFrames) {
philipelaee3e0e2016-11-01 11:45:34 +0100251 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200252
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200253 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
254 StartSeqNumsAre(seq_num));
255 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kFirst, kLast),
256 StartSeqNumsAre(seq_num + 1));
philipelc707ab72016-04-01 02:01:54 -0700257}
258
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200259TEST_F(PacketBufferTest, TwoPacketsOneFrames) {
philipelaee3e0e2016-11-01 11:45:34 +0100260 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200261
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100262 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200263 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast),
264 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700265}
266
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200267TEST_F(PacketBufferTest, ThreePacketReorderingOneFrame) {
philipelaee3e0e2016-11-01 11:45:34 +0100268 const uint16_t seq_num = Rand();
philipelc707ab72016-04-01 02:01:54 -0700269
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100270 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kNotLast).packets, IsEmpty());
271 EXPECT_THAT(Insert(seq_num + 2, kKeyFrame, kNotFirst, kLast).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200272 IsEmpty());
273 EXPECT_THAT(Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast),
274 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700275}
276
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200277TEST_F(PacketBufferTest, Frames) {
philipelaee3e0e2016-11-01 11:45:34 +0100278 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200279
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200280 EXPECT_THAT(Insert(seq_num, kKeyFrame, kFirst, kLast),
281 StartSeqNumsAre(seq_num));
282 EXPECT_THAT(Insert(seq_num + 1, kDeltaFrame, kFirst, kLast),
283 StartSeqNumsAre(seq_num + 1));
284 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast),
285 StartSeqNumsAre(seq_num + 2));
286 EXPECT_THAT(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast),
287 StartSeqNumsAre(seq_num + 3));
philipelf4139332016-04-20 10:26:34 +0200288}
289
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200290TEST_F(PacketBufferTest, ClearSinglePacket) {
philipelaee3e0e2016-11-01 11:45:34 +0100291 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200292
philipelaee3e0e2016-11-01 11:45:34 +0100293 for (int i = 0; i < kMaxSize; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200294 Insert(seq_num + i, kDeltaFrame, kFirst, kLast);
philipelaee3e0e2016-11-01 11:45:34 +0100295
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200296 packet_buffer_.ClearTo(seq_num);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200297 EXPECT_FALSE(
298 Insert(seq_num + kMaxSize, kDeltaFrame, kFirst, kLast).buffer_cleared);
philipelaee3e0e2016-11-01 11:45:34 +0100299}
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
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100387// If |sps_pps_idr_is_keyframe| is true, we require keyframes to contain
388// SPS/PPS/IDR and the keyframes we create as part of the test do contain
389// SPS/PPS/IDR. If |sps_pps_idr_is_keyframe| is false, we only require and
390// 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)
394 : PacketBufferTest(sps_pps_idr_is_keyframe
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100395 ? "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"
396 : ""),
397 sps_pps_idr_is_keyframe_(sps_pps_idr_is_keyframe) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200398
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200399 PacketBufferInsertResult InsertH264(
Danil Chapovalove3c48842019-12-02 15:54:27 +0100400 uint16_t seq_num, // packet sequence number
401 IsKeyFrame keyframe, // is keyframe
402 IsFirst first, // is first packet of frame
403 IsLast last, // is last packet of frame
404 uint32_t timestamp, // rtp timestamp
405 rtc::ArrayView<const uint8_t> data = {},
406 uint32_t width = 0, // width of frame (SPS/IDR)
407 uint32_t height = 0) { // height of frame (SPS/IDR)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100408 auto packet = std::make_unique<PacketBuffer::Packet>();
409 packet->video_header.codec = kVideoCodecH264;
philipel7d745e52018-08-02 14:03:53 +0200410 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100411 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
412 packet->seq_num = seq_num;
413 packet->timestamp = timestamp;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200414 if (keyframe == kKeyFrame) {
415 if (sps_pps_idr_is_keyframe_) {
philipel7d745e52018-08-02 14:03:53 +0200416 h264_header.nalus[0].type = H264::NaluType::kSps;
417 h264_header.nalus[1].type = H264::NaluType::kPps;
418 h264_header.nalus[2].type = H264::NaluType::kIdr;
419 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200420 } else {
philipel7d745e52018-08-02 14:03:53 +0200421 h264_header.nalus[0].type = H264::NaluType::kIdr;
422 h264_header.nalus_length = 1;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200423 }
424 }
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100425 packet->video_header.width = width;
426 packet->video_header.height = height;
427 packet->video_header.is_first_packet_in_frame = first == kFirst;
428 packet->video_header.is_last_packet_in_frame = last == kLast;
429 packet->video_payload.SetData(data.data(), data.size());
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200430
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100431 return PacketBufferInsertResult(
432 packet_buffer_.InsertPacket(std::move(packet)));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200433 }
434
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200435 PacketBufferInsertResult InsertH264KeyFrameWithAud(
Danil Chapovalove3c48842019-12-02 15:54:27 +0100436 uint16_t seq_num, // packet sequence number
437 IsKeyFrame keyframe, // is keyframe
438 IsFirst first, // is first packet of frame
439 IsLast last, // is last packet of frame
440 uint32_t timestamp, // rtp timestamp
441 rtc::ArrayView<const uint8_t> data = {},
442 uint32_t width = 0, // width of frame (SPS/IDR)
443 uint32_t height = 0) { // height of frame (SPS/IDR)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100444 auto packet = std::make_unique<PacketBuffer::Packet>();
445 packet->video_header.codec = kVideoCodecH264;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700446 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100447 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
448 packet->seq_num = seq_num;
449 packet->timestamp = timestamp;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700450
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200451 // this should be the start of frame.
452 RTC_CHECK(first == kFirst);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700453
454 // Insert a AUD NALU / packet without width/height.
455 h264_header.nalus[0].type = H264::NaluType::kAud;
456 h264_header.nalus_length = 1;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100457 packet->video_header.is_first_packet_in_frame = true;
458 packet->video_header.is_last_packet_in_frame = false;
459 IgnoreResult(packet_buffer_.InsertPacket(std::move(packet)));
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200460 // insert IDR
Danil Chapovalove3c48842019-12-02 15:54:27 +0100461 return InsertH264(seq_num + 1, keyframe, kNotFirst, last, timestamp, data,
462 width, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700463 }
464
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200465 const bool sps_pps_idr_is_keyframe_;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100466};
467
468// This fixture is used to test the general behaviour of the packet buffer
469// in both configurations.
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200470class PacketBufferH264ParameterizedTest
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100471 : public ::testing::WithParamInterface<bool>,
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200472 public PacketBufferH264Test {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100473 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200474 PacketBufferH264ParameterizedTest() : PacketBufferH264Test(GetParam()) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200475};
476
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100477INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200478 PacketBufferH264ParameterizedTest,
479 ::testing::Bool());
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200480
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200481TEST_P(PacketBufferH264ParameterizedTest, DontRemoveMissingPacketOnClearTo) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200482 InsertH264(0, kKeyFrame, kFirst, kLast, 0);
483 InsertH264(2, kDeltaFrame, kFirst, kNotLast, 2);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200484 packet_buffer_.ClearTo(0);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200485 // Expect no frame because of missing of packet #1
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100486 EXPECT_THAT(InsertH264(3, kDeltaFrame, kNotFirst, kLast, 2).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200487 IsEmpty());
philipelbc5a4082017-12-06 10:41:08 +0100488}
489
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200490TEST_P(PacketBufferH264ParameterizedTest, GetBitstreamOneFrameFullBuffer) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100491 uint8_t data_arr[kStartSize][1];
philipel227f8b92017-08-04 06:39:31 -0700492 uint8_t expected[kStartSize];
philipel227f8b92017-08-04 06:39:31 -0700493
494 for (uint8_t i = 0; i < kStartSize; ++i) {
philipel227f8b92017-08-04 06:39:31 -0700495 data_arr[i][0] = i;
496 expected[i] = i;
497 }
498
Danil Chapovalove3c48842019-12-02 15:54:27 +0100499 InsertH264(0, kKeyFrame, kFirst, kNotLast, 1, data_arr[0]);
philipel227f8b92017-08-04 06:39:31 -0700500 for (uint8_t i = 1; i < kStartSize - 1; ++i) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100501 InsertH264(i, kKeyFrame, kNotFirst, kNotLast, 1, data_arr[i]);
philipel227f8b92017-08-04 06:39:31 -0700502 }
philipel227f8b92017-08-04 06:39:31 -0700503
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100504 auto packets = InsertH264(kStartSize - 1, kKeyFrame, kNotFirst, kLast, 1,
505 data_arr[kStartSize - 1])
506 .packets;
507 ASSERT_THAT(StartSeqNums(packets), ElementsAre(0));
508 EXPECT_THAT(packets, SizeIs(kStartSize));
509 for (size_t i = 0; i < packets.size(); ++i) {
510 EXPECT_THAT(packets[i]->video_payload, SizeIs(1)) << "Packet #" << i;
511 }
philipel227f8b92017-08-04 06:39:31 -0700512}
513
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200514TEST_P(PacketBufferH264ParameterizedTest, GetBitstreamBufferPadding) {
philipel36928452016-11-07 10:42:36 +0100515 uint16_t seq_num = Rand();
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100516 rtc::CopyOnWriteBuffer data = "some plain old data";
philipel36928452016-11-07 10:42:36 +0100517
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100518 auto packet = std::make_unique<PacketBuffer::Packet>();
philipel7d745e52018-08-02 14:03:53 +0200519 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100520 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200521 h264_header.nalus_length = 1;
522 h264_header.nalus[0].type = H264::NaluType::kIdr;
523 h264_header.packetization_type = kH264SingleNalu;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100524 packet->seq_num = seq_num;
525 packet->video_header.codec = kVideoCodecH264;
526 packet->video_payload = data;
527 packet->video_header.is_first_packet_in_frame = true;
528 packet->video_header.is_last_packet_in_frame = true;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100529 auto frames = packet_buffer_.InsertPacket(std::move(packet)).packets;
philipel36928452016-11-07 10:42:36 +0100530
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200531 ASSERT_THAT(frames, SizeIs(1));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100532 EXPECT_EQ(frames[0]->seq_num, seq_num);
533 EXPECT_EQ(frames[0]->video_payload, data);
philipel36928452016-11-07 10:42:36 +0100534}
535
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200536TEST_P(PacketBufferH264ParameterizedTest, FrameResolution) {
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700537 uint16_t seq_num = 100;
Danil Chapovalove3c48842019-12-02 15:54:27 +0100538 uint8_t data[] = "some plain old data";
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700539 uint32_t width = 640;
540 uint32_t height = 360;
541 uint32_t timestamp = 1000;
542
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100543 auto packets = InsertH264(seq_num, kKeyFrame, kFirst, kLast, timestamp, data,
544 width, height)
545 .packets;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700546
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100547 ASSERT_THAT(packets, SizeIs(1));
548 EXPECT_EQ(packets[0]->video_header.width, width);
549 EXPECT_EQ(packets[0]->video_header.height, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700550}
551
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200552TEST_P(PacketBufferH264ParameterizedTest, FrameResolutionNaluBeforeSPS) {
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700553 uint16_t seq_num = 100;
Danil Chapovalove3c48842019-12-02 15:54:27 +0100554 uint8_t data[] = "some plain old data";
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700555 uint32_t width = 640;
556 uint32_t height = 360;
557 uint32_t timestamp = 1000;
558
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100559 auto packets = InsertH264KeyFrameWithAud(seq_num, kKeyFrame, kFirst, kLast,
560 timestamp, data, width, height)
561 .packets;
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700562
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100563 ASSERT_THAT(StartSeqNums(packets), ElementsAre(seq_num));
564 EXPECT_EQ(packets[0]->video_header.width, width);
565 EXPECT_EQ(packets[0]->video_header.height, height);
Shyam Sadhwani5b2df172019-10-16 09:13:38 -0700566}
567
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200568TEST_F(PacketBufferTest, FreeSlotsOnFrameCreation) {
philipelaee3e0e2016-11-01 11:45:34 +0100569 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200570
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200571 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
572 Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast);
573 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast),
574 StartSeqNumsAre(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700575
philipel17deeb42016-08-11 15:09:26 +0200576 // Insert frame that fills the whole buffer.
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200577 Insert(seq_num + 3, kKeyFrame, kFirst, kNotLast);
philipel17deeb42016-08-11 15:09:26 +0200578 for (int i = 0; i < kMaxSize - 2; ++i)
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200579 Insert(seq_num + i + 4, kDeltaFrame, kNotFirst, kNotLast);
580 EXPECT_THAT(Insert(seq_num + kMaxSize + 2, kKeyFrame, kNotFirst, kLast),
581 StartSeqNumsAre(seq_num + 3));
philipelc707ab72016-04-01 02:01:54 -0700582}
583
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200584TEST_F(PacketBufferTest, Clear) {
philipelaee3e0e2016-11-01 11:45:34 +0100585 const uint16_t seq_num = Rand();
philipelf4139332016-04-20 10:26:34 +0200586
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200587 Insert(seq_num, kKeyFrame, kFirst, kNotLast);
588 Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast);
589 EXPECT_THAT(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast),
590 StartSeqNumsAre(seq_num));
philipelf4139332016-04-20 10:26:34 +0200591
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200592 packet_buffer_.Clear();
philipelf4139332016-04-20 10:26:34 +0200593
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200594 Insert(seq_num + kStartSize, kKeyFrame, kFirst, kNotLast);
595 Insert(seq_num + kStartSize + 1, kDeltaFrame, kNotFirst, kNotLast);
596 EXPECT_THAT(Insert(seq_num + kStartSize + 2, kDeltaFrame, kNotFirst, kLast),
597 StartSeqNumsAre(seq_num + kStartSize));
philipelc707ab72016-04-01 02:01:54 -0700598}
599
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200600TEST_F(PacketBufferTest, FramesAfterClear) {
philipel20dce342016-11-28 16:14:57 +0100601 Insert(9025, kDeltaFrame, kFirst, kLast);
602 Insert(9024, kKeyFrame, kFirst, kLast);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200603 packet_buffer_.ClearTo(9025);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100604 EXPECT_THAT(Insert(9057, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
605 EXPECT_THAT(Insert(9026, kDeltaFrame, kFirst, kLast).packets, SizeIs(1));
philipel20dce342016-11-28 16:14:57 +0100606}
607
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200608TEST_F(PacketBufferTest, SameFrameDifferentTimestamps) {
Danil Chapovalove3c48842019-12-02 15:54:27 +0100609 Insert(0, kKeyFrame, kFirst, kNotLast, {}, 1000);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100610 EXPECT_THAT(Insert(1, kKeyFrame, kNotFirst, kLast, {}, 1001).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200611 IsEmpty());
philipel8b6995b2019-01-09 12:39:18 +0100612}
613
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200614TEST_F(PacketBufferTest, ContinuousSeqNumDoubleMarkerBit) {
philipelea142f82017-01-11 02:01:56 -0800615 Insert(2, kKeyFrame, kNotFirst, kNotLast);
616 Insert(1, kKeyFrame, kFirst, kLast);
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100617 EXPECT_THAT(Insert(3, kKeyFrame, kNotFirst, kLast).packets, IsEmpty());
philipelea142f82017-01-11 02:01:56 -0800618}
619
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200620TEST_F(PacketBufferTest, PacketTimestamps) {
Danil Chapovalov0040b662018-06-18 10:48:16 +0200621 absl::optional<int64_t> packet_ms;
622 absl::optional<int64_t> packet_keyframe_ms;
philipel3184f8e2017-05-18 08:08:53 -0700623
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200624 packet_ms = packet_buffer_.LastReceivedPacketMs();
625 packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
philipel3184f8e2017-05-18 08:08:53 -0700626 EXPECT_FALSE(packet_ms);
627 EXPECT_FALSE(packet_keyframe_ms);
628
Danil Chapovalove3c48842019-12-02 15:54:27 +0100629 int64_t keyframe_ms = clock_.TimeInMilliseconds();
Danil Chapovalovc9e532a2019-12-10 17:03:00 +0100630 Insert(100, kKeyFrame, kFirst, kLast, {}, /*timestamp=*/1000);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200631 packet_ms = packet_buffer_.LastReceivedPacketMs();
632 packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
philipel3184f8e2017-05-18 08:08:53 -0700633 EXPECT_TRUE(packet_ms);
634 EXPECT_TRUE(packet_keyframe_ms);
635 EXPECT_EQ(keyframe_ms, *packet_ms);
636 EXPECT_EQ(keyframe_ms, *packet_keyframe_ms);
637
Danil Chapovalove3c48842019-12-02 15:54:27 +0100638 clock_.AdvanceTimeMilliseconds(100);
639 int64_t delta_ms = clock_.TimeInMilliseconds();
Danil Chapovalovc9e532a2019-12-10 17:03:00 +0100640 Insert(101, kDeltaFrame, kFirst, kLast, {}, /*timestamp=*/2000);
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200641 packet_ms = packet_buffer_.LastReceivedPacketMs();
642 packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
philipel3184f8e2017-05-18 08:08:53 -0700643 EXPECT_TRUE(packet_ms);
644 EXPECT_TRUE(packet_keyframe_ms);
645 EXPECT_EQ(delta_ms, *packet_ms);
646 EXPECT_EQ(keyframe_ms, *packet_keyframe_ms);
647
Danil Chapovalovf7457e52019-09-20 17:57:15 +0200648 packet_buffer_.Clear();
649 packet_ms = packet_buffer_.LastReceivedPacketMs();
650 packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
philipel3184f8e2017-05-18 08:08:53 -0700651 EXPECT_FALSE(packet_ms);
652 EXPECT_FALSE(packet_keyframe_ms);
653}
654
Danil Chapovalovc9e532a2019-12-10 17:03:00 +0100655TEST_F(PacketBufferTest,
656 LastReceivedKeyFrameReturnsReceiveTimeOfALastReceivedPacketOfAKeyFrame) {
657 clock_.AdvanceTimeMilliseconds(100);
658 Insert(/*seq_num=*/100, kKeyFrame, kFirst, kNotLast, {}, /*timestamp=*/1000);
659 EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
660 clock_.TimeInMilliseconds());
661
662 clock_.AdvanceTimeMilliseconds(100);
663 Insert(/*seq_num=*/102, kDeltaFrame, kNotFirst, kLast, {},
664 /*timestamp=*/1000);
665 EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
666 clock_.TimeInMilliseconds());
667
668 clock_.AdvanceTimeMilliseconds(100);
669 Insert(/*seq_num=*/101, kDeltaFrame, kNotFirst, kNotLast, {},
670 /*timestamp=*/1000);
671 EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
672 clock_.TimeInMilliseconds());
673
674 clock_.AdvanceTimeMilliseconds(100);
675 Insert(/*seq_num=*/103, kDeltaFrame, kFirst, kNotLast, {},
676 /*timestamp=*/2000);
677 EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
678 clock_.TimeInMilliseconds() - 100);
679}
680
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200681TEST_F(PacketBufferTest, IncomingCodecChange) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100682 auto packet = std::make_unique<PacketBuffer::Packet>();
683 packet->video_header.is_first_packet_in_frame = true;
684 packet->video_header.is_last_packet_in_frame = true;
685 packet->video_header.codec = kVideoCodecVP8;
686 packet->video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
687 packet->timestamp = 1;
688 packet->seq_num = 1;
689 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100690 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
691 SizeIs(1));
philipel09133af2018-05-17 14:11:09 +0200692
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100693 packet = std::make_unique<PacketBuffer::Packet>();
694 packet->video_header.is_first_packet_in_frame = true;
695 packet->video_header.is_last_packet_in_frame = true;
696 packet->video_header.codec = kVideoCodecH264;
philipel7d745e52018-08-02 14:03:53 +0200697 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100698 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200699 h264_header.nalus_length = 1;
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100700 packet->timestamp = 3;
701 packet->seq_num = 3;
702 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100703 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
704 IsEmpty());
philipel09133af2018-05-17 14:11:09 +0200705
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100706 packet = std::make_unique<PacketBuffer::Packet>();
707 packet->video_header.is_first_packet_in_frame = true;
708 packet->video_header.is_last_packet_in_frame = true;
709 packet->video_header.codec = kVideoCodecVP8;
710 packet->video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
711 packet->timestamp = 2;
712 packet->seq_num = 2;
713 packet->video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100714 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
715 SizeIs(2));
philipel09133af2018-05-17 14:11:09 +0200716}
717
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200718TEST_F(PacketBufferTest, TooManyNalusInPacket) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100719 auto packet = std::make_unique<PacketBuffer::Packet>();
720 packet->video_header.codec = kVideoCodecH264;
721 packet->timestamp = 1;
722 packet->seq_num = 1;
723 packet->video_header.frame_type = VideoFrameType::kVideoFrameKey;
724 packet->video_header.is_first_packet_in_frame = true;
725 packet->video_header.is_last_packet_in_frame = true;
philipel7d745e52018-08-02 14:03:53 +0200726 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100727 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200728 h264_header.nalus_length = kMaxNalusPerPacket;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100729 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
730 IsEmpty());
philipel09133af2018-05-17 14:11:09 +0200731}
732
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200733TEST_P(PacketBufferH264ParameterizedTest, OneFrameFillBuffer) {
philipel2c9f9f22017-06-13 02:47:28 -0700734 InsertH264(0, kKeyFrame, kFirst, kNotLast, 1000);
735 for (int i = 1; i < kStartSize - 1; ++i)
736 InsertH264(i, kKeyFrame, kNotFirst, kNotLast, 1000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200737 EXPECT_THAT(InsertH264(kStartSize - 1, kKeyFrame, kNotFirst, kLast, 1000),
738 StartSeqNumsAre(0));
philipel2c9f9f22017-06-13 02:47:28 -0700739}
740
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200741TEST_P(PacketBufferH264ParameterizedTest, CreateFramesAfterFilledBuffer) {
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100742 EXPECT_THAT(InsertH264(kStartSize - 2, kKeyFrame, kFirst, kLast, 0).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200743 SizeIs(1));
philipel227f8b92017-08-04 06:39:31 -0700744
745 InsertH264(kStartSize, kDeltaFrame, kFirst, kNotLast, 2000);
746 for (int i = 1; i < kStartSize; ++i)
747 InsertH264(kStartSize + i, kDeltaFrame, kNotFirst, kNotLast, 2000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200748 EXPECT_THAT(
749 InsertH264(kStartSize + kStartSize, kDeltaFrame, kNotFirst, kLast, 2000)
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100750 .packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200751 IsEmpty());
philipel227f8b92017-08-04 06:39:31 -0700752
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200753 EXPECT_THAT(InsertH264(kStartSize - 1, kKeyFrame, kFirst, kLast, 1000),
754 StartSeqNumsAre(kStartSize - 1, kStartSize));
philipel227f8b92017-08-04 06:39:31 -0700755}
756
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200757TEST_P(PacketBufferH264ParameterizedTest, OneFrameMaxSeqNum) {
philipel2c9f9f22017-06-13 02:47:28 -0700758 InsertH264(65534, kKeyFrame, kFirst, kNotLast, 1000);
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200759 EXPECT_THAT(InsertH264(65535, kKeyFrame, kNotFirst, kLast, 1000),
760 StartSeqNumsAre(65534));
philipel2c9f9f22017-06-13 02:47:28 -0700761}
762
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200763TEST_P(PacketBufferH264ParameterizedTest, ClearMissingPacketsOnKeyframe) {
philipel2c9f9f22017-06-13 02:47:28 -0700764 InsertH264(0, kKeyFrame, kFirst, kLast, 1000);
765 InsertH264(2, kKeyFrame, kFirst, kLast, 3000);
766 InsertH264(3, kDeltaFrame, kFirst, kNotLast, 4000);
767 InsertH264(4, kDeltaFrame, kNotFirst, kLast, 4000);
768
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200769 EXPECT_THAT(InsertH264(kStartSize + 1, kKeyFrame, kFirst, kLast, 18000),
770 StartSeqNumsAre(kStartSize + 1));
philipel2c9f9f22017-06-13 02:47:28 -0700771}
772
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200773TEST_P(PacketBufferH264ParameterizedTest, FindFramesOnPadding) {
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200774 EXPECT_THAT(InsertH264(0, kKeyFrame, kFirst, kLast, 1000),
775 StartSeqNumsAre(0));
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100776 EXPECT_THAT(InsertH264(2, kDeltaFrame, kFirst, kLast, 1000).packets,
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200777 IsEmpty());
philipel2c9f9f22017-06-13 02:47:28 -0700778
Danil Chapovalov1dac7072019-10-24 12:44:23 +0200779 EXPECT_THAT(packet_buffer_.InsertPadding(1), StartSeqNumsAre(2));
philipel2c9f9f22017-06-13 02:47:28 -0700780}
781
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200782class PacketBufferH264XIsKeyframeTest : public PacketBufferH264Test {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200783 protected:
784 const uint16_t kSeqNum = 5;
785
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200786 explicit PacketBufferH264XIsKeyframeTest(bool sps_pps_idr_is_keyframe)
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100787 : PacketBufferH264Test(sps_pps_idr_is_keyframe) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200788
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100789 std::unique_ptr<PacketBuffer::Packet> CreatePacket() {
790 auto packet = std::make_unique<PacketBuffer::Packet>();
791 packet->video_header.codec = kVideoCodecH264;
792 packet->seq_num = kSeqNum;
793
794 packet->video_header.is_first_packet_in_frame = true;
795 packet->video_header.is_last_packet_in_frame = true;
796 return packet;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200797 }
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200798};
799
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200800class PacketBufferH264IdrIsKeyframeTest
801 : public PacketBufferH264XIsKeyframeTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200802 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200803 PacketBufferH264IdrIsKeyframeTest()
804 : PacketBufferH264XIsKeyframeTest(false) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200805};
806
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200807TEST_F(PacketBufferH264IdrIsKeyframeTest, IdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100808 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200809 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100810 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200811 h264_header.nalus[0].type = H264::NaluType::kIdr;
812 h264_header.nalus_length = 1;
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100813 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200814 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200815}
816
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200817TEST_F(PacketBufferH264IdrIsKeyframeTest, SpsPpsIdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100818 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200819 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100820 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200821 h264_header.nalus[0].type = H264::NaluType::kSps;
822 h264_header.nalus[1].type = H264::NaluType::kPps;
823 h264_header.nalus[2].type = H264::NaluType::kIdr;
824 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200825
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100826 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200827 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200828}
829
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200830class PacketBufferH264SpsPpsIdrIsKeyframeTest
831 : public PacketBufferH264XIsKeyframeTest {
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200832 protected:
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200833 PacketBufferH264SpsPpsIdrIsKeyframeTest()
834 : PacketBufferH264XIsKeyframeTest(true) {}
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200835};
836
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200837TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, IdrIsNotKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100838 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200839 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100840 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200841 h264_header.nalus[0].type = H264::NaluType::kIdr;
842 h264_header.nalus_length = 1;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200843
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100844 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200845 ElementsAre(DeltaFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200846}
847
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200848TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIsNotKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100849 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200850 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100851 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200852 h264_header.nalus[0].type = H264::NaluType::kSps;
853 h264_header.nalus[1].type = H264::NaluType::kPps;
854 h264_header.nalus_length = 2;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200855
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100856 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200857 ElementsAre(DeltaFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200858}
859
Danil Chapovalov05269ec2019-10-17 19:06:46 +0200860TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIdrIsKeyframe) {
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100861 auto packet = CreatePacket();
philipel7d745e52018-08-02 14:03:53 +0200862 auto& h264_header =
Danil Chapovalov97ffbef2020-01-24 16:04:35 +0100863 packet->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
philipel7d745e52018-08-02 14:03:53 +0200864 h264_header.nalus[0].type = H264::NaluType::kSps;
865 h264_header.nalus[1].type = H264::NaluType::kPps;
866 h264_header.nalus[2].type = H264::NaluType::kIdr;
867 h264_header.nalus_length = 3;
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200868
Danil Chapovalov810b4ca2020-03-19 13:56:11 +0100869 EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets,
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200870 ElementsAre(KeyFrame()));
Rasmus Brandtedf4ff72017-10-24 10:07:48 +0200871}
872
Danil Chapovalovce1ffcd2019-10-22 17:12:42 +0200873} // namespace
philipelc707ab72016-04-01 02:01:54 -0700874} // namespace video_coding
875} // namespace webrtc