Only advance |first_seq_num_| if packets are explicitly cleared from the PacketBuffer.

In this CL:
 - Don't insert a packet if we have explicitly cleared past it.
 - Added some logging to ExpandBufferSize.
 - Renamed IsContinuous to PotentialNewFrame.
 - Unittests updated/added for this new behavior.
 - Refactored TestPacketBuffer unittests.

BUG=webrtc:5514
R=danilchap@webrtc.org, stefan@webrtc.org

Review URL: https://codereview.webrtc.org/2399373002 .

Cr-Commit-Position: refs/heads/master@{#14871}
This commit is contained in:
philipel
2016-11-01 11:45:34 +01:00
parent b521aa704f
commit aee3e0eb32
4 changed files with 211 additions and 156 deletions

1
third_party/drmemory vendored Symbolic link
View File

@ -0,0 +1 @@
../chromium/src/third_party/drmemory

View File

@ -42,6 +42,7 @@ PacketBuffer::PacketBuffer(Clock* clock,
first_seq_num_(0), first_seq_num_(0),
last_seq_num_(0), last_seq_num_(0),
first_packet_received_(false), first_packet_received_(false),
is_cleared_to_first_seq_num_(false),
data_buffer_(start_buffer_size), data_buffer_(start_buffer_size),
sequence_buffer_(start_buffer_size), sequence_buffer_(start_buffer_size),
received_frame_callback_(received_frame_callback) { received_frame_callback_(received_frame_callback) {
@ -51,7 +52,9 @@ PacketBuffer::PacketBuffer(Clock* clock,
RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
} }
PacketBuffer::~PacketBuffer() {} PacketBuffer::~PacketBuffer() {
Clear();
}
bool PacketBuffer::InsertPacket(const VCMPacket& packet) { bool PacketBuffer::InsertPacket(const VCMPacket& packet) {
rtc::CritScope lock(&crit_); rtc::CritScope lock(&crit_);
@ -59,9 +62,16 @@ bool PacketBuffer::InsertPacket(const VCMPacket& packet) {
size_t index = seq_num % size_; size_t index = seq_num % size_;
if (!first_packet_received_) { if (!first_packet_received_) {
first_seq_num_ = seq_num - 1; first_seq_num_ = seq_num;
last_seq_num_ = seq_num; last_seq_num_ = seq_num;
first_packet_received_ = true; first_packet_received_ = true;
} else if (AheadOf(first_seq_num_, seq_num)) {
// If we have explicitly cleared past this packet then it's old,
// don't insert it.
if (is_cleared_to_first_seq_num_)
return false;
first_seq_num_ = seq_num;
} }
if (sequence_buffer_[index].used) { if (sequence_buffer_[index].used) {
@ -106,19 +116,39 @@ bool PacketBuffer::InsertPacket(const VCMPacket& packet) {
void PacketBuffer::ClearTo(uint16_t seq_num) { void PacketBuffer::ClearTo(uint16_t seq_num) {
rtc::CritScope lock(&crit_); rtc::CritScope lock(&crit_);
size_t index = first_seq_num_ % size_;
while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) { // If the packet buffer was cleared between a frame was created and returned.
index = (index + 1) % size_; if (!first_packet_received_)
++first_seq_num_; return;
is_cleared_to_first_seq_num_ = true;
while (AheadOrAt<uint16_t>(seq_num, first_seq_num_)) {
size_t index = first_seq_num_ % size_;
delete[] data_buffer_[index].dataPtr; delete[] data_buffer_[index].dataPtr;
data_buffer_[index].dataPtr = nullptr; data_buffer_[index].dataPtr = nullptr;
sequence_buffer_[index].used = false; sequence_buffer_[index].used = false;
++first_seq_num_;
} }
} }
void PacketBuffer::Clear() {
rtc::CritScope lock(&crit_);
for (size_t i = 0; i < size_; ++i) {
delete[] data_buffer_[i].dataPtr;
data_buffer_[i].dataPtr = nullptr;
sequence_buffer_[i].used = false;
}
first_packet_received_ = false;
is_cleared_to_first_seq_num_ = false;
}
bool PacketBuffer::ExpandBufferSize() { bool PacketBuffer::ExpandBufferSize() {
if (size_ == max_size_) if (size_ == max_size_) {
LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
<< "), failed to increase size.";
return false; return false;
}
size_t new_size = std::min(max_size_, 2 * size_); size_t new_size = std::min(max_size_, 2 * size_);
std::vector<VCMPacket> new_data_buffer(new_size); std::vector<VCMPacket> new_data_buffer(new_size);
@ -133,10 +163,11 @@ bool PacketBuffer::ExpandBufferSize() {
size_ = new_size; size_ = new_size;
sequence_buffer_ = std::move(new_sequence_buffer); sequence_buffer_ = std::move(new_sequence_buffer);
data_buffer_ = std::move(new_data_buffer); data_buffer_ = std::move(new_data_buffer);
LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
return true; return true;
} }
bool PacketBuffer::IsContinuous(uint16_t seq_num) const { bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
size_t index = seq_num % size_; size_t index = seq_num % size_;
int prev_index = index > 0 ? index - 1 : size_ - 1; int prev_index = index > 0 ? index - 1 : size_ - 1;
@ -144,13 +175,22 @@ bool PacketBuffer::IsContinuous(uint16_t seq_num) const {
return false; return false;
if (sequence_buffer_[index].frame_created) if (sequence_buffer_[index].frame_created)
return false; return false;
if (sequence_buffer_[index].frame_begin) if (sequence_buffer_[index].frame_begin &&
(!sequence_buffer_[prev_index].used ||
AheadOf(seq_num, sequence_buffer_[prev_index].seq_num))) {
// The reason we only return true if this packet is the first packet of the
// frame and the sequence number is newer than the packet with the previous
// index is because we want to avoid an inifite loop in the case where
// a single frame containing more packets than the current size of the
// packet buffer is inserted.
return true; return true;
}
if (!sequence_buffer_[prev_index].used) if (!sequence_buffer_[prev_index].used)
return false; return false;
if (sequence_buffer_[prev_index].seq_num != if (sequence_buffer_[prev_index].seq_num !=
static_cast<uint16_t>(seq_num - 1)) sequence_buffer_[index].seq_num - 1) {
return false; return false;
}
if (sequence_buffer_[prev_index].continuous) if (sequence_buffer_[prev_index].continuous)
return true; return true;
@ -158,8 +198,8 @@ bool PacketBuffer::IsContinuous(uint16_t seq_num) const {
} }
void PacketBuffer::FindFrames(uint16_t seq_num) { void PacketBuffer::FindFrames(uint16_t seq_num) {
size_t index = seq_num % size_; while (PotentialNewFrame(seq_num)) {
while (IsContinuous(seq_num)) { size_t index = seq_num % size_;
sequence_buffer_[index].continuous = true; sequence_buffer_[index].continuous = true;
// If all packets of the frame is continuous, find the first packet of the // If all packets of the frame is continuous, find the first packet of the
@ -192,7 +232,6 @@ void PacketBuffer::FindFrames(uint16_t seq_num) {
received_frame_callback_->OnReceivedFrame(std::move(frame)); received_frame_callback_->OnReceivedFrame(std::move(frame));
} }
index = (index + 1) % size_;
++seq_num; ++seq_num;
} }
} }
@ -212,13 +251,6 @@ void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
index = (index + 1) % size_; index = (index + 1) % size_;
++seq_num; ++seq_num;
} }
index = first_seq_num_ % size_;
while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) &&
!sequence_buffer_[index].used) {
++first_seq_num_;
index = (index + 1) % size_;
}
} }
bool PacketBuffer::GetBitstream(const RtpFrameObject& frame, bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
@ -254,14 +286,6 @@ VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
return &data_buffer_[index]; return &data_buffer_[index];
} }
void PacketBuffer::Clear() {
rtc::CritScope lock(&crit_);
for (size_t i = 0; i < size_; ++i)
sequence_buffer_[i].used = false;
first_packet_received_ = false;
}
int PacketBuffer::AddRef() const { int PacketBuffer::AddRef() const {
return rtc::AtomicOps::Increment(&ref_count_); return rtc::AtomicOps::Increment(&ref_count_);
} }

View File

@ -48,7 +48,8 @@ class PacketBuffer {
virtual ~PacketBuffer(); virtual ~PacketBuffer();
// Made virtual for testing. // Returns true if |packet| is inserted into the packet buffer,
// false otherwise. Made virtual for testing.
virtual bool InsertPacket(const VCMPacket& packet); virtual bool InsertPacket(const VCMPacket& packet);
void ClearTo(uint16_t seq_num); void ClearTo(uint16_t seq_num);
void Clear(); void Clear();
@ -94,7 +95,8 @@ class PacketBuffer {
bool ExpandBufferSize() EXCLUSIVE_LOCKS_REQUIRED(crit_); bool ExpandBufferSize() EXCLUSIVE_LOCKS_REQUIRED(crit_);
// Test if all previous packets has arrived for the given sequence number. // Test if all previous packets has arrived for the given sequence number.
bool IsContinuous(uint16_t seq_num) const EXCLUSIVE_LOCKS_REQUIRED(crit_); bool PotentialNewFrame(uint16_t seq_num) const
EXCLUSIVE_LOCKS_REQUIRED(crit_);
// Test if all packets of a frame has arrived, and if so, creates a frame. // Test if all packets of a frame has arrived, and if so, creates a frame.
// May create multiple frames per invocation. // May create multiple frames per invocation.
@ -127,6 +129,9 @@ class PacketBuffer {
// If the packet buffer has received its first packet. // If the packet buffer has received its first packet.
bool first_packet_received_ GUARDED_BY(crit_); bool first_packet_received_ GUARDED_BY(crit_);
// If the buffer is cleared to |first_seq_num_|.
bool is_cleared_to_first_seq_num_ GUARDED_BY(crit_);
// Buffer that holds the inserted packets. // Buffer that holds the inserted packets.
std::vector<VCMPacket> data_buffer_ GUARDED_BY(crit_); std::vector<VCMPacket> data_buffer_ GUARDED_BY(crit_);

View File

@ -49,12 +49,12 @@ class TestPacketBuffer : public ::testing::Test,
enum IsFirst { kFirst, kNotFirst }; enum IsFirst { kFirst, kNotFirst };
enum IsLast { kLast, kNotLast }; enum IsLast { kLast, kNotLast };
void InsertPacket(uint16_t seq_num, // packet sequence number bool Insert(uint16_t seq_num, // packet sequence number
IsKeyFrame keyframe, // is keyframe IsKeyFrame keyframe, // is keyframe
IsFirst first, // is first packet of frame IsFirst first, // is first packet of frame
IsLast last, // is last packet of frame IsLast last, // is last packet of frame
int data_size = 0, // size of data int data_size = 0, // size of data
uint8_t* data = nullptr) { // data pointer uint8_t* data = nullptr) { // data pointer
VCMPacket packet; VCMPacket packet;
packet.codec = kVideoCodecGeneric; packet.codec = kVideoCodecGeneric;
packet.seqNum = seq_num; packet.seqNum = seq_num;
@ -64,7 +64,7 @@ class TestPacketBuffer : public ::testing::Test,
packet.sizeBytes = data_size; packet.sizeBytes = data_size;
packet.dataPtr = data; packet.dataPtr = data;
EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); return packet_buffer_->InsertPacket(packet);
} }
void CheckFrame(uint16_t first_seq_num) { void CheckFrame(uint16_t first_seq_num) {
@ -84,26 +84,55 @@ class TestPacketBuffer : public ::testing::Test,
}; };
TEST_F(TestPacketBuffer, InsertOnePacket) { TEST_F(TestPacketBuffer, InsertOnePacket) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
} }
TEST_F(TestPacketBuffer, InsertMultiplePackets) { TEST_F(TestPacketBuffer, InsertMultiplePackets) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
InsertPacket(seq_num + 1, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + 1, kKeyFrame, kFirst, kLast));
InsertPacket(seq_num + 2, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + 2, kKeyFrame, kFirst, kLast));
InsertPacket(seq_num + 3, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + 3, kKeyFrame, kFirst, kLast));
} }
TEST_F(TestPacketBuffer, InsertDuplicatePacket) { TEST_F(TestPacketBuffer, InsertDuplicatePacket) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
}
TEST_F(TestPacketBuffer, SeqNumWrap) {
EXPECT_TRUE(Insert(0xFFFF, kKeyFrame, kFirst, kLast));
EXPECT_TRUE(Insert(0x0, kKeyFrame, kFirst, kLast));
CheckFrame(0xFFFF);
}
TEST_F(TestPacketBuffer, InsertOldPackets) {
const uint16_t seq_num = Rand();
EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
EXPECT_TRUE(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast));
EXPECT_TRUE(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast));
ASSERT_EQ(2UL, frames_from_callback_.size());
frames_from_callback_.erase(seq_num + 2);
EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
ASSERT_EQ(1UL, frames_from_callback_.size());
frames_from_callback_.erase(frames_from_callback_.find(seq_num));
ASSERT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
EXPECT_TRUE(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast));
packet_buffer_->ClearTo(seq_num + 2);
EXPECT_FALSE(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast));
EXPECT_TRUE(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast));
ASSERT_EQ(2UL, frames_from_callback_.size());
} }
TEST_F(TestPacketBuffer, NackCount) { TEST_F(TestPacketBuffer, NackCount) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
VCMPacket packet; VCMPacket packet;
packet.codec = kVideoCodecGeneric; packet.codec = kVideoCodecGeneric;
@ -129,57 +158,64 @@ TEST_F(TestPacketBuffer, NackCount) {
packet.timesNacked = 1; packet.timesNacked = 1;
packet_buffer_->InsertPacket(packet); packet_buffer_->InsertPacket(packet);
ASSERT_EQ(1UL, frames_from_callback_.size()); ASSERT_EQ(1UL, frames_from_callback_.size());
RtpFrameObject* frame = frames_from_callback_.begin()->second.get(); RtpFrameObject* frame = frames_from_callback_.begin()->second.get();
EXPECT_EQ(3, frame->times_nacked()); EXPECT_EQ(3, frame->times_nacked());
} }
TEST_F(TestPacketBuffer, FrameSize) { TEST_F(TestPacketBuffer, FrameSize) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
uint8_t data[] = {1, 2, 3, 4, 5}; uint8_t data[] = {1, 2, 3, 4, 5};
InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast, 5, data); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast, 5, data));
InsertPacket(seq_num + 1, kKeyFrame, kNotFirst, kNotLast, 5, data); EXPECT_TRUE(Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast, 5, data));
InsertPacket(seq_num + 2, kKeyFrame, kNotFirst, kNotLast, 5, data); EXPECT_TRUE(Insert(seq_num + 2, kKeyFrame, kNotFirst, kNotLast, 5, data));
InsertPacket(seq_num + 3, kKeyFrame, kNotFirst, kLast, 5, data); EXPECT_TRUE(Insert(seq_num + 3, kKeyFrame, kNotFirst, kLast, 5, data));
ASSERT_EQ(1UL, frames_from_callback_.size()); ASSERT_EQ(1UL, frames_from_callback_.size());
EXPECT_EQ(20UL, frames_from_callback_.begin()->second->size()); EXPECT_EQ(20UL, frames_from_callback_.begin()->second->size());
} }
TEST_F(TestPacketBuffer, ExpandBuffer) { TEST_F(TestPacketBuffer, ExpandBuffer) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
for (int i = 0; i < kStartSize + 1; ++i) { for (int i = 0; i < kStartSize + 1; ++i) {
InsertPacket(seq_num + i, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + i, kKeyFrame, kFirst, kLast));
} }
} }
TEST_F(TestPacketBuffer, SingleFrameExpandsBuffer) {
const uint16_t seq_num = Rand();
EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
for (int i = 1; i < kStartSize; ++i)
EXPECT_TRUE(Insert(seq_num + i, kKeyFrame, kNotFirst, kNotLast));
EXPECT_TRUE(Insert(seq_num + kStartSize, kKeyFrame, kNotFirst, kLast));
ASSERT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num);
}
TEST_F(TestPacketBuffer, ExpandBufferOverflow) { TEST_F(TestPacketBuffer, ExpandBufferOverflow) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
for (int i = 0; i < kMaxSize; ++i) { for (int i = 0; i < kMaxSize; ++i)
InsertPacket(seq_num + i, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + i, kKeyFrame, kFirst, kLast));
} EXPECT_FALSE(Insert(seq_num + kMaxSize + 1, kKeyFrame, kFirst, kLast));
VCMPacket packet;
packet.seqNum = seq_num + kMaxSize + 1;
EXPECT_FALSE(packet_buffer_->InsertPacket(packet));
} }
TEST_F(TestPacketBuffer, OnePacketOneFrame) { TEST_F(TestPacketBuffer, OnePacketOneFrame) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
ASSERT_EQ(1UL, frames_from_callback_.size()); ASSERT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
} }
TEST_F(TestPacketBuffer, TwoPacketsTwoFrames) { TEST_F(TestPacketBuffer, TwoPacketsTwoFrames) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
InsertPacket(seq_num + 1, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + 1, kKeyFrame, kFirst, kLast));
EXPECT_EQ(2UL, frames_from_callback_.size()); EXPECT_EQ(2UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
@ -187,75 +223,33 @@ TEST_F(TestPacketBuffer, TwoPacketsTwoFrames) {
} }
TEST_F(TestPacketBuffer, TwoPacketsOneFrames) { TEST_F(TestPacketBuffer, TwoPacketsOneFrames) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
InsertPacket(seq_num + 1, kKeyFrame, kNotFirst, kLast); EXPECT_TRUE(Insert(seq_num + 1, kKeyFrame, kNotFirst, kLast));
EXPECT_EQ(1UL, frames_from_callback_.size()); EXPECT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
} }
TEST_F(TestPacketBuffer, ThreePacketReorderingOneFrame) { TEST_F(TestPacketBuffer, ThreePacketReorderingOneFrame) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
InsertPacket(seq_num + 2, kKeyFrame, kNotFirst, kLast); EXPECT_TRUE(Insert(seq_num + 2, kKeyFrame, kNotFirst, kLast));
InsertPacket(seq_num + 1, kKeyFrame, kNotFirst, kNotLast); EXPECT_TRUE(Insert(seq_num + 1, kKeyFrame, kNotFirst, kNotLast));
EXPECT_EQ(1UL, frames_from_callback_.size()); EXPECT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
} }
TEST_F(TestPacketBuffer, DiscardOldPacket) {
VCMPacket packet;
packet.seqNum = Rand();
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
packet.seqNum += 2;
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
for (int i = 3; i < kMaxSize; ++i) {
++packet.seqNum;
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
}
++packet.seqNum;
EXPECT_FALSE(packet_buffer_->InsertPacket(packet));
packet_buffer_->ClearTo(packet.seqNum + 1);
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
}
TEST_F(TestPacketBuffer, DiscardMultipleOldPackets) {
uint16_t seq_num = Rand();
VCMPacket packet;
packet.seqNum = seq_num;
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
packet.seqNum += 2;
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
for (int i = 3; i < kMaxSize; ++i) {
++packet.seqNum;
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
}
packet_buffer_->ClearTo(seq_num + 15);
for (int i = 0; i < 15; ++i) {
++packet.seqNum;
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
}
for (int i = 15; i < kMaxSize; ++i) {
++packet.seqNum;
EXPECT_FALSE(packet_buffer_->InsertPacket(packet));
}
}
TEST_F(TestPacketBuffer, Frames) { TEST_F(TestPacketBuffer, Frames) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
InsertPacket(seq_num + 1, kDeltaFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + 1, kDeltaFrame, kFirst, kLast));
InsertPacket(seq_num + 2, kDeltaFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast));
InsertPacket(seq_num + 3, kDeltaFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast));
ASSERT_EQ(4UL, frames_from_callback_.size()); ASSERT_EQ(4UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
@ -264,13 +258,45 @@ TEST_F(TestPacketBuffer, Frames) {
CheckFrame(seq_num + 3); CheckFrame(seq_num + 3);
} }
TEST_F(TestPacketBuffer, FramesReordered) { TEST_F(TestPacketBuffer, ClearSinglePacket) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num + 1, kDeltaFrame, kFirst, kLast); for (int i = 0; i < kMaxSize; ++i)
InsertPacket(seq_num, kKeyFrame, kFirst, kLast); EXPECT_TRUE(Insert(seq_num + i, kDeltaFrame, kFirst, kLast));
InsertPacket(seq_num + 3, kDeltaFrame, kFirst, kLast);
InsertPacket(seq_num + 2, kDeltaFrame, kFirst, kLast); packet_buffer_->ClearTo(seq_num);
EXPECT_TRUE(Insert(seq_num + kMaxSize, kDeltaFrame, kFirst, kLast));
}
TEST_F(TestPacketBuffer, OneIncompleteFrame) {
const uint16_t seq_num = Rand();
EXPECT_TRUE(Insert(seq_num, kDeltaFrame, kFirst, kNotLast));
EXPECT_TRUE(Insert(seq_num + 1, kDeltaFrame, kNotFirst, kLast));
EXPECT_TRUE(Insert(seq_num - 1, kDeltaFrame, kNotFirst, kLast));
ASSERT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num);
}
TEST_F(TestPacketBuffer, TwoIncompleteFramesFullBuffer) {
const uint16_t seq_num = Rand();
for (int i = 1; i < kMaxSize - 1; ++i)
EXPECT_TRUE(Insert(seq_num + i, kDeltaFrame, kNotFirst, kNotLast));
EXPECT_TRUE(Insert(seq_num, kDeltaFrame, kFirst, kNotLast));
EXPECT_TRUE(Insert(seq_num - 1, kDeltaFrame, kNotFirst, kLast));
ASSERT_EQ(0UL, frames_from_callback_.size());
}
TEST_F(TestPacketBuffer, FramesReordered) {
const uint16_t seq_num = Rand();
EXPECT_TRUE(Insert(seq_num + 1, kDeltaFrame, kFirst, kLast));
EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
EXPECT_TRUE(Insert(seq_num + 3, kDeltaFrame, kFirst, kLast));
EXPECT_TRUE(Insert(seq_num + 2, kDeltaFrame, kFirst, kLast));
ASSERT_EQ(4UL, frames_from_callback_.size()); ASSERT_EQ(4UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
@ -289,14 +315,15 @@ TEST_F(TestPacketBuffer, GetBitstreamFromFrame) {
uint8_t uint8_t
result[sizeof(many) + sizeof(bitstream) + sizeof(such) + sizeof(data)]; result[sizeof(many) + sizeof(bitstream) + sizeof(such) + sizeof(data)];
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast, sizeof(many), many); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast, sizeof(many), many));
InsertPacket(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast, sizeof(bitstream), EXPECT_TRUE(Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast,
bitstream); sizeof(bitstream), bitstream));
InsertPacket(seq_num + 2, kDeltaFrame, kNotFirst, kNotLast, sizeof(such), EXPECT_TRUE(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kNotLast,
such); sizeof(such), such));
InsertPacket(seq_num + 3, kDeltaFrame, kNotFirst, kLast, sizeof(data), data); EXPECT_TRUE(
Insert(seq_num + 3, kDeltaFrame, kNotFirst, kLast, sizeof(data), data));
ASSERT_EQ(1UL, frames_from_callback_.size()); ASSERT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
@ -305,50 +332,48 @@ TEST_F(TestPacketBuffer, GetBitstreamFromFrame) {
} }
TEST_F(TestPacketBuffer, FreeSlotsOnFrameDestruction) { TEST_F(TestPacketBuffer, FreeSlotsOnFrameDestruction) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
InsertPacket(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast); EXPECT_TRUE(Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast));
InsertPacket(seq_num + 2, kDeltaFrame, kNotFirst, kLast); EXPECT_TRUE(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast));
EXPECT_EQ(1UL, frames_from_callback_.size()); EXPECT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
frames_from_callback_.clear(); frames_from_callback_.clear();
// Insert frame that fills the whole buffer. // Insert frame that fills the whole buffer.
InsertPacket(seq_num + 3, kKeyFrame, kFirst, kNotLast); EXPECT_TRUE(Insert(seq_num + 3, kKeyFrame, kFirst, kNotLast));
for (int i = 0; i < kMaxSize - 2; ++i) for (int i = 0; i < kMaxSize - 2; ++i)
InsertPacket(seq_num + i + 4, kDeltaFrame, kNotFirst, kNotLast); EXPECT_TRUE(Insert(seq_num + i + 4, kDeltaFrame, kNotFirst, kNotLast));
InsertPacket(seq_num + kMaxSize + 2, kKeyFrame, kNotFirst, kLast); EXPECT_TRUE(Insert(seq_num + kMaxSize + 2, kKeyFrame, kNotFirst, kLast));
EXPECT_EQ(1UL, frames_from_callback_.size()); EXPECT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num + 3); CheckFrame(seq_num + 3);
} }
TEST_F(TestPacketBuffer, Clear) { TEST_F(TestPacketBuffer, Clear) {
uint16_t seq_num = Rand(); const uint16_t seq_num = Rand();
InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kNotLast));
InsertPacket(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast); EXPECT_TRUE(Insert(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast));
InsertPacket(seq_num + 2, kDeltaFrame, kNotFirst, kLast); EXPECT_TRUE(Insert(seq_num + 2, kDeltaFrame, kNotFirst, kLast));
EXPECT_EQ(1UL, frames_from_callback_.size()); EXPECT_EQ(1UL, frames_from_callback_.size());
CheckFrame(seq_num); CheckFrame(seq_num);
packet_buffer_->Clear(); packet_buffer_->Clear();
InsertPacket(seq_num + kStartSize, kKeyFrame, kFirst, kNotLast); EXPECT_TRUE(Insert(seq_num + kStartSize, kKeyFrame, kFirst, kNotLast));
InsertPacket(seq_num + kStartSize + 1, kDeltaFrame, kNotFirst, kNotLast); EXPECT_TRUE(
InsertPacket(seq_num + kStartSize + 2, kDeltaFrame, kNotFirst, kLast); Insert(seq_num + kStartSize + 1, kDeltaFrame, kNotFirst, kNotLast));
EXPECT_TRUE(Insert(seq_num + kStartSize + 2, kDeltaFrame, kNotFirst, kLast));
EXPECT_EQ(2UL, frames_from_callback_.size()); EXPECT_EQ(2UL, frames_from_callback_.size());
CheckFrame(seq_num + kStartSize); CheckFrame(seq_num + kStartSize);
} }
TEST_F(TestPacketBuffer, InvalidateFrameByClearing) { TEST_F(TestPacketBuffer, InvalidateFrameByClearing) {
VCMPacket packet; const uint16_t seq_num = Rand();
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = true; EXPECT_TRUE(Insert(seq_num, kKeyFrame, kFirst, kLast));
packet.markerBit = true;
packet.seqNum = Rand();
EXPECT_TRUE(packet_buffer_->InsertPacket(packet));
ASSERT_EQ(1UL, frames_from_callback_.size()); ASSERT_EQ(1UL, frames_from_callback_.size());
packet_buffer_->Clear(); packet_buffer_->Clear();