Ported more jitter buffer tests to unit tests.
BUG= TEST=jitter_buffer_unittest Review URL: http://webrtc-codereview.appspot.com/350009 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1433 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "modules/video_coding/main/source/jitter_buffer.h"
|
||||
#include "modules/video_coding/main/source/media_opt_util.h"
|
||||
@@ -22,57 +24,116 @@ class StreamGenerator {
|
||||
public:
|
||||
StreamGenerator(uint16_t start_seq_num, uint32_t start_timestamp,
|
||||
int64_t current_time)
|
||||
: sequence_number_(start_seq_num),
|
||||
: packets_(),
|
||||
sequence_number_(start_seq_num),
|
||||
timestamp_(start_timestamp),
|
||||
start_time_(current_time),
|
||||
num_packets_(0),
|
||||
type_(kVideoFrameKey),
|
||||
first_packet_(true) {}
|
||||
start_time_(current_time) {}
|
||||
|
||||
void GenerateFrame(FrameType type, int num_packets, int64_t current_time) {
|
||||
void Init(uint16_t start_seq_num, uint32_t start_timestamp,
|
||||
int64_t current_time) {
|
||||
packets_.clear();
|
||||
sequence_number_ = start_seq_num;
|
||||
timestamp_ = start_timestamp;
|
||||
start_time_ = current_time;
|
||||
}
|
||||
|
||||
void GenerateFrame(FrameType type, int num_media_packets,
|
||||
int num_empty_packets, int64_t current_time) {
|
||||
timestamp_ += 90 * (current_time - start_time_);
|
||||
// Move the sequence number counter if all packets from the previous frame
|
||||
// wasn't collected.
|
||||
sequence_number_ += num_packets_;
|
||||
num_packets_ = num_packets;
|
||||
type_ = type;
|
||||
first_packet_ = true;
|
||||
sequence_number_ += packets_.size();
|
||||
packets_.clear();
|
||||
for (int i = 0; i < num_media_packets; ++i) {
|
||||
packets_.push_back(GeneratePacket(sequence_number_,
|
||||
timestamp_,
|
||||
(i == 0),
|
||||
(i == num_media_packets - 1),
|
||||
type));
|
||||
++sequence_number_;
|
||||
}
|
||||
for (int i = 0; i < num_empty_packets; ++i) {
|
||||
packets_.push_back(GeneratePacket(sequence_number_,
|
||||
timestamp_,
|
||||
false,
|
||||
false,
|
||||
kFrameEmpty));
|
||||
++sequence_number_;
|
||||
}
|
||||
}
|
||||
|
||||
bool NextPacket(VCMPacket* packet) {
|
||||
if (num_packets_ == 0) {
|
||||
return false;
|
||||
}
|
||||
--num_packets_;
|
||||
if (packet) {
|
||||
packet->seqNum = sequence_number_;
|
||||
packet->timestamp = timestamp_;
|
||||
packet->frameType = type_;
|
||||
packet->isFirstPacket = first_packet_;
|
||||
packet->markerBit = (num_packets_ == 0);
|
||||
if (packet->isFirstPacket)
|
||||
packet->completeNALU = kNaluStart;
|
||||
else if (packet->markerBit)
|
||||
packet->completeNALU = kNaluEnd;
|
||||
static VCMPacket GeneratePacket(uint16_t sequence_number,
|
||||
uint32_t timestamp,
|
||||
bool first_packet,
|
||||
bool marker_bit,
|
||||
FrameType type) {
|
||||
VCMPacket packet;
|
||||
packet.seqNum = sequence_number;
|
||||
packet.timestamp = timestamp;
|
||||
packet.frameType = type;
|
||||
packet.isFirstPacket = first_packet;
|
||||
packet.markerBit = marker_bit;
|
||||
if (packet.isFirstPacket)
|
||||
packet.completeNALU = kNaluStart;
|
||||
else if (packet.markerBit)
|
||||
packet.completeNALU = kNaluEnd;
|
||||
else
|
||||
packet->completeNALU = kNaluIncomplete;
|
||||
packet.completeNALU = kNaluIncomplete;
|
||||
return packet;
|
||||
}
|
||||
++sequence_number_;
|
||||
first_packet_ = false;
|
||||
|
||||
bool PopPacket(VCMPacket* packet, int index) {
|
||||
std::list<VCMPacket>::iterator it = GetPacketIterator(index);
|
||||
if (it == packets_.end())
|
||||
return false;
|
||||
if (packet)
|
||||
*packet = (*it);
|
||||
packets_.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetPacket(VCMPacket* packet, int index) {
|
||||
std::list<VCMPacket>::iterator it = GetPacketIterator(index);
|
||||
if (it == packets_.end())
|
||||
return false;
|
||||
if (packet)
|
||||
*packet = (*it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NextPacket(VCMPacket* packet) {
|
||||
if (packets_.empty())
|
||||
return false;
|
||||
if (packet != NULL)
|
||||
*packet = packets_.front();
|
||||
packets_.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t NextSequenceNumber() const {
|
||||
if (packets_.empty())
|
||||
return sequence_number_;
|
||||
return packets_.front().seqNum;
|
||||
}
|
||||
|
||||
int PacketsRemaining() const {
|
||||
return num_packets_;
|
||||
return packets_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<VCMPacket>::iterator GetPacketIterator(int index) {
|
||||
std::list<VCMPacket>::iterator it = packets_.begin();
|
||||
for (int i = 0; i < index; ++i) {
|
||||
++it;
|
||||
if (it == packets_.end()) break;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
std::list<VCMPacket> packets_;
|
||||
uint16_t sequence_number_;
|
||||
uint32_t timestamp_;
|
||||
int64_t start_time_;
|
||||
int num_packets_;
|
||||
FrameType type_;
|
||||
bool first_packet_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StreamGenerator);
|
||||
};
|
||||
@@ -99,11 +160,25 @@ class TestRunningJitterBuffer : public ::testing::Test {
|
||||
delete clock_;
|
||||
}
|
||||
|
||||
VCMFrameBufferEnum InsertNextPacket() {
|
||||
VCMFrameBufferEnum InsertPacketAndPop(int index) {
|
||||
VCMPacket packet;
|
||||
packet.dataPtr = data_buffer_;
|
||||
VCMEncodedFrame* frame;
|
||||
bool packet_available = stream_generator->NextPacket(&packet);
|
||||
|
||||
packet.dataPtr = data_buffer_;
|
||||
bool packet_available = stream_generator->PopPacket(&packet, index);
|
||||
EXPECT_TRUE(packet_available);
|
||||
if (!packet_available)
|
||||
return kStateError; // Return here to avoid crashes below.
|
||||
EXPECT_EQ(VCM_OK, jitter_buffer_->GetFrame(packet, frame));
|
||||
return jitter_buffer_->InsertPacket(frame, packet);
|
||||
}
|
||||
|
||||
VCMFrameBufferEnum InsertPacket(int index) {
|
||||
VCMPacket packet;
|
||||
VCMEncodedFrame* frame;
|
||||
|
||||
packet.dataPtr = data_buffer_;
|
||||
bool packet_available = stream_generator->GetPacket(&packet, index);
|
||||
EXPECT_TRUE(packet_available);
|
||||
if (!packet_available)
|
||||
return kStateError; // Return here to avoid crashes below.
|
||||
@@ -112,31 +187,47 @@ class TestRunningJitterBuffer : public ::testing::Test {
|
||||
}
|
||||
|
||||
void InsertFrame(FrameType frame_type) {
|
||||
stream_generator->GenerateFrame(frame_type, 1,
|
||||
stream_generator->GenerateFrame(frame_type,
|
||||
(frame_type != kFrameEmpty) ? 1 : 0,
|
||||
(frame_type == kFrameEmpty) ? 1 : 0,
|
||||
clock_->MillisecondTimestamp());
|
||||
EXPECT_EQ(kFirstPacket, InsertNextPacket());
|
||||
EXPECT_EQ(kFirstPacket, InsertPacketAndPop(0));
|
||||
clock_->IncrementDebugClock(kDefaultFramePeriodMs);
|
||||
}
|
||||
|
||||
void InsertFrames(int num_frames) {
|
||||
void InsertFrames(int num_frames, FrameType frame_type) {
|
||||
for (int i = 0; i < num_frames; ++i) {
|
||||
InsertFrame(kVideoFrameDelta);
|
||||
InsertFrame(frame_type);
|
||||
}
|
||||
}
|
||||
|
||||
void DropFrame(int num_packets) {
|
||||
stream_generator->GenerateFrame(kVideoFrameDelta, num_packets,
|
||||
stream_generator->GenerateFrame(kVideoFrameDelta, num_packets, 0,
|
||||
clock_->MillisecondTimestamp());
|
||||
clock_->IncrementDebugClock(kDefaultFramePeriodMs);
|
||||
}
|
||||
|
||||
bool DecodeCompleteFrame() {
|
||||
VCMEncodedFrame* frame = jitter_buffer_->GetCompleteFrameForDecoding(0);
|
||||
bool ret = (frame != NULL);
|
||||
jitter_buffer_->ReleaseFrame(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DecodeFrame() {
|
||||
VCMEncodedFrame* frame = jitter_buffer_->GetFrameForDecoding();
|
||||
bool ret = (frame != NULL);
|
||||
jitter_buffer_->ReleaseFrame(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
VCMJitterBuffer* jitter_buffer_;
|
||||
StreamGenerator* stream_generator;
|
||||
FakeTickTime* clock_;
|
||||
uint8_t data_buffer_[kDataBufferSize];
|
||||
};
|
||||
|
||||
class TestNack : public TestRunningJitterBuffer {
|
||||
class TestJitterBufferNack : public TestRunningJitterBuffer {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
TestRunningJitterBuffer::SetUp();
|
||||
@@ -148,32 +239,51 @@ class TestNack : public TestRunningJitterBuffer {
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNack, TestJitterBufferFull) {
|
||||
TEST_F(TestRunningJitterBuffer, TestFull) {
|
||||
// Insert a key frame and decode it.
|
||||
InsertFrame(kVideoFrameKey);
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) != NULL);
|
||||
EXPECT_TRUE(DecodeCompleteFrame());
|
||||
DropFrame(1);
|
||||
// Fill the jitter buffer.
|
||||
InsertFrames(kMaxNumberOfFrames);
|
||||
InsertFrames(kMaxNumberOfFrames, kVideoFrameDelta);
|
||||
// Make sure we can't decode these frames.
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) == NULL);
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
// This frame will make the jitter buffer recycle frames until a key frame.
|
||||
// Since none is found it will have to wait until the next key frame before
|
||||
// decoding.
|
||||
InsertFrame(kVideoFrameDelta);
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) == NULL);
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
}
|
||||
|
||||
TEST_F(TestNack, TestNackListFull) {
|
||||
TEST_F(TestRunningJitterBuffer, TestEmptyPackets) {
|
||||
// Make sure a frame can get complete even though empty packets are missing.
|
||||
stream_generator->GenerateFrame(kVideoFrameKey, 3, 3,
|
||||
clock_->MillisecondTimestamp());
|
||||
EXPECT_EQ(kFirstPacket, InsertPacketAndPop(4));
|
||||
EXPECT_EQ(kIncomplete, InsertPacketAndPop(4));
|
||||
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||
EXPECT_EQ(kCompleteSession, InsertPacketAndPop(0));
|
||||
}
|
||||
|
||||
TEST_F(TestJitterBufferNack, TestEmptyPackets) {
|
||||
// Make sure empty packets doesn't clog the jitter buffer.
|
||||
jitter_buffer_->SetNackMode(kNackHybrid, kLowRttNackMs, -1);
|
||||
InsertFrames(kMaxNumberOfFrames, kFrameEmpty);
|
||||
InsertFrame(kVideoFrameKey);
|
||||
EXPECT_TRUE(DecodeCompleteFrame());
|
||||
}
|
||||
|
||||
TEST_F(TestJitterBufferNack, TestNackListFull) {
|
||||
// Insert a key frame and decode it.
|
||||
InsertFrame(kVideoFrameKey);
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) != NULL);
|
||||
EXPECT_TRUE(DecodeCompleteFrame());
|
||||
|
||||
// Generate and drop |kNackHistoryLength| packets to fill the NACK list.
|
||||
DropFrame(kNackHistoryLength);
|
||||
// Insert a frame which should trigger a recycle until the next key frame.
|
||||
InsertFrame(kVideoFrameDelta);
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) == NULL);
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
|
||||
uint16_t nack_list_length = kNackHistoryLength;
|
||||
bool extended;
|
||||
@@ -182,11 +292,11 @@ TEST_F(TestNack, TestNackListFull) {
|
||||
EXPECT_TRUE(nack_list_length == 0xffff && nack_list == NULL);
|
||||
|
||||
InsertFrame(kVideoFrameDelta);
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) == NULL);
|
||||
EXPECT_TRUE(jitter_buffer_->GetFrameForDecoding() == NULL);
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
EXPECT_FALSE(DecodeFrame());
|
||||
}
|
||||
|
||||
TEST_F(TestNack, TestNackBeforeDecode) {
|
||||
TEST_F(TestJitterBufferNack, TestNackBeforeDecode) {
|
||||
DropFrame(10);
|
||||
// Insert a frame and try to generate a NACK list. Shouldn't get one.
|
||||
InsertFrame(kVideoFrameDelta);
|
||||
@@ -195,44 +305,72 @@ TEST_F(TestNack, TestNackBeforeDecode) {
|
||||
uint16_t* list = jitter_buffer_->GetNackList(nack_list_size, extended);
|
||||
// No list generated, and a key frame request is signaled.
|
||||
EXPECT_TRUE(list == NULL);
|
||||
EXPECT_TRUE(nack_list_size == 0xFFFF);
|
||||
EXPECT_EQ(0xFFFF, nack_list_size);
|
||||
}
|
||||
|
||||
TEST_F(TestNack, TestNormalOperation) {
|
||||
TEST_F(TestJitterBufferNack, TestNormalOperation) {
|
||||
EXPECT_EQ(kNackInfinite, jitter_buffer_->GetNackMode());
|
||||
|
||||
InsertFrame(kVideoFrameKey);
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) != NULL);
|
||||
EXPECT_TRUE(DecodeFrame());
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// | 1 | 2 | .. | 8 | 9 | x | 11 | 12 | .. | 19 | x | 21 | .. | 100 |
|
||||
// ----------------------------------------------------------------
|
||||
stream_generator->GenerateFrame(kVideoFrameKey, 100,
|
||||
stream_generator->GenerateFrame(kVideoFrameKey, 100, 0,
|
||||
clock_->MillisecondTimestamp());
|
||||
clock_->IncrementDebugClock(kDefaultFramePeriodMs);
|
||||
EXPECT_EQ(kFirstPacket, InsertNextPacket());
|
||||
EXPECT_EQ(kFirstPacket, InsertPacketAndPop(0));
|
||||
// Verify that the frame is incomplete.
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) == NULL);
|
||||
int i = 2;
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
while (stream_generator->PacketsRemaining() > 1) {
|
||||
if (i % 10 != 0)
|
||||
EXPECT_EQ(kIncomplete, InsertNextPacket());
|
||||
if (stream_generator->NextSequenceNumber() % 10 != 0)
|
||||
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||
else
|
||||
stream_generator->NextPacket(NULL); // Drop packet
|
||||
++i;
|
||||
}
|
||||
EXPECT_EQ(kIncomplete, InsertNextPacket());
|
||||
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||
EXPECT_EQ(0, stream_generator->PacketsRemaining());
|
||||
EXPECT_TRUE(jitter_buffer_->GetCompleteFrameForDecoding(0) == NULL);
|
||||
EXPECT_TRUE(jitter_buffer_->GetFrameForDecoding() == NULL);
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
EXPECT_FALSE(DecodeFrame());
|
||||
uint16_t nack_list_size = 0;
|
||||
bool extended = false;
|
||||
uint16_t* list = jitter_buffer_->GetNackList(nack_list_size, extended);
|
||||
// Verify the NACK list.
|
||||
const int kExpectedNackSize = 9;
|
||||
ASSERT_EQ(kExpectedNackSize, nack_list_size);
|
||||
for (i = 0; i < nack_list_size; ++i)
|
||||
for (int i = 0; i < nack_list_size; ++i)
|
||||
EXPECT_EQ((1 + i) * 10, list[i]);
|
||||
}
|
||||
|
||||
TEST_F(TestJitterBufferNack, TestNormalOperationWrap) {
|
||||
// ------- ------------------------------------------------------------
|
||||
// | 65532 | | 65533 | 65534 | 65535 | x | 1 | .. | 9 | x | 11 |.....| 96 |
|
||||
// ------- ------------------------------------------------------------
|
||||
stream_generator->Init(65532, 0, clock_->MillisecondTimestamp());
|
||||
InsertFrame(kVideoFrameKey);
|
||||
EXPECT_TRUE(DecodeCompleteFrame());
|
||||
stream_generator->GenerateFrame(kVideoFrameDelta, 100, 0,
|
||||
clock_->MillisecondTimestamp());
|
||||
EXPECT_EQ(kFirstPacket, InsertPacketAndPop(0));
|
||||
while (stream_generator->PacketsRemaining() > 1) {
|
||||
if (stream_generator->NextSequenceNumber() % 10 != 0)
|
||||
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||
else
|
||||
stream_generator->NextPacket(NULL); // Drop packet
|
||||
}
|
||||
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||
EXPECT_EQ(0, stream_generator->PacketsRemaining());
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
EXPECT_FALSE(DecodeCompleteFrame());
|
||||
uint16_t nack_list_size = 0;
|
||||
bool extended = false;
|
||||
uint16_t* list = jitter_buffer_->GetNackList(nack_list_size, extended);
|
||||
// Verify the NACK list.
|
||||
const int kExpectedNackSize = 10;
|
||||
ASSERT_EQ(kExpectedNackSize, nack_list_size);
|
||||
for (int i = 0; i < nack_list_size; ++i)
|
||||
EXPECT_EQ(i * 10, list[i]);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@@ -1292,6 +1292,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
// check the frame type
|
||||
TEST(frameOut->FrameType() == kVideoFrameDelta);
|
||||
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
seqNum--;
|
||||
timeStamp = 2000;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
@@ -1344,6 +1346,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
// check the frame type
|
||||
TEST(frameOut->FrameType() == kVideoFrameDelta);
|
||||
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
seqNum--;
|
||||
timeStamp = 0xffffff00;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
@@ -1407,6 +1411,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
TEST(CheckOutFrame(frameOut, size*2, false) == 0);
|
||||
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
seqNum++;
|
||||
timeStamp += 33*90;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
@@ -1607,230 +1613,6 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
//printf("DONE insert 2 frames (1 packet) re-ordered with wrap in timestamp\n");
|
||||
|
||||
//
|
||||
// TEST NACK
|
||||
//
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// | 3 | 4 | 5 | 6 | 7 | 9 | x | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | x | 21 |.....| 102 |
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
jb.SetNackMode(kNackInfinite, -1, -1);
|
||||
|
||||
TEST(jb.GetNackMode() == kNackInfinite);
|
||||
|
||||
// insert first packet
|
||||
timeStamp += 33*90;
|
||||
seqNum += 2;
|
||||
packet.frameType = kVideoFrameKey;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert a packet into a frame
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// get packet notification
|
||||
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
|
||||
|
||||
// check incoming frame type
|
||||
TEST(incomingFrameType == kVideoFrameKey);
|
||||
|
||||
// get the frame
|
||||
frameOut = jb.GetCompleteFrameForDecoding(10);
|
||||
|
||||
// it should not be complete
|
||||
TEST(frameOut == 0);
|
||||
|
||||
// insert 98 packets
|
||||
loop = 0;
|
||||
do
|
||||
{
|
||||
seqNum++;
|
||||
if(seqNum % 10 != 0)
|
||||
{
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert a packet into a frame
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
}
|
||||
loop++;
|
||||
} while (loop < 98);
|
||||
|
||||
// insert last packet
|
||||
seqNum++;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = true;
|
||||
packet.seqNum = seqNum;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert a packet into a frame
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// try to get the frame, should fail
|
||||
frameOut = jb.GetCompleteFrameForDecoding(10);
|
||||
TEST(frameOut == 0);
|
||||
|
||||
// try to get the frame, should fail
|
||||
frameOut = jb.GetFrameForDecoding();
|
||||
TEST(frameOut == 0);
|
||||
|
||||
WebRtc_UWord16 nackSize = 0;
|
||||
bool extended = false;
|
||||
WebRtc_UWord16* list = jb.GetNackList(nackSize, extended);
|
||||
|
||||
TEST(nackSize == 10);
|
||||
|
||||
for(int i = 0; i < nackSize; i++)
|
||||
{
|
||||
TEST(list[i] == (1+i)*10);
|
||||
}
|
||||
|
||||
jb.Stop();
|
||||
|
||||
//printf("DONE NACK\n");
|
||||
|
||||
//
|
||||
// TEST NACK with wrap in seqNum
|
||||
//
|
||||
// ------- -----------------------------------------------------------------------------------
|
||||
// | 65532 | | 65533 | 65534 | 65535 | x | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | x | 11 |.....| 96 |
|
||||
// ------- -----------------------------------------------------------------------------------
|
||||
|
||||
jb.Flush();
|
||||
jb.Start();
|
||||
|
||||
// insert first frame
|
||||
timeStamp = 33*90;
|
||||
seqNum = 65532;
|
||||
packet.frameType = kVideoFrameKey;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = true;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert a packet into a frame
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// get packet notification
|
||||
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
|
||||
|
||||
// check incoming frame type
|
||||
TEST(incomingFrameType == kVideoFrameKey);
|
||||
|
||||
// get the frame
|
||||
frameOut = jb.GetCompleteFrameForDecoding(10);
|
||||
|
||||
TEST(CheckOutFrame(frameOut, size, false) == 0);
|
||||
|
||||
// check the frame type
|
||||
TEST(frameOut->FrameType() == kVideoFrameKey);
|
||||
|
||||
// Release frame (when done with decoding)
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
|
||||
// insert first packet
|
||||
timeStamp += 33*90;
|
||||
seqNum++;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert a packet into a frame
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// get packet notification
|
||||
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
|
||||
|
||||
// check incoming frame type
|
||||
TEST(incomingFrameType == kVideoFrameDelta);
|
||||
|
||||
// get the frame
|
||||
frameOut = jb.GetCompleteFrameForDecoding(10);
|
||||
|
||||
// it should not be complete
|
||||
TEST(frameOut == 0);
|
||||
|
||||
// insert 98 packets
|
||||
loop = 0;
|
||||
do
|
||||
{
|
||||
seqNum++;
|
||||
if (seqNum % 10 != 0)
|
||||
{
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert a packet into a frame
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// try to get the frame, should fail
|
||||
frameOut = jb.GetCompleteFrameForDecoding(1);
|
||||
TEST(frameOut == 0);
|
||||
|
||||
// try to get the frame, should fail
|
||||
frameOut = jb.GetFrameForDecoding();
|
||||
TEST(frameOut == 0);
|
||||
}
|
||||
loop++;
|
||||
} while (loop < 98);
|
||||
|
||||
// insert last packet
|
||||
seqNum++;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = true;
|
||||
packet.seqNum = seqNum;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert a packet into a frame
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// try to get the frame, should fail
|
||||
frameOut = jb.GetCompleteFrameForDecoding(10);
|
||||
TEST(frameOut == 0);
|
||||
|
||||
// try to get the frame, should fail
|
||||
frameOut = jb.GetFrameForDecoding();
|
||||
TEST(frameOut == 0);
|
||||
|
||||
nackSize = 0;
|
||||
list = jb.GetNackList(nackSize, extended);
|
||||
|
||||
TEST(nackSize == 10);
|
||||
|
||||
for(int i = 0; i < nackSize; i++)
|
||||
{
|
||||
TEST(list[i] == i*10);
|
||||
}
|
||||
|
||||
jb.Stop();
|
||||
|
||||
//printf("DONE NACK with wrap in seqNum\n");
|
||||
|
||||
//
|
||||
// TEST delta frame with more than max number of packets
|
||||
//
|
||||
@@ -1889,52 +1671,6 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
//printf("DONE fill frame - packets > max number of packets\n");
|
||||
|
||||
//
|
||||
// TEST fill JB with more than max number of delta frame
|
||||
//
|
||||
|
||||
loop = 0;
|
||||
WebRtc_UWord32 timeStampStart = timeStamp + 33*90;
|
||||
// insert MAX_NUMBER_OF_FRAMES frames
|
||||
do
|
||||
{
|
||||
timeStamp += 33*90;
|
||||
seqNum++;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = true;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
// Insert frame
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// get packet notification
|
||||
TEST(timeStampStart == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
|
||||
|
||||
// check incoming frame type
|
||||
TEST(incomingFrameType == kVideoFrameDelta);
|
||||
|
||||
loop++;
|
||||
} while (loop < kMaxNumberOfFrames);
|
||||
|
||||
// Max number of frames inserted
|
||||
|
||||
// Insert one more frame
|
||||
timeStamp += 33*90;
|
||||
seqNum++;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = true;
|
||||
packet.seqNum = seqNum;
|
||||
|
||||
// Now, no free frame - frames will be recycled until first key frame
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn); // no key, so we have recycled all frames
|
||||
|
||||
//printf("DONE fill JB - number of delta frames > max number of frames\n");
|
||||
|
||||
//
|
||||
// TEST fill JB with more than max number of frame (50 delta frames +
|
||||
// 51 key frames) with wrap in seqNum
|
||||
@@ -1948,7 +1684,7 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
loop = 0;
|
||||
seqNum = 65485;
|
||||
timeStampStart = timeStamp + 33*90;
|
||||
WebRtc_UWord32 timeStampStart = timeStamp + 33*90;
|
||||
WebRtc_UWord32 timeStampFirstKey = 0;
|
||||
VCMEncodedFrame* ptrLastDeltaFrame = NULL;
|
||||
VCMEncodedFrame* ptrFirstKeyFrame = NULL;
|
||||
@@ -2031,93 +1767,11 @@ int JitterBufferTest(CmdArgs& args)
|
||||
// printf("DONE fill JB - nr of delta + key frames (w/ wrap in seqNum) >
|
||||
// max nr of frames\n");
|
||||
|
||||
// Test handling empty packets
|
||||
// first insert 2 empty packets
|
||||
jb.ReleaseFrame(frameIn);
|
||||
timeStamp = 33 * 90;
|
||||
seqNum = 5;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn);
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
seqNum = 6;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
// now insert the first data packet
|
||||
seqNum = 1;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
// insert an additional data packet
|
||||
seqNum = 2;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// insert the last packet and verify frame completness
|
||||
// (even though packet 4 (empty) is missing)
|
||||
seqNum = 3;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = true;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
|
||||
jb.Flush();
|
||||
|
||||
// testing that empty packets do not clog the jitter buffer
|
||||
// Set hybrid mode
|
||||
jb.SetNackMode(kNackHybrid, kLowRttNackMs, -1);
|
||||
TEST(jb.GetNackMode() == kNackHybrid);
|
||||
|
||||
int maxSize = 100;
|
||||
seqNum = 3;
|
||||
VCMEncodedFrame* testFrame;
|
||||
for (int i = 0; i < maxSize + 10; i++)
|
||||
{
|
||||
timeStamp += 33 * 90;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
testFrame = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
TEST(kFirstPacket == jb.InsertPacket(testFrame, packet));
|
||||
}
|
||||
// verify insertion of a data packet (old empty frames will be flushed)
|
||||
timeStamp += 33 * 90;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
testFrame = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
jb.SetNackMode(kNoNack, -1, -1);
|
||||
jb.Flush();
|
||||
|
||||
// Testing that 1 empty packet inserted last will not be set for decoding
|
||||
seqNum = 3;
|
||||
// Insert one empty packet per frame, should never return the last timestamp
|
||||
// inserted. Only return empty frames in the presence of subsequent frames.
|
||||
maxSize = 1000;
|
||||
int maxSize = 1000;
|
||||
for (int i = 0; i < maxSize + 10; i++)
|
||||
{
|
||||
timeStamp += 33 * 90;
|
||||
@@ -2127,7 +1781,7 @@ int JitterBufferTest(CmdArgs& args)
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
testFrame = jb.GetFrameForDecoding();
|
||||
VCMEncodedFrame* testFrame = jb.GetFrameForDecoding();
|
||||
// timestamp should bever be the last TS inserted
|
||||
if (testFrame != NULL)
|
||||
{
|
||||
@@ -2325,6 +1979,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
// Only last NALU is complete
|
||||
TEST(CheckOutFrame(frameOut, packet.sizeBytes, false) == 0);
|
||||
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
jb.Flush();
|
||||
|
||||
// Three reordered H263 packets with bits.
|
||||
@@ -2366,6 +2022,7 @@ int JitterBufferTest(CmdArgs& args)
|
||||
TEST(frameOut != NULL);
|
||||
const WebRtc_UWord8* buf = frameOut->Buffer();
|
||||
TEST(buf[packet.sizeBytes - 1] == (startByte | endByte));
|
||||
jb.ReleaseFrame(frameOut);
|
||||
// First packet lost, second packet with bits.
|
||||
|
||||
// The JB only outputs frame if the next one arrives:
|
||||
@@ -2392,6 +2049,7 @@ int JitterBufferTest(CmdArgs& args)
|
||||
frameOut = jb.GetFrameForDecoding();
|
||||
TEST(frameOut != NULL);
|
||||
TEST(frameOut->Length() == 0);
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
data[0] = oldData1;
|
||||
data[packet.sizeBytes - 1] = oldData2;
|
||||
@@ -2425,6 +2083,7 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
TEST(frameOut != NULL);
|
||||
TEST(CheckOutFrame(frameOut, packet.sizeBytes, false) == 0);
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
jb.Stop();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user