From 273759048c80fa411812c19a6754b79536e01732 Mon Sep 17 00:00:00 2001 From: "stefan@webrtc.org" Date: Mon, 6 May 2013 13:12:58 +0000 Subject: [PATCH] Revert r3956 "VCM/JB: Porting jitter_buffer_test to gtest." TBR=phoglund@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1408005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3962 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../main/source/jitter_buffer_unittest.cc | 1259 ------------ .../main/test/jitter_buffer_test.cc | 1755 +++++++++++++++++ 2 files changed, 1755 insertions(+), 1259 deletions(-) create mode 100644 webrtc/modules/video_coding/main/test/jitter_buffer_test.cc diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc index 3c377cf8d..cac7a22f1 100644 --- a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc +++ b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc @@ -13,7 +13,6 @@ #include #include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/video_coding/main/source/frame_buffer.h" #include "webrtc/modules/video_coding/main/source/jitter_buffer.h" #include "webrtc/modules/video_coding/main/source/media_opt_util.h" #include "webrtc/modules/video_coding/main/source/packet.h" @@ -23,101 +22,6 @@ namespace webrtc { -class TestBasicJitterBuffer : public ::testing::Test { - protected: - virtual void SetUp() { - clock_.reset(new SimulatedClock(0)); - jitter_buffer_.reset(new VCMJitterBuffer(clock_.get(), - &event_factory_, -1, -1, true)); - jitter_buffer_->Start(); - seq_num_ = 1234; - timestamp_ = 0; - size_ = 1400; - // Data vector - 0, 0, 0x80, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0x80, 3.... - data_[0] = 0; - data_[1] = 0; - data_[2] = 0x80; - int count = 3; - for (unsigned int i = 3; i < sizeof(data_) - 3; ++i) { - data_[i] = count; - count++; - if (count == 10) { - data_[i + 1] = 0; - data_[i + 2] = 0; - data_[i + 3] = 0x80; - count = 3; - i += 3; - } - } - packet_.reset(new VCMPacket(data_, size_, seq_num_, timestamp_, true)); - } - - VCMEncodedFrame* DecodeCompleteFrame() { - uint32_t timestamp = 0; - bool found_frame = jitter_buffer_->NextCompleteTimestamp(10, ×tamp); - if (!found_frame) - return NULL; - VCMEncodedFrame* frame = jitter_buffer_->ExtractAndSetDecode(timestamp); - return frame; - } - - VCMEncodedFrame* DecodeIncompleteFrame() { - uint32_t timestamp = 0; - bool found_frame = jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp); - if (!found_frame) - return NULL; - VCMEncodedFrame* frame = jitter_buffer_->ExtractAndSetDecode(timestamp); - return frame; - } - int CheckOutFrame(VCMEncodedFrame* frame_out, - unsigned int size, - bool startCode) { - EXPECT_FALSE(frame_out == NULL); - - const uint8_t* outData = frame_out->Buffer(); - unsigned int i = 0; - - if (startCode) { - EXPECT_EQ(0, outData[0]); - EXPECT_EQ(0, outData[1]); - EXPECT_EQ(0, outData[2]); - EXPECT_EQ(1, outData[3]); - i += 4; - } - - EXPECT_EQ(size, frame_out->Length()); - int count = 3; - for (; i < size; i++) { - if (outData[i] == 0 && outData[i + 1] == 0 && outData[i + 2] == 0x80) { - i += 2; - } else if (startCode && outData[i] == 0 && outData[i + 1] == 0) { - EXPECT_EQ(0, outData[0]); - EXPECT_EQ(0, outData[1]); - EXPECT_EQ(0, outData[2]); - EXPECT_EQ(1, outData[3]); - i += 3; - } else { - EXPECT_EQ(count, outData[i]); - count++; - if (count == 10) { - count = 3; - } - } - } - return 0; - } - - uint16_t seq_num_; - uint32_t timestamp_; - int size_; - uint8_t data_[1500]; - scoped_ptr jitter_buffer_; - scoped_ptr packet_; - scoped_ptr clock_; - NullEventFactory event_factory_; -}; - - class TestRunningJitterBuffer : public ::testing::Test { protected: enum { kDataBufferSize = 10 }; @@ -240,1169 +144,6 @@ class TestJitterBufferNack : public TestRunningJitterBuffer { } }; -TEST_F(TestBasicJitterBuffer, StopRunning) { - jitter_buffer_->Stop(); - EXPECT_EQ(0, jitter_buffer_->GetFrame(*packet_)); - EXPECT_TRUE(NULL == DecodeCompleteFrame()); - EXPECT_TRUE(NULL == DecodeIncompleteFrame()); - jitter_buffer_->Start(); - // Allow decoding with errors. - jitter_buffer_->DecodeWithErrors(true); - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - // No packets inserted. - EXPECT_TRUE(NULL == DecodeCompleteFrame()); - EXPECT_TRUE(NULL == DecodeIncompleteFrame()); -} - -TEST_F(TestBasicJitterBuffer, SinglePacketFrame) { - // Always start with a complete key frame. - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->timestamp += 123*90; - - // Insert the packet to the jitter buffer and get a frame. - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - EXPECT_EQ(0, CheckOutFrame(frame_out, size_, false)); - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, DualPacketFrame) { - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - // Should not be complete. - EXPECT_TRUE(frame_out == NULL); - - ++seq_num_; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_FALSE(frame_in == NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - EXPECT_EQ(0, CheckOutFrame(frame_out, 2 * size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, 100PacketKeyFrame) { - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - // Frame should not be complete. - EXPECT_TRUE(frame_out == NULL); - - // Insert 98 frames. - int loop = 0; - do { - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_FALSE(frame_in == NULL); - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - loop++; - } while (loop < 98); - - // Insert last packet. - ++seq_num_; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_FALSE(frame_in == NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 100 * size_, false)); - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, 100PacketDeltaFrame) { - // Always start with a complete key frame. - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = true; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - EXPECT_FALSE(frame_out == NULL); - - ++seq_num_; - packet_->seqNum = seq_num_; - packet_->markerBit = false; - packet_->frameType = kVideoFrameDelta; - packet_->timestamp += 33 * 90; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_FALSE(frame_in == NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - // Frame should not be complete. - EXPECT_TRUE(frame_out == NULL); - - packet_->isFirstPacket = false; - // Insert 98 frames. - int loop = 0; - do { - ++seq_num_; - packet_->seqNum = seq_num_; - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_FALSE(frame_in == NULL); - // Insert a packet into a frame. - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - loop++; - } while (loop < 98); - - // Insert the last packet. - ++seq_num_; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_FALSE(frame_in == NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 100 * size_, false)); - EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, PacketReorderingReverseOrder) { - // Insert the "first" packet last. - seq_num_ += 100; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - // Insert 98 packets. - int loop = 0; - do { - seq_num_--; - packet_->isFirstPacket = false; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - loop++; - } while (loop < 98); - - // Insert the last packet. - seq_num_--; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame();; - - EXPECT_EQ(0, CheckOutFrame(frame_out, 100 * size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, FrameReordering2Frames2PacketsEach) { - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = true; - packet_->markerBit = false; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - // check that we fail to get frame since seqnum is not continuous - frame_out = DecodeCompleteFrame(); - EXPECT_TRUE(frame_out == NULL); - - seq_num_ -= 3; - timestamp_ -= 33*90; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - // It should not be complete. - EXPECT_TRUE(frame_out == NULL); - - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 2 * size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); - - jitter_buffer_->ReleaseFrame(frame_out); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 2 * size_, false)); - - EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, DuplicatePackets) { - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - packet_->isFirstPacket = false; - packet_->markerBit = true; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - // Insert a packet into a frame. - EXPECT_EQ(kDuplicatePacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - seq_num_++; - packet_->seqNum = seq_num_; - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 2 * size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, H264InsertStartCode) { - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->insertStartCode = true; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - // Frame should not be complete. - EXPECT_TRUE(frame_out == NULL); - - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, size_ * 2 + 4 * 2, true)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, PacketLoss) { - // Verify missing packets statistics and not decodable packets statistics. - // Insert 10 frames consisting of 4 packets and remove one from all of them. - // The last packet is an empty (non-media) packet. - - // Select a start seqNum which triggers a difficult wrap situation - // The JB will only output (incomplete)frames if the next one has started - // to arrive. Start by inserting one frame (key). - jitter_buffer_->DecodeWithErrors(true); - seq_num_ = 0xffff - 4; - seq_num_++; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->completeNALU = kNaluStart; - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - for (int i = 0; i < 11; ++i) { - webrtc::FrameType frametype = kVideoFrameDelta; - seq_num_++; - timestamp_ += 33*90; - packet_->frameType = frametype; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->completeNALU = kNaluStart; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - // Should not be complete. - EXPECT_TRUE(frame_out == NULL); - - seq_num_ += 2; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->completeNALU = kNaluEnd; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - - // Insert an empty (non-media) packet. - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->completeNALU = kNaluEnd; - packet_->frameType = kFrameEmpty; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeIncompleteFrame(); - - // One of the packets has been discarded by the jitter buffer. - // Last frame can't be extracted yet. - if (i < 10) { - EXPECT_EQ(0, CheckOutFrame(frame_out, size_, false)); - - if (i == 0) { - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); - } else { - EXPECT_EQ(frametype, frame_out->FrameType()); - } - EXPECT_FALSE(frame_out->Complete()); - EXPECT_FALSE(frame_out->MissingFrame()); - } - - jitter_buffer_->ReleaseFrame(frame_out); - } - - EXPECT_EQ(10, jitter_buffer_->num_not_decodable_packets()); - - // Insert 3 old packets and verify that we have 3 discarded packets - // Match value to actual latest timestamp decoded. - timestamp_ -= 33 * 90; - packet_->timestamp = timestamp_ - 1000; - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in == NULL); - - packet_->timestamp = timestamp_ - 500; - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in == NULL); - - packet_->timestamp = timestamp_ - 100; - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in == NULL); - - EXPECT_EQ(3, jitter_buffer_->num_discarded_packets()); - - jitter_buffer_->Flush(); - - // This statistic shouldn't be reset by a flush. - EXPECT_EQ(3, jitter_buffer_->num_discarded_packets()); -} - -TEST_F(TestBasicJitterBuffer, DeltaFrame100PacketsWithSeqNumWrap) { - seq_num_ = 0xfff0; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - int loop = 0; - do { - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - loop++; - } while (loop < 98); - - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 100 * size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, PacketReorderingReverseWithNegSeqNumWrap) { - // Insert "first" packet last seqnum. - seq_num_ = 10; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - // Should not be complete. - EXPECT_TRUE(frame_out == NULL); - - // Insert 98 frames. - int loop = 0; - do { - seq_num_--; - packet_->isFirstPacket = false; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - loop++; - } while (loop < 98); - - // Insert last packet. - seq_num_--; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - EXPECT_EQ(0, CheckOutFrame(frame_out, 100 * size_, false)); - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, TestInsertOldFrame) { - // ------- ------- - // | 2 | | 1 | - // ------- ------- - // t = 3000 t = 2000 - seq_num_ = 2; - timestamp_ = 3000; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->timestamp = timestamp_; - packet_->seqNum = seq_num_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - EXPECT_EQ(3000u, frame_out->TimeStamp()); - - EXPECT_EQ(0, CheckOutFrame(frame_out, size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); - - jitter_buffer_->ReleaseFrame(frame_out); - - seq_num_--; - timestamp_ = 2000; - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - // Changed behavior, never insert packets into frames older than the - // last decoded frame. - EXPECT_TRUE(frame_in == NULL); -} - -TEST_F(TestBasicJitterBuffer, TestInsertOldFrameWithSeqNumWrap) { - // ------- ------- - // | 2 | | 1 | - // ------- ------- - // t = 3000 t = 0xffffff00 - - seq_num_ = 2; - timestamp_ = 3000; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - EXPECT_EQ(timestamp_, frame_out->TimeStamp()); - - EXPECT_EQ(0, CheckOutFrame(frame_out, size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); - - jitter_buffer_->ReleaseFrame(frame_out); - - seq_num_--; - timestamp_ = 0xffffff00; - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - // This timestamp is old. - EXPECT_TRUE(frame_in == NULL); -} - -TEST_F(TestBasicJitterBuffer, TimestampWrap) { - // --------------- --------------- - // | 1 | 2 | | 3 | 4 | - // --------------- --------------- - // t = 0xffffff00 t = 33*90 - - timestamp_ = 0xffffff00; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 2 * size_, false)); - - jitter_buffer_->ReleaseFrame(frame_out); - - seq_num_++; - timestamp_ += 33*90; - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = true; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_TRUE(frame_out == NULL); - - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeCompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, 2 * size_, false)); - - EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, 2FrameWithTimestampWrap) { - // ------- ------- - // | 1 | | 2 | - // ------- ------- - // t = 0xffffff00 t = 2700 - - timestamp_ = 0xffffff00; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->timestamp = timestamp_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - // Insert first frame (session will be complete). - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - // Insert next frame. - seq_num_++; - timestamp_ = 2700; - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - EXPECT_EQ(0xffffff00, frame_out->TimeStamp()); - - EXPECT_EQ(0, CheckOutFrame(frame_out, size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); - - VCMEncodedFrame* frame_out2 = DecodeCompleteFrame(); - EXPECT_EQ(2700u, frame_out2->TimeStamp()); - - EXPECT_EQ(0, CheckOutFrame(frame_out2, size_, false)); - - EXPECT_EQ(kVideoFrameDelta, frame_out2->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, Insert2FramesReOrderedWithTimestampWrap) { - // ------- ------- - // | 2 | | 1 | - // ------- ------- - // t = 2700 t = 0xffffff00 - - seq_num_ = 2; - timestamp_ = 2700; - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - // Insert second frame - seq_num_--; - timestamp_ = 0xffffff00; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - EXPECT_EQ(0xffffff00, frame_out->TimeStamp()); - - EXPECT_EQ(0, CheckOutFrame(frame_out, size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); - - VCMEncodedFrame* frame_out2 = DecodeCompleteFrame(); - EXPECT_EQ(2700u, frame_out2->TimeStamp()); - - EXPECT_EQ(0, CheckOutFrame(frame_out2, size_, false)); - - EXPECT_EQ(kVideoFrameDelta, frame_out2->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, DeltaFrameWithMoreThanMaxNumberOfPackets) { - int loop = 0; - bool firstPacket = true; - VCMEncodedFrame* frame_in; - // Insert kMaxPacketsInJitterBuffer into frame. - do { - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - if (firstPacket) { - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - firstPacket = false; - } else { - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - } - - loop++; - } while (loop < kMaxPacketsInSession); - - // Max number of packets inserted. - // Insert one more packet. - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - // Insert the packet -> frame recycled. - EXPECT_EQ(kSizeError, jitter_buffer_->InsertPacket(frame_in, *packet_)); - EXPECT_TRUE(NULL == DecodeCompleteFrame()); - -} - -TEST_F(TestBasicJitterBuffer, ExceedNumOfFrameWithSeqNumWrap) { - // TEST fill JB with more than max number of frame (50 delta frames + - // 51 key frames) with wrap in seq_num_ - // - // -------------------------------------------------------------- - // | 65485 | 65486 | 65487 | .... | 65535 | 0 | 1 | 2 | .....| 50 | - // -------------------------------------------------------------- - // |<-----------delta frames------------->|<------key frames----->| - - int loop = 0; - seq_num_ = 65485; - VCMEncodedFrame* ptrLastDeltaFrame = NULL; - VCMEncodedFrame* ptrFirstKeyFrame = NULL; - VCMEncodedFrame* frame_in; - // Insert MAX_NUMBER_OF_FRAMES frames. - do { - timestamp_ += 33*90; - seq_num_++; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_TRUE(frame_in != NULL); - - if (loop == 49) { // last delta - ptrLastDeltaFrame = frame_in; - } - if (loop == 50) { // first key - ptrFirstKeyFrame = frame_in; - packet_->frameType = kVideoFrameKey; - } - - // Insert frame. - EXPECT_EQ(kCompleteSession, - jitter_buffer_->InsertPacket(frame_in, *packet_)); - - loop++; - } while (loop < kMaxNumberOfFrames); - - // Max number of frames inserted. - - // Insert one more frame. - timestamp_ += 33*90; - seq_num_++; - packet_->isFirstPacket = true; - packet_->markerBit = true; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - - // Now, no free frame - frames will be recycled until first key frame. - frame_in = jitter_buffer_->GetFrame(*packet_); - // Pointer to last inserted delta frame should be returned. - EXPECT_TRUE(frame_in != NULL && frame_in && ptrLastDeltaFrame); - - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeCompleteFrame();; - EXPECT_EQ(ptrFirstKeyFrame, frame_out); - - EXPECT_EQ(0, CheckOutFrame(frame_out, size_, false)); - - EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); -} - -TEST_F(TestBasicJitterBuffer, EmptyLastFrame) { - jitter_buffer_->DecodeWithErrors(true); - seq_num_ = 3; - // Insert one empty packet per frame, should never return the last timestamp - // inserted. Only return empty frames in the presence of subsequent frames. - int maxSize = 1000; - for (int i = 0; i < maxSize + 10; i++) { - timestamp_ += 33 * 90; - seq_num_++; - packet_->isFirstPacket = false; - packet_->markerBit = false; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kFrameEmpty; - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - VCMEncodedFrame* testFrame = DecodeIncompleteFrame(); - // Timestamp should never be the last TS inserted. - if (testFrame != NULL) { - EXPECT_TRUE(testFrame->TimeStamp() < timestamp_); - } - } -} - -TEST_F(TestBasicJitterBuffer, H264IncompleteNalu) { - jitter_buffer_->SetNackMode(kNoNack, -1, -1); - jitter_buffer_->DecodeWithErrors(true); - seq_num_ ++; - timestamp_ += 33 * 90; - int insertedLength = 0; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->completeNALU = kNaluStart; - packet_->markerBit = false; - - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - seq_num_ += 2; // Skip one packet - packet_->seqNum = seq_num_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->completeNALU = kNaluIncomplete; - packet_->markerBit = false; - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - seq_num_++; - packet_->seqNum = seq_num_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->completeNALU = kNaluEnd; - packet_->markerBit = false; - - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - seq_num_++; - packet_->seqNum = seq_num_; - packet_->completeNALU = kNaluComplete; - packet_->markerBit = true; // Last packet - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - // The JB will only output (incomplete) frames if a packet belonging to a - // subsequent frame was already inserted. Insert one packet of a subsequent - // frame. place high timestamp so the JB would always have a next frame - // (otherwise, for every inserted frame we need to take care of the next - // frame as well). - packet_->seqNum = 1; - packet_->timestamp = timestamp_ + 33 * 90 * 10; - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = false; - packet_->completeNALU = kNaluStart; - packet_->markerBit = false; - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - VCMEncodedFrame* frame_out = DecodeIncompleteFrame(); - - // We can decode everything from a NALU until a packet has been lost. - // Thus we can decode the first packet of the first NALU and the second NALU - // which consists of one packet. - EXPECT_EQ(0, CheckOutFrame(frame_out, packet_->sizeBytes * 2, false)); - jitter_buffer_->ReleaseFrame(frame_out); - - // Test reordered start frame + 1 lost. - seq_num_ += 2; // Re-order 1 frame. - timestamp_ += 33*90; - insertedLength = 0; - - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->completeNALU = kNaluEnd; - packet_->markerBit = false; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - insertedLength += packet_->sizeBytes; // This packet should be decoded. - - seq_num_--; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->completeNALU = kNaluStart; - packet_->markerBit = false; - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - insertedLength += packet_->sizeBytes; // This packet should be decoded. - - seq_num_ += 3; // One packet drop - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->completeNALU = kNaluComplete; - packet_->markerBit = false; - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - insertedLength += packet_->sizeBytes; // This packet should be decoded. - - seq_num_ += 1; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->completeNALU = kNaluStart; - packet_->markerBit = false; - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - // This packet should be decoded since it's the beginning of a NAL. - insertedLength += packet_->sizeBytes; - - seq_num_ += 2; - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = false; - packet_->completeNALU = kNaluEnd; - packet_->markerBit = true; - EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(frame_in, *packet_)); - // This packet should not be decoded because it is an incomplete NAL if it - // is the last. - frame_out = DecodeIncompleteFrame(); - // Only last NALU is complete. - EXPECT_EQ(0, CheckOutFrame(frame_out, insertedLength, false)); - jitter_buffer_->ReleaseFrame(frame_out); - - - // Test to insert empty packet. - seq_num_ += 1; - timestamp_ += 33 * 90; - VCMPacket emptypacket(data_, 0, seq_num_, timestamp_, true); - emptypacket.seqNum = seq_num_; - emptypacket.timestamp = timestamp_; - emptypacket.frameType = kVideoFrameKey; - emptypacket.isFirstPacket = true; - emptypacket.completeNALU = kNaluComplete; - emptypacket.markerBit = true; - frame_in = jitter_buffer_->GetFrame(emptypacket); - EXPECT_EQ(kCompleteSession, - jitter_buffer_->InsertPacket(frame_in, emptypacket)); - // This packet should not be decoded because it is an incomplete NAL if it - // is the last. - insertedLength += 0; - - // Will be sent to the decoder, as a packet belonging to a subsequent frame - // has arrived. - frame_out = DecodeIncompleteFrame(); - - - // Test that a frame can include an empty packet. - seq_num_ += 1; - timestamp_ += 33 * 90; - - packet_->seqNum = seq_num_; - packet_->timestamp = timestamp_; - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->completeNALU = kNaluComplete; - packet_->markerBit = false; - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - seq_num_ += 1; - emptypacket.seqNum = seq_num_; - emptypacket.timestamp = timestamp_; - emptypacket.frameType = kVideoFrameKey; - emptypacket.isFirstPacket = true; - emptypacket.completeNALU = kNaluComplete; - emptypacket.markerBit = true; - EXPECT_EQ(kCompleteSession, - jitter_buffer_->InsertPacket(frame_in, emptypacket)); - - frame_out = DecodeCompleteFrame(); - // Only last NALU is complete - EXPECT_EQ(0, CheckOutFrame(frame_out, packet_->sizeBytes, false)); -} - -TEST_F(TestBasicJitterBuffer, NextFrameWhenIncomplete) { - // Test that a we cannot get incomplete frames from the JB if we haven't - // received the marker bit, unless we have received a packet from a later - // timestamp. - jitter_buffer_->DecodeWithErrors(true); - // Start with a complete key frame - insert and decode. - packet_->frameType = kVideoFrameKey; - packet_->isFirstPacket = true; - packet_->markerBit = true; - VCMEncodedFrame* frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(frame_in, *packet_)); - VCMEncodedFrame* frame_out = DecodeCompleteFrame(); - EXPECT_TRUE(frame_out != NULL); - - packet_->seqNum += 2; - packet_->timestamp += 33 * 90; - packet_->frameType = kVideoFrameDelta; - packet_->isFirstPacket = false; - packet_->markerBit = false; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeIncompleteFrame(); - EXPECT_TRUE(frame_out == NULL); - - packet_->seqNum += 2; - packet_->timestamp += 33 * 90; - packet_->isFirstPacket = true; - - frame_in = jitter_buffer_->GetFrame(*packet_); - EXPECT_EQ(kFirstPacket, jitter_buffer_->InsertPacket(frame_in, *packet_)); - - frame_out = DecodeIncompleteFrame(); - - EXPECT_EQ(0, CheckOutFrame(frame_out, packet_->sizeBytes, false)); -} - TEST_F(TestRunningJitterBuffer, Full) { // Insert a key frame and decode it. EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); diff --git a/webrtc/modules/video_coding/main/test/jitter_buffer_test.cc b/webrtc/modules/video_coding/main/test/jitter_buffer_test.cc new file mode 100644 index 000000000..9edbd2a82 --- /dev/null +++ b/webrtc/modules/video_coding/main/test/jitter_buffer_test.cc @@ -0,0 +1,1755 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/video_coding/main/test/jitter_estimate_test.h" + +#include + +#include "webrtc/common_types.h" +#include "webrtc/modules/video_coding/main/interface/video_coding.h" +#include "webrtc/modules/video_coding/main/source/frame_buffer.h" +#include "webrtc/modules/video_coding/main/source/inter_frame_delay.h" +#include "webrtc/modules/video_coding/main/source/jitter_buffer.h" +#include "webrtc/modules/video_coding/main/source/jitter_estimator.h" +#include "webrtc/modules/video_coding/main/source/media_opt_util.h" +#include "webrtc/modules/video_coding/main/source/packet.h" +#include "webrtc/modules/video_coding/main/test/test_util.h" +#include "webrtc/modules/video_coding/main/test/test_macros.h" +#include "webrtc/system_wrappers/interface/clock.h" + +// TODO(holmer): Get rid of this to conform with style guide. +using namespace webrtc; + +// TODO (Mikhal/Stefan): Update as gtest and separate to specific tests. + +int CheckOutFrame(VCMEncodedFrame* frameOut, unsigned int size, bool startCode) +{ + if (frameOut == 0) + { + return -1; + } + + const uint8_t* outData = frameOut->Buffer(); + + unsigned int i = 0; + + if(startCode) + { + if (outData[0] != 0 || outData[1] != 0 || outData[2] != 0 || + outData[3] != 1) + { + return -2; + } + i+= 4; + } + + // check the frame data + int count = 3; + + // check the frame length + if (frameOut->Length() != size) + { + return -3; + } + + for(; i < size; i++) + { + if (outData[i] == 0 && outData[i + 1] == 0 && outData[i + 2] == 0x80) + { + i += 2; + } + else if(startCode && outData[i] == 0 && outData[i + 1] == 0) + { + if (outData[i] != 0 || outData[i + 1] != 0 || + outData[i + 2] != 0 || outData[i + 3] != 1) + { + return -3; + } + i += 3; + } + else + { + if (outData[i] != count) + { + return -4; + } + count++; + if(count == 10) + { + count = 3; + } + } + } + return 0; +} + +VCMEncodedFrame* DecodeCompleteFrame(uint32_t max_wait_time_ms) { + uint32_t timestamp = 0; + bool found_frame = jb.NextCompleteTimestamp(max_wait_time_ms, ×tamp); + if (!found_frame) + return NULL; + + return jb.ExtractAndSetDecode(timestamp); +} + +VCMEncodedFrame* DecodeIncompleteFrame() { + uint32_t timestamp = 0; + bool found_frame = + jb.MaybeGetIncompleteFrameTimestampForDecoding(×tamp); + if (!found_frame) + return NULL; + return frame = jb.ExtractAndSetDecode(timestamp); +} + +int JitterBufferTest(CmdArgs& args) +{ + Clock* clock = Clock::GetRealTimeClock(); + + // Start test + uint16_t seqNum = 1234; + uint32_t timeStamp = 0; + int size = 1400; + uint8_t data[1500]; + VCMPacket packet(data, size, seqNum, timeStamp, true); + + NullEventFactory event_factory; + VCMJitterBuffer jb(clock, &event_factory, -1, -1, true); + + seqNum = 1234; + timeStamp = 123*90; + VCMEncodedFrame* frameOut=NULL; + packet.timestamp = timeStamp; + packet.seqNum = seqNum; + + // build a data vector with 0, 0, 0x80, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0x80, 3.... + data[0] = 0; + data[1] = 0; + data[2] = 0x80; + int count = 3; + for (unsigned int i = 3; i < sizeof(data) - 3; ++i) + { + data[i] = count; + count++; + if(count == 10) + { + data[i+1] = 0; + data[i+2] = 0; + data[i+3] = 0x80; + count = 3; + i += 3; + } + } + + // Not started + TEST(0 == jb.GetFrame(packet)); + TEST(0 == DecodeCompleteFrame(10)); + TEST(0 == DecodeIncompleteFrame()); + + // Start + jb.Start(); + + // Allow decoding with errors. + jb.DecodeWithErrors(true); + + // Get frame to use for this timestamp + VCMEncodedFrame* frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // No packets inserted + TEST(0 == DecodeCompleteFrame(10)); + + + // + // TEST single packet frame + // + // -------- + // | 1234 | + // -------- + + // packet.frameType; + // packet.dataPtr; + // packet.sizeBytes; + // packet.timestamp; + // packet.seqNum; + // packet.isFirstPacket; + // packet.markerBit; + // + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = true; + packet.markerBit = true; + + // Insert a packet into a frame. + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + // Get the frame (always starts with a key frame). + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameKey); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE delta frame 1 packet\n"); + + // + // TEST dual packet frame + // + // ----------------- + // | 1235 | 1236 | + // ----------------- + // + + seqNum++; + timeStamp += 33*90; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*2, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE delta frame 2 packets\n"); + + + // + // TEST 100 packets frame Key frame + // + // ---------------------------------- + // | 1237 | 1238 | .... | 1336 | + // ---------------------------------- + + // insert first packet + timeStamp += 33*90; + seqNum++; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + // insert 98 frames + int loop = 0; + do + { + seqNum++; + 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(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*100, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameKey); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE key frame 100 packets\n"); + + // + // TEST 100 packets frame Delta frame + // + // ---------------------------------- + // | 1337 | 1238 | .... | 1436 | + // ---------------------------------- + + // 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + // insert 98 frames + loop = 0; + do + { + seqNum++; + 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(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*100, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE delta frame 100 packets\n"); + + // + // TEST packet re-ordering reverse order + // + // ---------------------------------- + // | 1437 | 1238 | .... | 1536 | + // ---------------------------------- + // <---------- + + // insert "first" packet last seqnum + timeStamp += 33*90; + seqNum += 100; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = false; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + // insert 98 packets + loop = 0; + do + { + seqNum--; + 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 = true; + packet.markerBit = false; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*100, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE delta frame 100 packets reverse order\n"); + + seqNum+= 100; + + // + // TEST frame re-ordering 2 frames 2 packets each + // + // ----------------- ----------------- + // | 1539 | 1540 | | 1537 | 1538 | + // ----------------- ----------------- + + seqNum += 2; + timeStamp += 2* 33 * 90; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // check that we fail to get frame since seqnum is not continuous + frameOut = DecodeCompleteFrame(10); + TEST(frameOut == 0); + + seqNum -= 3; + timeStamp -= 33*90; + 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 the frame + frameOut = jb.GetCompleteFrameForDecoding(10); + + // it should not be complete + TEST(frameOut == 0); + + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*2, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*2, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + seqNum += 2; + //printf("DONE frame re-ordering 2 frames 2 packets\n"); + + // restore + packet.dataPtr = data; + packet.codec = kVideoCodecUnknown; + + // + // TEST duplicate packets + // + // ----------------- + // | 1543 | 1543 | + // ----------------- + // + + seqNum++; + timeStamp += 2*33*90; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + packet.isFirstPacket = false; + packet.markerBit = true; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kDuplicatePacket == jb.InsertPacket(frameIn, packet)); + + seqNum++; + packet.seqNum = seqNum; + + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*2, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE test duplicate packets\n"); + + // + // TEST H.264 insert start code + // + // ----------------- + // | 1544 | 1545 | + // ----------------- + // insert start code, both packets + + seqNum++; + timeStamp += 33 * 90; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = true; + packet.markerBit = false; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.insertStartCode = true; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size * 2 + 4 * 2, true) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + // reset + packet.insertStartCode = false; + //printf("DONE H.264 insert start code test 2 packets\n"); + + + jb.Flush(); + + // + // TEST packet loss. Verify missing packets statistics and not decodable + // packets statistics. + // Insert 10 frames consisting of 4 packets and remove one from all of them. + // The last packet is an empty (non-media) packet + // + + // Select a start seqNum which triggers a difficult wrap situation + // The JB will only output (incomplete)frames if the next one has started + // to arrive. Start by inserting one frame (key). + seqNum = 0xffff - 4; + seqNum++; + timeStamp += 33*90; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = true; + packet.markerBit = false; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.completeNALU = kNaluStart; + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + // Insert a packet into a frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + for (int i = 0; i < 11; ++i) { + webrtc::FrameType frametype = kVideoFrameDelta; + seqNum++; + timeStamp += 33*90; + packet.frameType = frametype; + packet.isFirstPacket = true; + packet.markerBit = false; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.completeNALU = kNaluStart; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + // Get the frame + frameOut = DecodeCompleteFrame(10); + + // Should not be complete + TEST(frameOut == 0); + + seqNum += 2; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + packet.completeNALU = kNaluEnd; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + + + // Insert an empty (non-media) packet + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = false; + packet.seqNum = seqNum; + packet.completeNALU = kNaluEnd; + packet.frameType = kFrameEmpty; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + + // Get the frame + frameOut = DecodeIncompleteFrame(); + + // One of the packets has been discarded by the jitter buffer. + // Last frame can't be extracted yet. + if (i < 10) + { + TEST(CheckOutFrame(frameOut, size, false) == 0); + + // check the frame type + if (i == 0) + { + TEST(frameOut->FrameType() == kVideoFrameKey); + } + else + { + TEST(frameOut->FrameType() == frametype); + } + TEST(frameOut->Complete() == false); + TEST(frameOut->MissingFrame() == false); + } + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + } + + TEST(jb.num_not_decodable_packets() == 10); + + // Insert 3 old packets and verify that we have 3 discarded packets + // Match value to actual latest timestamp decoded + timeStamp -= 33 * 90; + packet.timestamp = timeStamp - 1000; + frameIn = jb.GetFrame(packet); + TEST(frameIn == NULL); + + packet.timestamp = timeStamp - 500; + frameIn = jb.GetFrame(packet); + TEST(frameIn == NULL); + + packet.timestamp = timeStamp - 100; + frameIn = jb.GetFrame(packet); + TEST(frameIn == NULL); + + TEST(jb.num_discarded_packets() == 3); + + jb.Flush(); + + // This statistic shouldn't be reset by a flush. + TEST(jb.num_discarded_packets() == 3); + + //printf("DONE Statistics\n"); + + + // Temporarily do this to make the rest of the test work: + timeStamp += 33*90; + seqNum += 4; + + + // + // TEST delta frame 100 packets with seqNum wrap + // + // --------------------------------------- + // | 65520 | 65521 | ... | 82 | 83 | + // --------------------------------------- + // + + jb.Flush(); + + // insert first packet + timeStamp += 33*90; + seqNum = 0xfff0; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + // Insert 98 packets. + loop = 0; + do + { + seqNum++; + 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)); + + // get the frame + frameOut = DecodeCompleteFrame(2); + + // it should not be complete + 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(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeCompleteFrame(10); + + TEST(CheckOutFrame(frameOut, size*100, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameKey); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE delta frame 100 packets with wrap in seqNum\n"); + + // + // TEST packet re-ordering reverse order with neg seqNum warp + // + // ---------------------------------------- + // | 65447 | 65448 | ... | 9 | 10 | + // ---------------------------------------- + // <------------- + + // test flush + jb.Flush(); + + // insert "first" packet last seqnum + timeStamp += 33*90; + seqNum = 10; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + 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 the frame + frameOut = DecodeIncompleteFrame(); + + // it should not be complete + TEST(frameOut == 0); + + // insert 98 frames + loop = 0; + do + { + seqNum--; + 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)); + + // get the frame + frameOut = DecodeCompleteFrame(2); + + // it should not be complete + TEST(frameOut == 0); + + loop++; + } while (loop < 98); + + // insert last packet + seqNum--; + packet.isFirstPacket = true; + packet.markerBit = false; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeIncompleteFrame(); + + TEST(CheckOutFrame(frameOut, size*100, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE delta frame 100 packets reverse order with wrap in seqNum \n"); + + // test flush + jb.Flush(); + + // + // TEST packet re-ordering with seqNum wrap + // + // ----------------------- + // | 1 | 65535 | 0 | + // ----------------------- + + // insert "first" packet last seqnum + timeStamp += 33*90; + seqNum = 1; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + // insert last packet + seqNum -= 2; + packet.isFirstPacket = true; + 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)); + + // get the frame + frameOut = DecodeIncompleteFrame(); + + // it should not be complete + TEST(frameOut == 0); + + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = false; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeIncompleteFrame(); + + TEST(CheckOutFrame(frameOut, size*3, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE delta frame 3 packets re-ordering with wrap in seqNum \n"); + + // test flush + jb.Flush(); + + // + // TEST insert old frame + // + // ------- ------- + // | 2 | | 1 | + // ------- ------- + // t = 3000 t = 2000 + + seqNum = 2; + timeStamp = 3000; + packet.frameType = kVideoFrameDelta; + 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 the frame + frameOut = DecodeCompleteFrame(); + TEST(3000 == frameOut->TimeStamp()); + + TEST(CheckOutFrame(frameOut, size, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + jb.ReleaseFrame(frameOut); + + seqNum--; + timeStamp = 2000; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = true; + packet.markerBit = true; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + + frameIn = jb.GetFrame(packet); + // Changed behavior, never insert packets into frames older than the + // last decoded frame. + TEST(frameIn == 0); + + //printf("DONE insert old frame\n"); + + jb.Flush(); + + // + // TEST insert old frame with wrap in timestamp + // + // ------- ------- + // | 2 | | 1 | + // ------- ------- + // t = 3000 t = 0xffffff00 + + seqNum = 2; + timeStamp = 3000; + packet.frameType = kVideoFrameDelta; + 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 the frame + frameOut = DecodeIncompleteFrame(); + TEST(timeStamp == frameOut->TimeStamp()); + + TEST(CheckOutFrame(frameOut, size, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + jb.ReleaseFrame(frameOut); + + seqNum--; + timeStamp = 0xffffff00; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = true; + packet.markerBit = true; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + + frameIn = jb.GetFrame(packet); + // This timestamp is old + TEST(frameIn == 0); + + jb.Flush(); + + // + // TEST wrap in timeStamp + // + // --------------- --------------- + // | 1 | 2 | | 3 | 4 | + // --------------- --------------- + // t = 0xffffff00 t = 33*90 + + seqNum = 1; + timeStamp = 0xffffff00; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + frameOut = DecodeIncompleteFrame(); + + TEST(CheckOutFrame(frameOut, size*2, false) == 0); + + jb.ReleaseFrame(frameOut); + + seqNum++; + timeStamp += 33*90; + 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 the frame + frameOut = DecodeCompleteFrame(10); + + // it should not be complete + TEST(frameOut == 0); + + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert a packet into a frame + TEST(kCompleteSession == jb.InsertPacket(frameIn, packet)); + + // get the frame + frameOut = DecodeIncompleteFrame(); + + TEST(CheckOutFrame(frameOut, size*2, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + //printf("DONE time stamp wrap 2 frames 2 packets\n"); + + jb.Flush(); + + // + // TEST insert 2 frames with wrap in timeStamp + // + // ------- ------- + // | 1 | | 2 | + // ------- ------- + // t = 0xffffff00 t = 2700 + + seqNum = 1; + timeStamp = 0xffffff00; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = true; + packet.markerBit = true; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert first frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + // Insert next frame + seqNum++; + timeStamp = 2700; + packet.frameType = kVideoFrameDelta; + 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 frame + frameOut = jb.GetFrameForDecoding(); + TEST(0xffffff00 == frameOut->TimeStamp()); + + TEST(CheckOutFrame(frameOut, size, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Get frame + VCMEncodedFrame* frameOut2 = DecodeIncompleteFrame(); + TEST(2700 == frameOut2->TimeStamp()); + + TEST(CheckOutFrame(frameOut2, size, false) == 0); + + // check the frame type + TEST(frameOut2->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + jb.ReleaseFrame(frameOut2); + + //printf("DONE insert 2 frames (1 packet) with wrap in timestamp\n"); + + jb.Flush(); + + // + // TEST insert 2 frames re-ordered with wrap in timeStamp + // + // ------- ------- + // | 2 | | 1 | + // ------- ------- + // t = 2700 t = 0xffffff00 + + seqNum = 2; + timeStamp = 2700; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = true; + packet.markerBit = true; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert first frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + // Insert second frame + seqNum--; + timeStamp = 0xffffff00; + packet.frameType = kVideoFrameDelta; + 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 frame + frameOut = jb.GetFrameForDecoding(); + TEST(0xffffff00 == frameOut->TimeStamp()); + + TEST(CheckOutFrame(frameOut, size, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameDelta); + + // Get frame + frameOut2 = DecodeIncompleteFrame(); + TEST(2700 == frameOut2->TimeStamp()); + + TEST(CheckOutFrame(frameOut2, size, false) == 0); + + // check the frame type + TEST(frameOut2->FrameType() == kVideoFrameDelta); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + jb.ReleaseFrame(frameOut2); + + //printf("DONE insert 2 frames (1 packet) re-ordered with wrap in timestamp\n"); + + // + // TEST delta frame with more than max number of packets + // + + jb.Start(); + + loop = 0; + packet.timestamp += 33*90; + bool firstPacket = true; + // insert kMaxPacketsInJitterBuffer into frame + do + { + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = false; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert frame + if (firstPacket) + { + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + firstPacket = false; + } + else + { + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + } + + loop++; + } while (loop < kMaxPacketsInSession); + + // Max number of packets inserted + + // Insert one more packet + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = true; + packet.seqNum = seqNum; + + frameIn = jb.GetFrame(packet); + TEST(frameIn != 0); + + // Insert the packet -> frame recycled + TEST(kSizeError == jb.InsertPacket(frameIn, packet)); + + TEST(0 == DecodeIncompleteFrame()); + + //printf("DONE fill frame - packets > max number of packets\n"); + + // + // TEST fill JB with more than max number of frame (50 delta frames + + // 51 key frames) with wrap in seqNum + // + // -------------------------------------------------------------- + // | 65485 | 65486 | 65487 | .... | 65535 | 0 | 1 | 2 | .....| 50 | + // -------------------------------------------------------------- + // |<-----------delta frames------------->|<------key frames----->| + + jb.Flush(); + + loop = 0; + seqNum = 65485; + VCMEncodedFrame* ptrLastDeltaFrame = NULL; + VCMEncodedFrame* ptrFirstKeyFrame = NULL; + // 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); + + if (loop == 49) // last delta + { + ptrLastDeltaFrame = frameIn; + } + if (loop == 50) // first key + { + ptrFirstKeyFrame = frameIn; + packet.frameType = kVideoFrameKey; + } + + // Insert frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + 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; + packet.timestamp = timeStamp; + + // Now, no free frame - frames will be recycled until first key frame + frameIn = jb.GetFrame(packet); + // ptr to last inserted delta frame should be returned + TEST(frameIn != 0 && frameIn && ptrLastDeltaFrame); + + // Insert frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + // get the first key frame + frameOut = jb.GetFrameForDecoding(); + TEST(ptrFirstKeyFrame == frameOut); + + TEST(CheckOutFrame(frameOut, size, false) == 0); + + // check the frame type + TEST(frameOut->FrameType() == kVideoFrameKey); + + // Release frame (when done with decoding) + jb.ReleaseFrame(frameOut); + + jb.Flush(); + + // printf("DONE fill JB - nr of delta + key frames (w/ wrap in seqNum) > + // max nr of frames\n"); + + // 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. + int maxSize = 1000; + for (int i = 0; i < maxSize + 10; i++) + { + timeStamp += 33 * 90; + seqNum++; + packet.isFirstPacket = false; + packet.markerBit = false; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kFrameEmpty; + VCMEncodedFrame* testFrame = jb.MaybeGetIncompleteFrameForDecoding(); + // timestamp should bever be the last TS inserted + if (testFrame != NULL) + { + TEST(testFrame->TimeStamp() < timeStamp); + printf("Not null TS = %d\n",testFrame->TimeStamp()); + } + } + + jb.Flush(); + + + // printf(DONE testing inserting empty packets to the JB) + + + // H.264 tests + // Test incomplete NALU frames + + jb.Flush(); + jb.SetNackMode(kNoNack, -1, -1); + seqNum ++; + timeStamp += 33 * 90; + int insertedLength = 0; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = true; + packet.completeNALU = kNaluStart; + packet.markerBit = false; + + frameIn = jb.GetFrame(packet); + + // Insert a packet into a frame + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + seqNum += 2; // Skip one packet + packet.seqNum = seqNum; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + packet.completeNALU = kNaluIncomplete; + packet.markerBit = false; + + // Insert a packet into a frame + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + + seqNum++; + packet.seqNum = seqNum; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + packet.completeNALU = kNaluEnd; + packet.markerBit = false; + + // Insert a packet into a frame + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + + seqNum++; + packet.seqNum = seqNum; + packet.completeNALU = kNaluComplete; + packet.markerBit = true; // Last packet + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + + + // The JB will only output (incomplete) frames if a packet belonging to a + // subsequent frame was already inserted. Insert one packet of a subsequent + // frame. place high timestamp so the JB would always have a next frame + // (otherwise, for every inserted frame we need to take care of the next + // frame as well). + packet.seqNum = 1; + packet.timestamp = timeStamp + 33 * 90 * 10; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = false; + packet.completeNALU = kNaluStart; + packet.markerBit = false; + frameIn = jb.GetFrame(packet); + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + frameOut = jb.MaybeGetIncompleteFrameForDecoding(); + + // We can decode everything from a NALU until a packet has been lost. + // Thus we can decode the first packet of the first NALU and the second NALU + // which consists of one packet. + TEST(CheckOutFrame(frameOut, packet.sizeBytes * 2, false) == 0); + jb.ReleaseFrame(frameOut); + + // Test reordered start frame + 1 lost + seqNum += 2; // Reoreder 1 frame + timeStamp += 33*90; + insertedLength = 0; + + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + packet.completeNALU = kNaluEnd; + packet.markerBit = false; + + TEST(frameIn = jb.GetFrame(packet)); + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + insertedLength += packet.sizeBytes; // This packet should be decoded + + seqNum--; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = true; + packet.completeNALU = kNaluStart; + packet.markerBit = false; + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + insertedLength += packet.sizeBytes; // This packet should be decoded + + seqNum += 3; // One packet drop + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + packet.completeNALU = kNaluComplete; + packet.markerBit = false; + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + insertedLength += packet.sizeBytes; // This packet should be decoded + + seqNum += 1; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + packet.completeNALU = kNaluStart; + packet.markerBit = false; + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + // This packet should be decoded since it's the beginning of a NAL + insertedLength += packet.sizeBytes; + + seqNum += 2; + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = false; + packet.completeNALU = kNaluEnd; + packet.markerBit = true; + TEST(kIncomplete == jb.InsertPacket(frameIn, packet)); + // This packet should not be decoded because it is an incomplete NAL if it + // is the last + + frameOut = jb.MaybeGetIncompleteFrameForDecoding(); + // Only last NALU is complete + TEST(CheckOutFrame(frameOut, insertedLength, false) == 0); + jb.ReleaseFrame(frameOut); + + + // Test to insert empty packet + seqNum += 1; + timeStamp += 33 * 90; + VCMPacket emptypacket(data, 0, seqNum, timeStamp, true); + emptypacket.seqNum = seqNum; + emptypacket.timestamp = timeStamp; + emptypacket.frameType = kVideoFrameKey; + emptypacket.isFirstPacket = true; + emptypacket.completeNALU = kNaluComplete; + emptypacket.markerBit = true; + TEST(frameIn = jb.GetFrame(emptypacket)); + TEST(kFirstPacket == jb.InsertPacket(frameIn, emptypacket)); + // This packet should not be decoded because it is an incomplete NAL if it + // is the last + insertedLength += 0; + + // Will be sent to the decoder, as a packet belonging to a subsequent frame + // has arrived. + frameOut = jb.MaybeGetIncompleteFrameForDecoding(); + + + // Test that a frame can include an empty packet. + seqNum += 1; + timeStamp += 33 * 90; + + packet.seqNum = seqNum; + packet.timestamp = timeStamp; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = true; + packet.completeNALU = kNaluComplete; + packet.markerBit = false; + TEST(frameIn = jb.GetFrame(packet)); + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + seqNum += 1; + emptypacket.seqNum = seqNum; + emptypacket.timestamp = timeStamp; + emptypacket.frameType = kVideoFrameKey; + emptypacket.isFirstPacket = true; + emptypacket.completeNALU = kNaluComplete; + emptypacket.markerBit = true; + TEST(kCompleteSession == jb.InsertPacket(frameIn, emptypacket)); + + // get the frame + frameOut = jb.GetFrameForDecoding(); + // Only last NALU is complete + TEST(CheckOutFrame(frameOut, packet.sizeBytes, false) == 0); + + jb.ReleaseFrame(frameOut); + + jb.Flush(); + + // Test that a we cannot get incomplete frames from the JB if we haven't + // received the marker bit, unless we have received a packet from a later + // timestamp. + + packet.seqNum += 2; + packet.frameType = kVideoFrameDelta; + packet.isFirstPacket = false; + packet.markerBit = false; + + TEST(frameIn = jb.GetFrame(packet)); + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + frameOut = jb.MaybeGetIncompleteFrameForDecoding(); + TEST(frameOut == NULL); + + packet.seqNum += 2; + packet.timestamp += 33 * 90; + + TEST(frameIn = jb.GetFrame(packet)); + TEST(kFirstPacket == jb.InsertPacket(frameIn, packet)); + + frameOut = jb.MaybeGetIncompleteFrameForDecoding(); + + TEST(frameOut != NULL); + TEST(CheckOutFrame(frameOut, packet.sizeBytes, false) == 0); + jb.ReleaseFrame(frameOut); + + jb.Stop(); + + printf("DONE !!!\n"); + + printf("\nVCM Jitter Buffer Test: \n\n%i tests completed\n", + vcmMacrosTests); + if (vcmMacrosErrors > 0) + { + printf("%i FAILED\n\n", vcmMacrosErrors); + } + else + { + printf("ALL PASSED\n\n"); + } + + return 0; + +}