diff options
Diffstat (limited to 'webrtc/modules/video_coding/jitter_buffer_unittest.cc')
-rw-r--r-- | webrtc/modules/video_coding/jitter_buffer_unittest.cc | 2571 |
1 files changed, 2571 insertions, 0 deletions
diff --git a/webrtc/modules/video_coding/jitter_buffer_unittest.cc b/webrtc/modules/video_coding/jitter_buffer_unittest.cc new file mode 100644 index 0000000000..8abc1b5471 --- /dev/null +++ b/webrtc/modules/video_coding/jitter_buffer_unittest.cc @@ -0,0 +1,2571 @@ +/* + * Copyright (c) 2011 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 <string.h> + +#include <list> + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/video_coding/frame_buffer.h" +#include "webrtc/modules/video_coding/jitter_buffer.h" +#include "webrtc/modules/video_coding/media_opt_util.h" +#include "webrtc/modules/video_coding/packet.h" +#include "webrtc/modules/video_coding/test/stream_generator.h" +#include "webrtc/modules/video_coding/test/test_util.h" +#include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/system_wrappers/include/metrics.h" +#include "webrtc/test/histogram.h" + +namespace webrtc { + +namespace { +const uint32_t kProcessIntervalSec = 60; +} // namespace + +class Vp9SsMapTest : public ::testing::Test { + protected: + Vp9SsMapTest() : packet_(data_, 1400, 1234, 1, true) {} + + virtual void SetUp() { + packet_.isFirstPacket = true; + packet_.markerBit = true; + packet_.frameType = kVideoFrameKey; + packet_.codec = kVideoCodecVP9; + packet_.codecSpecificHeader.codec = kRtpVideoVp9; + packet_.codecSpecificHeader.codecHeader.VP9.flexible_mode = false; + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = 0; + packet_.codecSpecificHeader.codecHeader.VP9.temporal_idx = kNoTemporalIdx; + packet_.codecSpecificHeader.codecHeader.VP9.temporal_up_switch = false; + packet_.codecSpecificHeader.codecHeader.VP9.ss_data_available = true; + packet_.codecSpecificHeader.codecHeader.VP9.gof.SetGofInfoVP9( + kTemporalStructureMode3); // kTemporalStructureMode3: 0-2-1-2.. + } + + Vp9SsMap map_; + uint8_t data_[1500]; + VCMPacket packet_; +}; + +TEST_F(Vp9SsMapTest, Insert) { + EXPECT_TRUE(map_.Insert(packet_)); +} + +TEST_F(Vp9SsMapTest, Insert_NoSsData) { + packet_.codecSpecificHeader.codecHeader.VP9.ss_data_available = false; + EXPECT_FALSE(map_.Insert(packet_)); +} + +TEST_F(Vp9SsMapTest, Find) { + EXPECT_TRUE(map_.Insert(packet_)); + Vp9SsMap::SsMap::iterator it; + EXPECT_TRUE(map_.Find(packet_.timestamp, &it)); + EXPECT_EQ(packet_.timestamp, it->first); +} + +TEST_F(Vp9SsMapTest, Find_WithWrap) { + const uint32_t kSsTimestamp1 = 0xFFFFFFFF; + const uint32_t kSsTimestamp2 = 100; + packet_.timestamp = kSsTimestamp1; + EXPECT_TRUE(map_.Insert(packet_)); + packet_.timestamp = kSsTimestamp2; + EXPECT_TRUE(map_.Insert(packet_)); + Vp9SsMap::SsMap::iterator it; + EXPECT_FALSE(map_.Find(kSsTimestamp1 - 1, &it)); + EXPECT_TRUE(map_.Find(kSsTimestamp1, &it)); + EXPECT_EQ(kSsTimestamp1, it->first); + EXPECT_TRUE(map_.Find(0, &it)); + EXPECT_EQ(kSsTimestamp1, it->first); + EXPECT_TRUE(map_.Find(kSsTimestamp2 - 1, &it)); + EXPECT_EQ(kSsTimestamp1, it->first); + EXPECT_TRUE(map_.Find(kSsTimestamp2, &it)); + EXPECT_EQ(kSsTimestamp2, it->first); + EXPECT_TRUE(map_.Find(kSsTimestamp2 + 1, &it)); + EXPECT_EQ(kSsTimestamp2, it->first); +} + +TEST_F(Vp9SsMapTest, Reset) { + EXPECT_TRUE(map_.Insert(packet_)); + Vp9SsMap::SsMap::iterator it; + EXPECT_TRUE(map_.Find(packet_.timestamp, &it)); + EXPECT_EQ(packet_.timestamp, it->first); + + map_.Reset(); + EXPECT_FALSE(map_.Find(packet_.timestamp, &it)); +} + +TEST_F(Vp9SsMapTest, RemoveOld) { + Vp9SsMap::SsMap::iterator it; + const uint32_t kSsTimestamp1 = 10000; + packet_.timestamp = kSsTimestamp1; + EXPECT_TRUE(map_.Insert(packet_)); + + const uint32_t kTimestamp = kSsTimestamp1 + kProcessIntervalSec * 90000; + map_.RemoveOld(kTimestamp - 1); // Interval not passed. + EXPECT_TRUE(map_.Find(kSsTimestamp1, &it)); // Should not been removed. + + map_.RemoveOld(kTimestamp); + EXPECT_FALSE(map_.Find(kSsTimestamp1, &it)); + EXPECT_TRUE(map_.Find(kTimestamp, &it)); + EXPECT_EQ(kTimestamp, it->first); +} + +TEST_F(Vp9SsMapTest, RemoveOld_WithWrap) { + Vp9SsMap::SsMap::iterator it; + const uint32_t kSsTimestamp1 = 0xFFFFFFFF - kProcessIntervalSec * 90000; + const uint32_t kSsTimestamp2 = 10; + const uint32_t kSsTimestamp3 = 1000; + packet_.timestamp = kSsTimestamp1; + EXPECT_TRUE(map_.Insert(packet_)); + packet_.timestamp = kSsTimestamp2; + EXPECT_TRUE(map_.Insert(packet_)); + packet_.timestamp = kSsTimestamp3; + EXPECT_TRUE(map_.Insert(packet_)); + + map_.RemoveOld(kSsTimestamp3); + EXPECT_FALSE(map_.Find(kSsTimestamp1, &it)); + EXPECT_FALSE(map_.Find(kSsTimestamp2, &it)); + EXPECT_TRUE(map_.Find(kSsTimestamp3, &it)); +} + +TEST_F(Vp9SsMapTest, UpdatePacket_NoSsData) { + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = 0; + EXPECT_FALSE(map_.UpdatePacket(&packet_)); +} + +TEST_F(Vp9SsMapTest, UpdatePacket_NoGofIdx) { + EXPECT_TRUE(map_.Insert(packet_)); + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = kNoGofIdx; + EXPECT_FALSE(map_.UpdatePacket(&packet_)); +} + +TEST_F(Vp9SsMapTest, UpdatePacket_InvalidGofIdx) { + EXPECT_TRUE(map_.Insert(packet_)); + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = 4; + EXPECT_FALSE(map_.UpdatePacket(&packet_)); +} + +TEST_F(Vp9SsMapTest, UpdatePacket) { + EXPECT_TRUE(map_.Insert(packet_)); // kTemporalStructureMode3: 0-2-1-2.. + + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = 0; + EXPECT_TRUE(map_.UpdatePacket(&packet_)); + EXPECT_EQ(0, packet_.codecSpecificHeader.codecHeader.VP9.temporal_idx); + EXPECT_FALSE(packet_.codecSpecificHeader.codecHeader.VP9.temporal_up_switch); + EXPECT_EQ(1U, packet_.codecSpecificHeader.codecHeader.VP9.num_ref_pics); + EXPECT_EQ(4, packet_.codecSpecificHeader.codecHeader.VP9.pid_diff[0]); + + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = 1; + EXPECT_TRUE(map_.UpdatePacket(&packet_)); + EXPECT_EQ(2, packet_.codecSpecificHeader.codecHeader.VP9.temporal_idx); + EXPECT_TRUE(packet_.codecSpecificHeader.codecHeader.VP9.temporal_up_switch); + EXPECT_EQ(1U, packet_.codecSpecificHeader.codecHeader.VP9.num_ref_pics); + EXPECT_EQ(1, packet_.codecSpecificHeader.codecHeader.VP9.pid_diff[0]); + + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = 2; + EXPECT_TRUE(map_.UpdatePacket(&packet_)); + EXPECT_EQ(1, packet_.codecSpecificHeader.codecHeader.VP9.temporal_idx); + EXPECT_TRUE(packet_.codecSpecificHeader.codecHeader.VP9.temporal_up_switch); + EXPECT_EQ(1U, packet_.codecSpecificHeader.codecHeader.VP9.num_ref_pics); + EXPECT_EQ(2, packet_.codecSpecificHeader.codecHeader.VP9.pid_diff[0]); + + packet_.codecSpecificHeader.codecHeader.VP9.gof_idx = 3; + EXPECT_TRUE(map_.UpdatePacket(&packet_)); + EXPECT_EQ(2, packet_.codecSpecificHeader.codecHeader.VP9.temporal_idx); + EXPECT_FALSE(packet_.codecSpecificHeader.codecHeader.VP9.temporal_up_switch); + EXPECT_EQ(2U, packet_.codecSpecificHeader.codecHeader.VP9.num_ref_pics); + EXPECT_EQ(1, packet_.codecSpecificHeader.codecHeader.VP9.pid_diff[0]); + EXPECT_EQ(2, packet_.codecSpecificHeader.codecHeader.VP9.pid_diff[1]); +} + +class TestBasicJitterBuffer : public ::testing::Test { + protected: + virtual void SetUp() { + clock_.reset(new SimulatedClock(0)); + jitter_buffer_.reset(new VCMJitterBuffer( + clock_.get(), + rtc::scoped_ptr<EventWrapper>(event_factory_.CreateEvent()))); + 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; + } + + void CheckOutFrame(VCMEncodedFrame* frame_out, + unsigned int size, + bool startCode) { + ASSERT_TRUE(frame_out); + + 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; + } + } + } + } + + uint16_t seq_num_; + uint32_t timestamp_; + int size_; + uint8_t data_[1500]; + rtc::scoped_ptr<VCMPacket> packet_; + rtc::scoped_ptr<SimulatedClock> clock_; + NullEventFactory event_factory_; + rtc::scoped_ptr<VCMJitterBuffer> jitter_buffer_; +}; + +class TestRunningJitterBuffer : public ::testing::Test { + protected: + enum { kDataBufferSize = 10 }; + + virtual void SetUp() { + clock_.reset(new SimulatedClock(0)); + max_nack_list_size_ = 150; + oldest_packet_to_nack_ = 250; + jitter_buffer_ = new VCMJitterBuffer( + clock_.get(), + rtc::scoped_ptr<EventWrapper>(event_factory_.CreateEvent())); + stream_generator_ = new StreamGenerator(0, clock_->TimeInMilliseconds()); + jitter_buffer_->Start(); + jitter_buffer_->SetNackSettings(max_nack_list_size_, oldest_packet_to_nack_, + 0); + memset(data_buffer_, 0, kDataBufferSize); + } + + virtual void TearDown() { + jitter_buffer_->Stop(); + delete stream_generator_; + delete jitter_buffer_; + } + + VCMFrameBufferEnum InsertPacketAndPop(int index) { + VCMPacket packet; + packet.dataPtr = data_buffer_; + bool packet_available = stream_generator_->PopPacket(&packet, index); + EXPECT_TRUE(packet_available); + if (!packet_available) + return kGeneralError; // Return here to avoid crashes below. + bool retransmitted = false; + return jitter_buffer_->InsertPacket(packet, &retransmitted); + } + + VCMFrameBufferEnum InsertPacket(int index) { + VCMPacket packet; + packet.dataPtr = data_buffer_; + bool packet_available = stream_generator_->GetPacket(&packet, index); + EXPECT_TRUE(packet_available); + if (!packet_available) + return kGeneralError; // Return here to avoid crashes below. + bool retransmitted = false; + return jitter_buffer_->InsertPacket(packet, &retransmitted); + } + + VCMFrameBufferEnum InsertFrame(FrameType frame_type) { + stream_generator_->GenerateFrame( + frame_type, (frame_type != kEmptyFrame) ? 1 : 0, + (frame_type == kEmptyFrame) ? 1 : 0, clock_->TimeInMilliseconds()); + VCMFrameBufferEnum ret = InsertPacketAndPop(0); + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + return ret; + } + + VCMFrameBufferEnum InsertFrames(int num_frames, FrameType frame_type) { + VCMFrameBufferEnum ret_for_all = kNoError; + for (int i = 0; i < num_frames; ++i) { + VCMFrameBufferEnum ret = InsertFrame(frame_type); + if (ret < kNoError) { + ret_for_all = ret; + } else if (ret_for_all >= kNoError) { + ret_for_all = ret; + } + } + return ret_for_all; + } + + void DropFrame(int num_packets) { + stream_generator_->GenerateFrame(kVideoFrameDelta, num_packets, 0, + clock_->TimeInMilliseconds()); + for (int i = 0; i < num_packets; ++i) + stream_generator_->DropLastPacket(); + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + } + + bool DecodeCompleteFrame() { + uint32_t timestamp = 0; + bool found_frame = jitter_buffer_->NextCompleteTimestamp(0, ×tamp); + if (!found_frame) + return false; + + VCMEncodedFrame* frame = jitter_buffer_->ExtractAndSetDecode(timestamp); + bool ret = (frame != NULL); + jitter_buffer_->ReleaseFrame(frame); + return ret; + } + + bool DecodeIncompleteFrame() { + uint32_t timestamp = 0; + bool found_frame = jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp); + if (!found_frame) + return false; + VCMEncodedFrame* frame = jitter_buffer_->ExtractAndSetDecode(timestamp); + bool ret = (frame != NULL); + jitter_buffer_->ReleaseFrame(frame); + return ret; + } + + VCMJitterBuffer* jitter_buffer_; + StreamGenerator* stream_generator_; + rtc::scoped_ptr<SimulatedClock> clock_; + NullEventFactory event_factory_; + size_t max_nack_list_size_; + int oldest_packet_to_nack_; + uint8_t data_buffer_[kDataBufferSize]; +}; + +class TestJitterBufferNack : public TestRunningJitterBuffer { + protected: + virtual void SetUp() { + TestRunningJitterBuffer::SetUp(); + jitter_buffer_->SetNackMode(kNack, -1, -1); + } + + virtual void TearDown() { TestRunningJitterBuffer::TearDown(); } +}; + +TEST_F(TestBasicJitterBuffer, StopRunning) { + jitter_buffer_->Stop(); + EXPECT_TRUE(NULL == DecodeCompleteFrame()); + EXPECT_TRUE(NULL == DecodeIncompleteFrame()); + jitter_buffer_->Start(); + // Allow selective errors. + jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors); + + // No packets inserted. + EXPECT_TRUE(NULL == DecodeCompleteFrame()); + EXPECT_TRUE(NULL == DecodeIncompleteFrame()); + + // Allow decoding with errors. + jitter_buffer_->SetDecodeErrorMode(kWithErrors); + + // No packets inserted. + EXPECT_TRUE(NULL == DecodeCompleteFrame()); + EXPECT_TRUE(NULL == DecodeIncompleteFrame()); +} + +TEST_F(TestBasicJitterBuffer, SinglePacketFrame) { + // Always start with a complete key frame when not allowing errors. + jitter_buffer_->SetDecodeErrorMode(kNoErrors); + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->timestamp += 123 * 90; + + // Insert the packet to the jitter buffer and get a frame. + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, VerifyHistogramStats) { + test::ClearHistograms(); + // Always start with a complete key frame when not allowing errors. + jitter_buffer_->SetDecodeErrorMode(kNoErrors); + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->timestamp += 123 * 90; + + // Insert single packet frame to the jitter buffer and get a frame. + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + // Verify that histograms are updated when the jitter buffer is stopped. + clock_->AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000); + jitter_buffer_->Stop(); + EXPECT_EQ( + 0, test::LastHistogramSample("WebRTC.Video.DiscardedPacketsInPercent")); + EXPECT_EQ( + 0, test::LastHistogramSample("WebRTC.Video.DuplicatedPacketsInPercent")); + EXPECT_NE(-1, test::LastHistogramSample( + "WebRTC.Video.CompleteFramesReceivedPerSecond")); + EXPECT_EQ(1000, test::LastHistogramSample( + "WebRTC.Video.KeyFramesReceivedInPermille")); + + // Verify that histograms are not updated if stop is called again. + jitter_buffer_->Stop(); + EXPECT_EQ( + 1, test::NumHistogramSamples("WebRTC.Video.DiscardedPacketsInPercent")); + EXPECT_EQ( + 1, test::NumHistogramSamples("WebRTC.Video.DuplicatedPacketsInPercent")); + EXPECT_EQ(1, test::NumHistogramSamples( + "WebRTC.Video.CompleteFramesReceivedPerSecond")); + EXPECT_EQ( + 1, test::NumHistogramSamples("WebRTC.Video.KeyFramesReceivedInPermille")); +} + +TEST_F(TestBasicJitterBuffer, DualPacketFrame) { + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = false; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + 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_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, 2 * size_, false); + + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, 100PacketKeyFrame) { + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = false; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + loop++; + } while (loop < 98); + + // Insert last packet. + ++seq_num_; + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + + CheckOutFrame(frame_out, 100 * size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, 100PacketDeltaFrame) { + // Always start with a complete key frame. + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_FALSE(frame_out == NULL); + jitter_buffer_->ReleaseFrame(frame_out); + + ++seq_num_; + packet_->seqNum = seq_num_; + packet_->markerBit = false; + packet_->frameType = kVideoFrameDelta; + packet_->timestamp += 33 * 90; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + // Insert a packet into a frame. + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + loop++; + } while (loop < 98); + + // Insert the last packet. + ++seq_num_; + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + + CheckOutFrame(frame_out, 100 * size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +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_; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + loop++; + } while (loop < 98); + + // Insert the last packet. + seq_num_--; + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + + CheckOutFrame(frame_out, 100 * size_, false); + + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, FrameReordering2Frames2PacketsEach) { + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = true; + packet_->markerBit = false; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + + EXPECT_TRUE(frame_out == NULL); + + seq_num_++; + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + // 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_; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, 2 * size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, 2 * size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, TestReorderingWithPadding) { + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + + // Send in an initial good packet/frame (Frame A) to start things off. + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out != NULL); + jitter_buffer_->ReleaseFrame(frame_out); + + // Now send in a complete delta frame (Frame C), but with a sequence number + // gap. No pic index either, so no temporal scalability cheating :) + packet_->frameType = kVideoFrameDelta; + // Leave a gap of 2 sequence numbers and two frames. + packet_->seqNum = seq_num_ + 3; + packet_->timestamp = timestamp_ + (66 * 90); + // Still isFirst = marker = true. + // Session should be complete (frame is complete), but there's nothing to + // decode yet. + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out == NULL); + + // Now send in a complete delta frame (Frame B) that is continuous from A, but + // doesn't fill the full gap to C. The rest of the gap is going to be padding. + packet_->seqNum = seq_num_ + 1; + packet_->timestamp = timestamp_ + (33 * 90); + // Still isFirst = marker = true. + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out != NULL); + jitter_buffer_->ReleaseFrame(frame_out); + + // But Frame C isn't continuous yet. + frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out == NULL); + + // Add in the padding. These are empty packets (data length is 0) with no + // marker bit and matching the timestamp of Frame B. + VCMPacket empty_packet(data_, 0, seq_num_ + 2, timestamp_ + (33 * 90), false); + EXPECT_EQ(kOldPacket, + jitter_buffer_->InsertPacket(empty_packet, &retransmitted)); + empty_packet.seqNum += 1; + EXPECT_EQ(kOldPacket, + jitter_buffer_->InsertPacket(empty_packet, &retransmitted)); + + // But now Frame C should be ready! + frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out != NULL); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, DuplicatePackets) { + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + EXPECT_EQ(0, jitter_buffer_->num_packets()); + EXPECT_EQ(0, jitter_buffer_->num_duplicated_packets()); + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + + EXPECT_TRUE(frame_out == NULL); + EXPECT_EQ(1, jitter_buffer_->num_packets()); + EXPECT_EQ(0, jitter_buffer_->num_duplicated_packets()); + + // Insert a packet into a frame. + EXPECT_EQ(kDuplicatePacket, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_EQ(2, jitter_buffer_->num_packets()); + EXPECT_EQ(1, jitter_buffer_->num_duplicated_packets()); + + seq_num_++; + packet_->seqNum = seq_num_; + packet_->markerBit = true; + packet_->isFirstPacket = false; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + ASSERT_TRUE(frame_out != NULL); + CheckOutFrame(frame_out, 2 * size_, false); + + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + EXPECT_EQ(3, jitter_buffer_->num_packets()); + EXPECT_EQ(1, jitter_buffer_->num_duplicated_packets()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, DuplicatePreviousDeltaFramePacket) { + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + jitter_buffer_->SetDecodeErrorMode(kNoErrors); + EXPECT_EQ(0, jitter_buffer_->num_packets()); + EXPECT_EQ(0, jitter_buffer_->num_duplicated_packets()); + + bool retransmitted = false; + // Insert first complete frame. + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + ASSERT_TRUE(frame_out != NULL); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + // Insert 3 delta frames. + for (uint16_t i = 1; i <= 3; ++i) { + packet_->seqNum = seq_num_ + i; + packet_->timestamp = timestamp_ + (i * 33) * 90; + packet_->frameType = kVideoFrameDelta; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_EQ(i + 1, jitter_buffer_->num_packets()); + EXPECT_EQ(0, jitter_buffer_->num_duplicated_packets()); + } + + // Retransmit second delta frame. + packet_->seqNum = seq_num_ + 2; + packet_->timestamp = timestamp_ + 66 * 90; + + EXPECT_EQ(kDuplicatePacket, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + EXPECT_EQ(5, jitter_buffer_->num_packets()); + EXPECT_EQ(1, jitter_buffer_->num_duplicated_packets()); + + // Should be able to decode 3 delta frames, key frame already decoded. + for (size_t i = 0; i < 3; ++i) { + frame_out = DecodeCompleteFrame(); + ASSERT_TRUE(frame_out != NULL); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + } +} + +TEST_F(TestBasicJitterBuffer, TestSkipForwardVp9) { + // Verify that JB skips forward to next base layer frame. + // ------------------------------------------------- + // | 65485 | 65486 | 65487 | 65488 | 65489 | ... + // | pid:5 | pid:6 | pid:7 | pid:8 | pid:9 | ... + // | tid:0 | tid:2 | tid:1 | tid:2 | tid:0 | ... + // | ss | x | x | x | | + // ------------------------------------------------- + // |<----------tl0idx:200--------->|<---tl0idx:201--- + + bool re = false; + packet_->codec = kVideoCodecVP9; + packet_->codecSpecificHeader.codec = kRtpVideoVp9; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->codecSpecificHeader.codecHeader.VP9.flexible_mode = false; + packet_->codecSpecificHeader.codecHeader.VP9.spatial_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.beginning_of_frame = true; + packet_->codecSpecificHeader.codecHeader.VP9.end_of_frame = true; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = false; + + packet_->seqNum = 65485; + packet_->timestamp = 1000; + packet_->frameType = kVideoFrameKey; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 5; + packet_->codecSpecificHeader.codecHeader.VP9.tl0_pic_idx = 200; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.ss_data_available = true; + packet_->codecSpecificHeader.codecHeader.VP9.gof.SetGofInfoVP9( + kTemporalStructureMode3); // kTemporalStructureMode3: 0-2-1-2.. + EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &re)); + + // Insert next temporal layer 0. + packet_->seqNum = 65489; + packet_->timestamp = 13000; + packet_->frameType = kVideoFrameDelta; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 9; + packet_->codecSpecificHeader.codecHeader.VP9.tl0_pic_idx = 201; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.ss_data_available = false; + EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &re)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(1000U, frame_out->TimeStamp()); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + frame_out = DecodeCompleteFrame(); + EXPECT_EQ(13000U, frame_out->TimeStamp()); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, ReorderedVp9SsData_3TlLayers) { + // Verify that frames are updated with SS data when SS packet is reordered. + // -------------------------------- + // | 65486 | 65487 | 65485 |... + // | pid:6 | pid:7 | pid:5 |... + // | tid:2 | tid:1 | tid:0 |... + // | | | ss | + // -------------------------------- + // |<--------tl0idx:200--------->| + + bool re = false; + packet_->codec = kVideoCodecVP9; + packet_->codecSpecificHeader.codec = kRtpVideoVp9; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->codecSpecificHeader.codecHeader.VP9.flexible_mode = false; + packet_->codecSpecificHeader.codecHeader.VP9.spatial_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.beginning_of_frame = true; + packet_->codecSpecificHeader.codecHeader.VP9.end_of_frame = true; + packet_->codecSpecificHeader.codecHeader.VP9.tl0_pic_idx = 200; + + packet_->seqNum = 65486; + packet_->timestamp = 6000; + packet_->frameType = kVideoFrameDelta; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 6; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 2; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = true; + EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &re)); + + packet_->seqNum = 65487; + packet_->timestamp = 9000; + packet_->frameType = kVideoFrameDelta; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 7; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 1; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = true; + EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &re)); + + // Insert first frame with SS data. + packet_->seqNum = 65485; + packet_->timestamp = 3000; + packet_->frameType = kVideoFrameKey; + packet_->width = 352; + packet_->height = 288; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 5; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = false; + packet_->codecSpecificHeader.codecHeader.VP9.ss_data_available = true; + packet_->codecSpecificHeader.codecHeader.VP9.gof.SetGofInfoVP9( + kTemporalStructureMode3); // kTemporalStructureMode3: 0-2-1-2.. + EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &re)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(3000U, frame_out->TimeStamp()); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + EXPECT_EQ(0, frame_out->CodecSpecific()->codecSpecific.VP9.temporal_idx); + EXPECT_FALSE( + frame_out->CodecSpecific()->codecSpecific.VP9.temporal_up_switch); + jitter_buffer_->ReleaseFrame(frame_out); + + frame_out = DecodeCompleteFrame(); + EXPECT_EQ(6000U, frame_out->TimeStamp()); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + EXPECT_EQ(2, frame_out->CodecSpecific()->codecSpecific.VP9.temporal_idx); + EXPECT_TRUE(frame_out->CodecSpecific()->codecSpecific.VP9.temporal_up_switch); + jitter_buffer_->ReleaseFrame(frame_out); + + frame_out = DecodeCompleteFrame(); + EXPECT_EQ(9000U, frame_out->TimeStamp()); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + EXPECT_EQ(1, frame_out->CodecSpecific()->codecSpecific.VP9.temporal_idx); + EXPECT_TRUE(frame_out->CodecSpecific()->codecSpecific.VP9.temporal_up_switch); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, ReorderedVp9SsData_2Tl2SLayers) { + // Verify that frames are updated with SS data when SS packet is reordered. + // ----------------------------------------- + // | 65486 | 65487 | 65485 | 65484 |... + // | pid:6 | pid:6 | pid:5 | pid:5 |... + // | tid:1 | tid:1 | tid:0 | tid:0 |... + // | sid:0 | sid:1 | sid:1 | sid:0 |... + // | t:6000 | t:6000 | t:3000 | t:3000 | + // | | | | ss | + // ----------------------------------------- + // |<-----------tl0idx:200------------>| + + bool re = false; + packet_->codec = kVideoCodecVP9; + packet_->codecSpecificHeader.codec = kRtpVideoVp9; + packet_->codecSpecificHeader.codecHeader.VP9.flexible_mode = false; + packet_->codecSpecificHeader.codecHeader.VP9.beginning_of_frame = true; + packet_->codecSpecificHeader.codecHeader.VP9.end_of_frame = true; + packet_->codecSpecificHeader.codecHeader.VP9.tl0_pic_idx = 200; + + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = 65486; + packet_->timestamp = 6000; + packet_->frameType = kVideoFrameDelta; + packet_->codecSpecificHeader.codecHeader.VP9.spatial_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 6; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 1; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = true; + EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(*packet_, &re)); + + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = 65487; + packet_->frameType = kVideoFrameDelta; + packet_->codecSpecificHeader.codecHeader.VP9.spatial_idx = 1; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 6; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 1; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = true; + EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &re)); + + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = 65485; + packet_->timestamp = 3000; + packet_->frameType = kVideoFrameKey; + packet_->codecSpecificHeader.codecHeader.VP9.spatial_idx = 1; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 5; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = false; + EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(*packet_, &re)); + + // Insert first frame with SS data. + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = 65484; + packet_->frameType = kVideoFrameKey; + packet_->width = 352; + packet_->height = 288; + packet_->codecSpecificHeader.codecHeader.VP9.spatial_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.picture_id = 5; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_idx = 0; + packet_->codecSpecificHeader.codecHeader.VP9.temporal_up_switch = false; + packet_->codecSpecificHeader.codecHeader.VP9.ss_data_available = true; + packet_->codecSpecificHeader.codecHeader.VP9.gof.SetGofInfoVP9( + kTemporalStructureMode2); // kTemporalStructureMode3: 0-1-0-1.. + EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &re)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(3000U, frame_out->TimeStamp()); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + EXPECT_EQ(0, frame_out->CodecSpecific()->codecSpecific.VP9.temporal_idx); + EXPECT_FALSE( + frame_out->CodecSpecific()->codecSpecific.VP9.temporal_up_switch); + jitter_buffer_->ReleaseFrame(frame_out); + + frame_out = DecodeCompleteFrame(); + EXPECT_EQ(6000U, frame_out->TimeStamp()); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + EXPECT_EQ(1, frame_out->CodecSpecific()->codecSpecific.VP9.temporal_idx); + EXPECT_TRUE(frame_out->CodecSpecific()->codecSpecific.VP9.temporal_up_switch); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, H264InsertStartCode) { + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + packet_->insertStartCode = true; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, size_ * 2 + 4 * 2, true); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +// Test threshold conditions of decodable state. +TEST_F(TestBasicJitterBuffer, PacketLossWithSelectiveErrorsThresholdCheck) { + jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors); + // Always start with a key frame. Use 10 packets to test Decodable State + // boundaries. + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + uint32_t timestamp = 0; + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + packet_->isFirstPacket = false; + for (int i = 1; i < 9; ++i) { + packet_->seqNum++; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + } + + // last packet + packet_->markerBit = true; + packet_->seqNum++; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, 10 * size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + // An incomplete frame can only be decoded once a subsequent frame has begun + // to arrive. Insert packet in distant frame for this purpose. + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum += 100; + packet_->timestamp += 33 * 90 * 8; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + // Insert second frame + packet_->seqNum -= 99; + packet_->timestamp -= 33 * 90 * 7; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + packet_->isFirstPacket = false; + for (int i = 1; i < 8; ++i) { + packet_->seqNum++; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + } + + packet_->seqNum++; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + frame_out = DecodeIncompleteFrame(); + ASSERT_FALSE(NULL == frame_out); + CheckOutFrame(frame_out, 9 * size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + packet_->markerBit = true; + packet_->seqNum++; + EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); +} + +// Make sure first packet is present before a frame can be decoded. +TEST_F(TestBasicJitterBuffer, PacketLossWithSelectiveErrorsIncompleteKey) { + jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors); + // Always start with a key frame. + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + // An incomplete frame can only be decoded once a subsequent frame has begun + // to arrive. Insert packet in distant frame for this purpose. + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = false; + packet_->markerBit = false; + packet_->seqNum += 100; + packet_->timestamp += 33 * 90 * 8; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + uint32_t timestamp; + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + // Insert second frame - an incomplete key frame. + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->seqNum -= 99; + packet_->timestamp -= 33 * 90 * 7; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + // Insert a few more packets. Make sure we're waiting for the key frame to be + // complete. + packet_->isFirstPacket = false; + for (int i = 1; i < 5; ++i) { + packet_->seqNum++; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + } + + // Complete key frame. + packet_->markerBit = true; + packet_->seqNum++; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, 6 * size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +// Make sure first packet is present before a frame can be decoded. +TEST_F(TestBasicJitterBuffer, PacketLossWithSelectiveErrorsMissingFirstPacket) { + jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors); + // Always start with a key frame. + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + // An incomplete frame can only be decoded once a subsequent frame has begun + // to arrive. Insert packet in distant frame for this purpose. + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = false; + packet_->markerBit = false; + packet_->seqNum += 100; + packet_->timestamp += 33 * 90 * 8; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + uint32_t timestamp; + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + // Insert second frame with the first packet missing. Make sure we're waiting + // for the key frame to be complete. + packet_->seqNum -= 98; + packet_->timestamp -= 33 * 90 * 7; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + for (int i = 0; i < 5; ++i) { + packet_->seqNum++; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + } + + // Add first packet. Frame should now be decodable, but incomplete. + packet_->isFirstPacket = true; + packet_->seqNum -= 6; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, ×tamp)); + EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp)); + + frame_out = DecodeIncompleteFrame(); + CheckOutFrame(frame_out, 7 * size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, DiscontinuousStreamWhenDecodingWithErrors) { + // Will use one packet per frame. + jitter_buffer_->SetDecodeErrorMode(kWithErrors); + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + uint32_t next_timestamp; + EXPECT_TRUE(jitter_buffer_->NextCompleteTimestamp(0, &next_timestamp)); + EXPECT_EQ(packet_->timestamp, next_timestamp); + VCMEncodedFrame* frame = jitter_buffer_->ExtractAndSetDecode(next_timestamp); + EXPECT_TRUE(frame != NULL); + jitter_buffer_->ReleaseFrame(frame); + + // Drop a complete frame. + timestamp_ += 2 * 33 * 90; + seq_num_ += 2; + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + // Insert a packet (so the previous one will be released). + timestamp_ += 33 * 90; + seq_num_ += 2; + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = true; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + EXPECT_FALSE(jitter_buffer_->NextCompleteTimestamp(0, &next_timestamp)); + EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(&next_timestamp)); + EXPECT_EQ(packet_->timestamp - 33 * 90, next_timestamp); +} + +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_->SetDecodeErrorMode(kWithErrors); + 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; + + bool retransmitted = false; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + 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; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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; + + EXPECT_EQ(jitter_buffer_->InsertPacket(*packet_, &retransmitted), + kDecodableSession); + + // Insert an empty (non-media) packet. + seq_num_++; + packet_->isFirstPacket = false; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + packet_->completeNALU = kNaluEnd; + packet_->frameType = kEmptyFrame; + + EXPECT_EQ(jitter_buffer_->InsertPacket(*packet_, &retransmitted), + kDecodableSession); + frame_out = DecodeIncompleteFrame(); + + // One of the packets has been discarded by the jitter buffer. + // Last frame can't be extracted yet. + if (i < 10) { + 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); + } + + // 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; + + EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + packet_->timestamp = timestamp_ - 500; + + EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + packet_->timestamp = timestamp_ - 100; + + EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + + EXPECT_TRUE(frame_out == NULL); + + loop++; + } while (loop < 98); + + seq_num_++; + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + + CheckOutFrame(frame_out, 100 * size_, false); + + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +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_; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + 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_; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, 100 * size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +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_; + + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(3000u, frame_out->TimeStamp()); + 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_; + + EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); +} + +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_; + + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(timestamp_, frame_out->TimeStamp()); + + 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_; + + // This timestamp is old. + EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); +} + +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_; + + bool retransmitted = false; + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out == NULL); + + seq_num_++; + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + 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_; + + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out == NULL); + + seq_num_++; + packet_->isFirstPacket = false; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + CheckOutFrame(frame_out, 2 * size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, 2FrameWithTimestampWrap) { + // ------- ------- + // | 1 | | 2 | + // ------- ------- + // t = 0xffffff00 t = 2700 + + timestamp_ = 0xffffff00; + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->timestamp = timestamp_; + + bool retransmitted = false; + // Insert first frame (session will be complete). + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + // Insert next frame. + seq_num_++; + timestamp_ = 2700; + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(0xffffff00, frame_out->TimeStamp()); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + VCMEncodedFrame* frame_out2 = DecodeCompleteFrame(); + EXPECT_EQ(2700u, frame_out2->TimeStamp()); + CheckOutFrame(frame_out2, size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out2->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out2); +} + +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_; + + bool retransmitted = false; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + // Insert second frame + seq_num_--; + timestamp_ = 0xffffff00; + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(0xffffff00, frame_out->TimeStamp()); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); + + VCMEncodedFrame* frame_out2 = DecodeCompleteFrame(); + EXPECT_EQ(2700u, frame_out2->TimeStamp()); + CheckOutFrame(frame_out2, size_, false); + EXPECT_EQ(kVideoFrameDelta, frame_out2->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out2); +} + +TEST_F(TestBasicJitterBuffer, DeltaFrameWithMoreThanMaxNumberOfPackets) { + int loop = 0; + bool firstPacket = true; + bool retransmitted = false; + // Insert kMaxPacketsInJitterBuffer into frame. + do { + seq_num_++; + packet_->isFirstPacket = false; + packet_->markerBit = false; + packet_->seqNum = seq_num_; + + if (firstPacket) { + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + firstPacket = false; + } else { + EXPECT_EQ(kIncomplete, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + } + + 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_; + + // Insert the packet -> frame recycled. + EXPECT_EQ(kSizeError, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + 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----->| + + // Make sure the jitter doesn't request a keyframe after too much non- + // decodable frames. + jitter_buffer_->SetNackMode(kNack, -1, -1); + jitter_buffer_->SetNackSettings(kMaxNumberOfFrames, kMaxNumberOfFrames, 0); + + int loop = 0; + seq_num_ = 65485; + uint32_t first_key_frame_timestamp = 0; + bool retransmitted = false; + // 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_; + + if (loop == 50) { + first_key_frame_timestamp = packet_->timestamp; + packet_->frameType = kVideoFrameKey; + } + + // Insert frame. + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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. + EXPECT_EQ(kFlushIndicator, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_EQ(first_key_frame_timestamp, frame_out->TimeStamp()); + CheckOutFrame(frame_out, size_, false); + EXPECT_EQ(kVideoFrameKey, frame_out->FrameType()); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestBasicJitterBuffer, EmptyLastFrame) { + jitter_buffer_->SetDecodeErrorMode(kWithErrors); + 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; + bool retransmitted = false; + 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 = kEmptyFrame; + + EXPECT_EQ(kNoError, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* testFrame = DecodeIncompleteFrame(); + // Timestamp should never be the last TS inserted. + if (testFrame != NULL) { + EXPECT_TRUE(testFrame->TimeStamp() < timestamp_); + jitter_buffer_->ReleaseFrame(testFrame); + } + } +} + +TEST_F(TestBasicJitterBuffer, H264IncompleteNalu) { + jitter_buffer_->SetNackMode(kNoNack, -1, -1); + jitter_buffer_->SetDecodeErrorMode(kWithErrors); + ++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; + bool retransmitted = false; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + seq_num_ += 2; // Skip one packet. + packet_->seqNum = seq_num_; + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = false; + packet_->completeNALU = kNaluIncomplete; + packet_->markerBit = false; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + seq_num_++; + packet_->seqNum = seq_num_; + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = false; + packet_->completeNALU = kNaluEnd; + packet_->markerBit = false; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + seq_num_++; + packet_->seqNum = seq_num_; + packet_->completeNALU = kNaluComplete; + packet_->markerBit = true; // Last packet. + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + // 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; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + 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. + 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; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + 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(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + 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(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + insertedLength += packet_->sizeBytes; // This packet should be decoded. + seq_num_++; + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = false; + packet_->completeNALU = kNaluStart; + packet_->markerBit = false; + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + // 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(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + // 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. + CheckOutFrame(frame_out, insertedLength, false); + jitter_buffer_->ReleaseFrame(frame_out); + + // Test to insert empty packet. + seq_num_++; + 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; + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(emptypacket, &retransmitted)); + // This packet should not be decoded because it is an incomplete NAL if it + // is the last. + + // Will be sent to the decoder, as a packet belonging to a subsequent frame + // has arrived. + frame_out = DecodeIncompleteFrame(); + EXPECT_TRUE(frame_out != NULL); + jitter_buffer_->ReleaseFrame(frame_out); + + // Test that a frame can include an empty packet. + seq_num_++; + timestamp_ += 33 * 90; + + packet_->seqNum = seq_num_; + packet_->timestamp = timestamp_; + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->completeNALU = kNaluComplete; + packet_->markerBit = false; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + seq_num_++; + 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(emptypacket, &retransmitted)); + + frame_out = DecodeCompleteFrame(); + // Only last NALU is complete + CheckOutFrame(frame_out, packet_->sizeBytes, false); + jitter_buffer_->ReleaseFrame(frame_out); +} + +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_->SetDecodeErrorMode(kWithErrors); + // Start with a complete key frame - insert and decode. + packet_->frameType = kVideoFrameKey; + packet_->isFirstPacket = true; + packet_->markerBit = true; + bool retransmitted = false; + + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + VCMEncodedFrame* frame_out = DecodeCompleteFrame(); + EXPECT_TRUE(frame_out != NULL); + jitter_buffer_->ReleaseFrame(frame_out); + + packet_->seqNum += 2; + packet_->timestamp += 33 * 90; + packet_->frameType = kVideoFrameDelta; + packet_->isFirstPacket = false; + packet_->markerBit = false; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeIncompleteFrame(); + EXPECT_TRUE(frame_out == NULL); + + packet_->seqNum += 2; + packet_->timestamp += 33 * 90; + packet_->isFirstPacket = true; + + EXPECT_EQ(kDecodableSession, + jitter_buffer_->InsertPacket(*packet_, &retransmitted)); + + frame_out = DecodeIncompleteFrame(); + CheckOutFrame(frame_out, packet_->sizeBytes, false); + jitter_buffer_->ReleaseFrame(frame_out); +} + +TEST_F(TestRunningJitterBuffer, Full) { + // Make sure the jitter doesn't request a keyframe after too much non- + // decodable frames. + jitter_buffer_->SetNackMode(kNack, -1, -1); + jitter_buffer_->SetNackSettings(kMaxNumberOfFrames, kMaxNumberOfFrames, 0); + // Insert a key frame and decode it. + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); + EXPECT_TRUE(DecodeCompleteFrame()); + DropFrame(1); + // Fill the jitter buffer. + EXPECT_GE(InsertFrames(kMaxNumberOfFrames, kVideoFrameDelta), kNoError); + // Make sure we can't decode these frames. + 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. + EXPECT_EQ(kFlushIndicator, InsertFrame(kVideoFrameDelta)); + EXPECT_FALSE(DecodeCompleteFrame()); +} + +TEST_F(TestRunningJitterBuffer, EmptyPackets) { + // Make sure a frame can get complete even though empty packets are missing. + stream_generator_->GenerateFrame(kVideoFrameKey, 3, 3, + clock_->TimeInMilliseconds()); + bool request_key_frame = false; + // Insert empty packet. + EXPECT_EQ(kNoError, InsertPacketAndPop(4)); + EXPECT_FALSE(request_key_frame); + // Insert 3 media packets. + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); + EXPECT_EQ(kCompleteSession, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); + // Insert empty packet. + EXPECT_EQ(kCompleteSession, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); +} + +TEST_F(TestRunningJitterBuffer, StatisticsTest) { + FrameCounts frame_stats(jitter_buffer_->FrameStatistics()); + EXPECT_EQ(0, frame_stats.delta_frames); + EXPECT_EQ(0, frame_stats.key_frames); + + uint32_t framerate = 0; + uint32_t bitrate = 0; + jitter_buffer_->IncomingRateStatistics(&framerate, &bitrate); + EXPECT_EQ(0u, framerate); + EXPECT_EQ(0u, bitrate); + + // Insert a couple of key and delta frames. + InsertFrame(kVideoFrameKey); + InsertFrame(kVideoFrameDelta); + InsertFrame(kVideoFrameDelta); + InsertFrame(kVideoFrameKey); + InsertFrame(kVideoFrameDelta); + // Decode some of them to make sure the statistics doesn't depend on frames + // being decoded. + EXPECT_TRUE(DecodeCompleteFrame()); + EXPECT_TRUE(DecodeCompleteFrame()); + frame_stats = jitter_buffer_->FrameStatistics(); + EXPECT_EQ(3, frame_stats.delta_frames); + EXPECT_EQ(2, frame_stats.key_frames); + + // Insert 20 more frames to get estimates of bitrate and framerate over + // 1 second. + for (int i = 0; i < 20; ++i) { + InsertFrame(kVideoFrameDelta); + } + jitter_buffer_->IncomingRateStatistics(&framerate, &bitrate); + // TODO(holmer): The current implementation returns the average of the last + // two framerate calculations, which is why it takes two calls to reach the + // actual framerate. This should be fixed. + EXPECT_EQ(kDefaultFrameRate / 2u, framerate); + EXPECT_EQ(kDefaultBitrateKbps, bitrate); + // Insert 25 more frames to get estimates of bitrate and framerate over + // 2 seconds. + for (int i = 0; i < 25; ++i) { + InsertFrame(kVideoFrameDelta); + } + jitter_buffer_->IncomingRateStatistics(&framerate, &bitrate); + EXPECT_EQ(kDefaultFrameRate, framerate); + EXPECT_EQ(kDefaultBitrateKbps, bitrate); +} + +TEST_F(TestRunningJitterBuffer, SkipToKeyFrame) { + // Insert delta frames. + EXPECT_GE(InsertFrames(5, kVideoFrameDelta), kNoError); + // Can't decode without a key frame. + EXPECT_FALSE(DecodeCompleteFrame()); + InsertFrame(kVideoFrameKey); + // Skip to the next key frame. + EXPECT_TRUE(DecodeCompleteFrame()); +} + +TEST_F(TestRunningJitterBuffer, DontSkipToKeyFrameIfDecodable) { + InsertFrame(kVideoFrameKey); + EXPECT_TRUE(DecodeCompleteFrame()); + const int kNumDeltaFrames = 5; + EXPECT_GE(InsertFrames(kNumDeltaFrames, kVideoFrameDelta), kNoError); + InsertFrame(kVideoFrameKey); + for (int i = 0; i < kNumDeltaFrames + 1; ++i) { + EXPECT_TRUE(DecodeCompleteFrame()); + } +} + +TEST_F(TestRunningJitterBuffer, KeyDeltaKeyDelta) { + InsertFrame(kVideoFrameKey); + EXPECT_TRUE(DecodeCompleteFrame()); + const int kNumDeltaFrames = 5; + EXPECT_GE(InsertFrames(kNumDeltaFrames, kVideoFrameDelta), kNoError); + InsertFrame(kVideoFrameKey); + EXPECT_GE(InsertFrames(kNumDeltaFrames, kVideoFrameDelta), kNoError); + InsertFrame(kVideoFrameKey); + for (int i = 0; i < 2 * (kNumDeltaFrames + 1); ++i) { + EXPECT_TRUE(DecodeCompleteFrame()); + } +} + +TEST_F(TestRunningJitterBuffer, TwoPacketsNonContinuous) { + InsertFrame(kVideoFrameKey); + EXPECT_TRUE(DecodeCompleteFrame()); + stream_generator_->GenerateFrame(kVideoFrameDelta, 1, 0, + clock_->TimeInMilliseconds()); + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + stream_generator_->GenerateFrame(kVideoFrameDelta, 2, 0, + clock_->TimeInMilliseconds()); + EXPECT_EQ(kIncomplete, InsertPacketAndPop(1)); + EXPECT_EQ(kCompleteSession, InsertPacketAndPop(1)); + EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_EQ(kCompleteSession, InsertPacketAndPop(0)); + EXPECT_TRUE(DecodeCompleteFrame()); + EXPECT_TRUE(DecodeCompleteFrame()); +} + +TEST_F(TestJitterBufferNack, EmptyPackets) { + // Make sure empty packets doesn't clog the jitter buffer. + jitter_buffer_->SetNackMode(kNack, media_optimization::kLowRttNackMs, -1); + EXPECT_GE(InsertFrames(kMaxNumberOfFrames, kEmptyFrame), kNoError); + InsertFrame(kVideoFrameKey); + EXPECT_TRUE(DecodeCompleteFrame()); +} + +TEST_F(TestJitterBufferNack, NackTooOldPackets) { + // Insert a key frame and decode it. + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); + EXPECT_TRUE(DecodeCompleteFrame()); + + // Drop one frame and insert |kNackHistoryLength| to trigger NACKing a too + // old packet. + DropFrame(1); + // Insert a frame which should trigger a recycle until the next key frame. + EXPECT_EQ(kFlushIndicator, + InsertFrames(oldest_packet_to_nack_ + 1, kVideoFrameDelta)); + EXPECT_FALSE(DecodeCompleteFrame()); + + bool request_key_frame = false; + std::vector<uint16_t> nack_list = + jitter_buffer_->GetNackList(&request_key_frame); + // No key frame will be requested since the jitter buffer is empty. + EXPECT_FALSE(request_key_frame); + EXPECT_EQ(0u, nack_list.size()); + + EXPECT_GE(InsertFrame(kVideoFrameDelta), kNoError); + // Waiting for a key frame. + EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_FALSE(DecodeIncompleteFrame()); + + // The next complete continuous frame isn't a key frame, but we're waiting + // for one. + EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); + // Skipping ahead to the key frame. + EXPECT_TRUE(DecodeCompleteFrame()); +} + +TEST_F(TestJitterBufferNack, NackLargeJitterBuffer) { + // Insert a key frame and decode it. + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); + EXPECT_TRUE(DecodeCompleteFrame()); + + // Insert a frame which should trigger a recycle until the next key frame. + EXPECT_GE(InsertFrames(oldest_packet_to_nack_, kVideoFrameDelta), kNoError); + + bool request_key_frame = false; + std::vector<uint16_t> nack_list = + jitter_buffer_->GetNackList(&request_key_frame); + // Verify that the jitter buffer does not request a key frame. + EXPECT_FALSE(request_key_frame); + // Verify that no packets are NACKed. + EXPECT_EQ(0u, nack_list.size()); + // Verify that we can decode the next frame. + EXPECT_TRUE(DecodeCompleteFrame()); +} + +TEST_F(TestJitterBufferNack, NackListFull) { + // Insert a key frame and decode it. + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); + EXPECT_TRUE(DecodeCompleteFrame()); + + // Generate and drop |kNackHistoryLength| packets to fill the NACK list. + DropFrame(max_nack_list_size_ + 1); + // Insert a frame which should trigger a recycle until the next key frame. + EXPECT_EQ(kFlushIndicator, InsertFrame(kVideoFrameDelta)); + EXPECT_FALSE(DecodeCompleteFrame()); + + bool request_key_frame = false; + jitter_buffer_->GetNackList(&request_key_frame); + // The jitter buffer is empty, so we won't request key frames until we get a + // packet. + EXPECT_FALSE(request_key_frame); + + EXPECT_GE(InsertFrame(kVideoFrameDelta), kNoError); + // Now we have a packet in the jitter buffer, a key frame will be requested + // since it's not a key frame. + jitter_buffer_->GetNackList(&request_key_frame); + // The jitter buffer is empty, so we won't request key frames until we get a + // packet. + EXPECT_TRUE(request_key_frame); + // The next complete continuous frame isn't a key frame, but we're waiting + // for one. + EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_FALSE(DecodeIncompleteFrame()); + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); + // Skipping ahead to the key frame. + EXPECT_TRUE(DecodeCompleteFrame()); +} + +TEST_F(TestJitterBufferNack, NoNackListReturnedBeforeFirstDecode) { + DropFrame(10); + // Insert a frame and try to generate a NACK list. Shouldn't get one. + EXPECT_GE(InsertFrame(kVideoFrameDelta), kNoError); + bool request_key_frame = false; + std::vector<uint16_t> nack_list = + jitter_buffer_->GetNackList(&request_key_frame); + // No list generated, and a key frame request is signaled. + EXPECT_EQ(0u, nack_list.size()); + EXPECT_TRUE(request_key_frame); +} + +TEST_F(TestJitterBufferNack, NackListBuiltBeforeFirstDecode) { + stream_generator_->Init(0, clock_->TimeInMilliseconds()); + InsertFrame(kVideoFrameKey); + stream_generator_->GenerateFrame(kVideoFrameDelta, 2, 0, + clock_->TimeInMilliseconds()); + stream_generator_->NextPacket(NULL); // Drop packet. + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + EXPECT_TRUE(DecodeCompleteFrame()); + bool extended = false; + std::vector<uint16_t> nack_list = jitter_buffer_->GetNackList(&extended); + EXPECT_EQ(1u, nack_list.size()); +} + +TEST_F(TestJitterBufferNack, VerifyRetransmittedFlag) { + stream_generator_->Init(0, clock_->TimeInMilliseconds()); + stream_generator_->GenerateFrame(kVideoFrameKey, 3, 0, + clock_->TimeInMilliseconds()); + VCMPacket packet; + stream_generator_->PopPacket(&packet, 0); + bool retransmitted = false; + EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(packet, &retransmitted)); + EXPECT_FALSE(retransmitted); + // Drop second packet. + stream_generator_->PopPacket(&packet, 1); + EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(packet, &retransmitted)); + EXPECT_FALSE(retransmitted); + EXPECT_FALSE(DecodeCompleteFrame()); + bool extended = false; + std::vector<uint16_t> nack_list = jitter_buffer_->GetNackList(&extended); + EXPECT_EQ(1u, nack_list.size()); + stream_generator_->PopPacket(&packet, 0); + EXPECT_EQ(packet.seqNum, nack_list[0]); + EXPECT_EQ(kCompleteSession, + jitter_buffer_->InsertPacket(packet, &retransmitted)); + EXPECT_TRUE(retransmitted); + EXPECT_TRUE(DecodeCompleteFrame()); +} + +TEST_F(TestJitterBufferNack, UseNackToRecoverFirstKeyFrame) { + stream_generator_->Init(0, clock_->TimeInMilliseconds()); + stream_generator_->GenerateFrame(kVideoFrameKey, 3, 0, + clock_->TimeInMilliseconds()); + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + // Drop second packet. + EXPECT_EQ(kIncomplete, InsertPacketAndPop(1)); + EXPECT_FALSE(DecodeCompleteFrame()); + bool extended = false; + std::vector<uint16_t> nack_list = jitter_buffer_->GetNackList(&extended); + EXPECT_EQ(1u, nack_list.size()); + VCMPacket packet; + stream_generator_->GetPacket(&packet, 0); + EXPECT_EQ(packet.seqNum, nack_list[0]); +} + +TEST_F(TestJitterBufferNack, UseNackToRecoverFirstKeyFrameSecondInQueue) { + VCMPacket packet; + stream_generator_->Init(0, clock_->TimeInMilliseconds()); + // First frame is delta. + stream_generator_->GenerateFrame(kVideoFrameDelta, 3, 0, + clock_->TimeInMilliseconds()); + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + // Drop second packet in frame. + ASSERT_TRUE(stream_generator_->PopPacket(&packet, 0)); + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + // Second frame is key. + stream_generator_->GenerateFrame(kVideoFrameKey, 3, 0, + clock_->TimeInMilliseconds() + 10); + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + // Drop second packet in frame. + EXPECT_EQ(kIncomplete, InsertPacketAndPop(1)); + EXPECT_FALSE(DecodeCompleteFrame()); + bool extended = false; + std::vector<uint16_t> nack_list = jitter_buffer_->GetNackList(&extended); + EXPECT_EQ(1u, nack_list.size()); + stream_generator_->GetPacket(&packet, 0); + EXPECT_EQ(packet.seqNum, nack_list[0]); +} + +TEST_F(TestJitterBufferNack, NormalOperation) { + EXPECT_EQ(kNack, jitter_buffer_->nack_mode()); + jitter_buffer_->SetDecodeErrorMode(kWithErrors); + + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); + EXPECT_TRUE(DecodeIncompleteFrame()); + + // ---------------------------------------------------------------- + // | 1 | 2 | .. | 8 | 9 | x | 11 | 12 | .. | 19 | x | 21 | .. | 100 | + // ---------------------------------------------------------------- + stream_generator_->GenerateFrame(kVideoFrameKey, 100, 0, + clock_->TimeInMilliseconds()); + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + EXPECT_EQ(kDecodableSession, InsertPacketAndPop(0)); + // Verify that the frame is incomplete. + EXPECT_FALSE(DecodeCompleteFrame()); + while (stream_generator_->PacketsRemaining() > 1) { + if (stream_generator_->NextSequenceNumber() % 10 != 0) { + EXPECT_EQ(kDecodableSession, InsertPacketAndPop(0)); + } else { + stream_generator_->NextPacket(NULL); // Drop packet + } + } + EXPECT_EQ(kDecodableSession, InsertPacketAndPop(0)); + EXPECT_EQ(0, stream_generator_->PacketsRemaining()); + EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_FALSE(DecodeIncompleteFrame()); + bool request_key_frame = false; + std::vector<uint16_t> nack_list = + jitter_buffer_->GetNackList(&request_key_frame); + // Verify the NACK list. + const size_t kExpectedNackSize = 9; + ASSERT_EQ(kExpectedNackSize, nack_list.size()); + for (size_t i = 0; i < nack_list.size(); ++i) + EXPECT_EQ((1 + i) * 10, nack_list[i]); +} + +TEST_F(TestJitterBufferNack, NormalOperationWrap) { + bool request_key_frame = false; + // ------- ------------------------------------------------------------ + // | 65532 | | 65533 | 65534 | 65535 | x | 1 | .. | 9 | x | 11 |.....| 96 | + // ------- ------------------------------------------------------------ + stream_generator_->Init(65532, clock_->TimeInMilliseconds()); + InsertFrame(kVideoFrameKey); + EXPECT_FALSE(request_key_frame); + EXPECT_TRUE(DecodeCompleteFrame()); + stream_generator_->GenerateFrame(kVideoFrameDelta, 100, 0, + clock_->TimeInMilliseconds()); + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + while (stream_generator_->PacketsRemaining() > 1) { + if (stream_generator_->NextSequenceNumber() % 10 != 0) { + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); + } else { + stream_generator_->NextPacket(NULL); // Drop packet + } + } + EXPECT_EQ(kIncomplete, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); + EXPECT_EQ(0, stream_generator_->PacketsRemaining()); + EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_FALSE(DecodeCompleteFrame()); + bool extended = false; + std::vector<uint16_t> nack_list = jitter_buffer_->GetNackList(&extended); + // Verify the NACK list. + const size_t kExpectedNackSize = 10; + ASSERT_EQ(kExpectedNackSize, nack_list.size()); + for (size_t i = 0; i < nack_list.size(); ++i) + EXPECT_EQ(i * 10, nack_list[i]); +} + +TEST_F(TestJitterBufferNack, NormalOperationWrap2) { + bool request_key_frame = false; + // ----------------------------------- + // | 65532 | 65533 | 65534 | x | 0 | 1 | + // ----------------------------------- + stream_generator_->Init(65532, clock_->TimeInMilliseconds()); + InsertFrame(kVideoFrameKey); + EXPECT_FALSE(request_key_frame); + EXPECT_TRUE(DecodeCompleteFrame()); + stream_generator_->GenerateFrame(kVideoFrameDelta, 1, 0, + clock_->TimeInMilliseconds()); + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + for (int i = 0; i < 5; ++i) { + if (stream_generator_->NextSequenceNumber() != 65535) { + EXPECT_EQ(kCompleteSession, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); + } else { + stream_generator_->NextPacket(NULL); // Drop packet + } + stream_generator_->GenerateFrame(kVideoFrameDelta, 1, 0, + clock_->TimeInMilliseconds()); + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + } + EXPECT_EQ(kCompleteSession, InsertPacketAndPop(0)); + EXPECT_FALSE(request_key_frame); + bool extended = false; + std::vector<uint16_t> nack_list = jitter_buffer_->GetNackList(&extended); + // Verify the NACK list. + ASSERT_EQ(1u, nack_list.size()); + EXPECT_EQ(65535, nack_list[0]); +} + +TEST_F(TestJitterBufferNack, ResetByFutureKeyFrameDoesntError) { + stream_generator_->Init(0, clock_->TimeInMilliseconds()); + InsertFrame(kVideoFrameKey); + EXPECT_TRUE(DecodeCompleteFrame()); + bool extended = false; + std::vector<uint16_t> nack_list = jitter_buffer_->GetNackList(&extended); + EXPECT_EQ(0u, nack_list.size()); + + // Far-into-the-future video frame, could be caused by resetting the encoder + // or otherwise restarting. This should not fail when error when the packet is + // a keyframe, even if all of the nack list needs to be flushed. + stream_generator_->Init(10000, clock_->TimeInMilliseconds()); + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + InsertFrame(kVideoFrameKey); + EXPECT_TRUE(DecodeCompleteFrame()); + nack_list = jitter_buffer_->GetNackList(&extended); + EXPECT_EQ(0u, nack_list.size()); + + // Stream should be decodable from this point. + clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs); + InsertFrame(kVideoFrameDelta); + EXPECT_TRUE(DecodeCompleteFrame()); + nack_list = jitter_buffer_->GetNackList(&extended); + EXPECT_EQ(0u, nack_list.size()); +} + +} // namespace webrtc |