| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/test/simple_test_tick_clock.h" |
| #include "media/cast/pacing/paced_sender.h" |
| #include "media/cast/test/fake_task_runner.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| |
| namespace media { |
| namespace cast { |
| |
| using testing::_; |
| |
| static const uint8 kValue = 123; |
| static const size_t kSize1 = 100; |
| static const size_t kSize2 = 101; |
| static const size_t kSize3 = 102; |
| static const size_t kSize4 = 103; |
| static const size_t kNackSize = 104; |
| static const int64 kStartMillisecond = GG_INT64_C(12345678900000); |
| |
| class TestPacketSender : public PacketSender { |
| public: |
| virtual bool SendPackets(const PacketList& packets) OVERRIDE { |
| PacketList::const_iterator it = packets.begin(); |
| for (; it != packets.end(); ++it) { |
| EXPECT_FALSE(expected_packet_size_.empty()); |
| size_t expected_packet_size = expected_packet_size_.front(); |
| expected_packet_size_.pop_front(); |
| EXPECT_EQ(expected_packet_size, it->size()); |
| } |
| return true; |
| } |
| |
| virtual bool SendPacket(const Packet& packet) OVERRIDE { |
| return true; |
| } |
| |
| void AddExpectedSize(int expected_packet_size, int repeat_count) { |
| for (int i = 0; i < repeat_count; ++i) { |
| expected_packet_size_.push_back(expected_packet_size); |
| } |
| } |
| |
| private: |
| std::list<int> expected_packet_size_; |
| }; |
| |
| class PacedSenderTest : public ::testing::Test { |
| protected: |
| PacedSenderTest() { |
| testing_clock_.Advance( |
| base::TimeDelta::FromMilliseconds(kStartMillisecond)); |
| } |
| |
| virtual ~PacedSenderTest() {} |
| |
| virtual void SetUp() { |
| task_runner_ = new test::FakeTaskRunner(&testing_clock_); |
| cast_environment_ = new CastEnvironment(&testing_clock_, task_runner_, |
| task_runner_, task_runner_, task_runner_, task_runner_, |
| GetDefaultCastLoggingConfig()); |
| paced_sender_.reset(new PacedSender(cast_environment_, &mock_transport_)); |
| } |
| |
| PacketList CreatePacketList(size_t packet_size, int num_of_packets_in_frame) { |
| PacketList packets; |
| for (int i = 0; i < num_of_packets_in_frame; ++i) { |
| packets.push_back(Packet(packet_size, kValue)); |
| } |
| return packets; |
| } |
| |
| base::SimpleTestTickClock testing_clock_; |
| TestPacketSender mock_transport_; |
| scoped_refptr<test::FakeTaskRunner> task_runner_; |
| scoped_ptr<PacedSender> paced_sender_; |
| scoped_refptr<CastEnvironment> cast_environment_; |
| }; |
| |
| TEST_F(PacedSenderTest, PassThroughRtcp) { |
| mock_transport_.AddExpectedSize(kSize1, 1); |
| PacketList packets = CreatePacketList(kSize1, 1); |
| |
| EXPECT_TRUE(paced_sender_->SendPackets(packets)); |
| EXPECT_TRUE(paced_sender_->ResendPackets(packets)); |
| |
| mock_transport_.AddExpectedSize(kSize2, 1); |
| EXPECT_TRUE(paced_sender_->SendRtcpPacket(Packet(kSize2, kValue))); |
| } |
| |
| TEST_F(PacedSenderTest, BasicPace) { |
| int num_of_packets = 9; |
| PacketList packets = CreatePacketList(kSize1, num_of_packets); |
| |
| mock_transport_.AddExpectedSize(kSize1, 3); |
| EXPECT_TRUE(paced_sender_->SendPackets(packets)); |
| |
| // Check that we get the next burst. |
| mock_transport_.AddExpectedSize(kSize1, 3); |
| |
| base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(10); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // If we call process too early make sure we don't send any packets. |
| timeout = base::TimeDelta::FromMilliseconds(5); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // Check that we get the next burst. |
| mock_transport_.AddExpectedSize(kSize1, 3); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // Check that we don't get any more packets. |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| } |
| |
| TEST_F(PacedSenderTest, PaceWithNack) { |
| // Testing what happen when we get multiple NACK requests for a fully lost |
| // frames just as we sent the first packets in a frame. |
| int num_of_packets_in_frame = 9; |
| int num_of_packets_in_nack = 9; |
| |
| PacketList first_frame_packets = |
| CreatePacketList(kSize1, num_of_packets_in_frame); |
| |
| PacketList second_frame_packets = |
| CreatePacketList(kSize2, num_of_packets_in_frame); |
| |
| PacketList nack_packets = |
| CreatePacketList(kNackSize, num_of_packets_in_nack); |
| |
| // Check that the first burst of the frame go out on the wire. |
| mock_transport_.AddExpectedSize(kSize1, 3); |
| EXPECT_TRUE(paced_sender_->SendPackets(first_frame_packets)); |
| |
| // Add first NACK request. |
| EXPECT_TRUE(paced_sender_->ResendPackets(nack_packets)); |
| |
| // Check that we get the first NACK burst. |
| mock_transport_.AddExpectedSize(kNackSize, 5); |
| base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(10); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // Add second NACK request. |
| EXPECT_TRUE(paced_sender_->ResendPackets(nack_packets)); |
| |
| // Check that we get the next NACK burst. |
| mock_transport_.AddExpectedSize(kNackSize, 7); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // End of NACK plus a packet from the oldest frame. |
| mock_transport_.AddExpectedSize(kNackSize, 6); |
| mock_transport_.AddExpectedSize(kSize1, 1); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // Add second frame. |
| // Make sure we don't delay the second frame due to the previous packets. |
| EXPECT_TRUE(paced_sender_->SendPackets(second_frame_packets)); |
| |
| // Last packets of frame 1 and the first packets of frame 2. |
| mock_transport_.AddExpectedSize(kSize1, 5); |
| mock_transport_.AddExpectedSize(kSize2, 2); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // Last packets of frame 2. |
| mock_transport_.AddExpectedSize(kSize2, 7); |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| |
| // No more packets. |
| testing_clock_.Advance(timeout); |
| task_runner_->RunTasks(); |
| } |
| |
| TEST_F(PacedSenderTest, PaceWith60fps) { |
| // Testing what happen when we get multiple NACK requests for a fully lost |
| // frames just as we sent the first packets in a frame. |
| int num_of_packets_in_frame = 9; |
| |
| PacketList first_frame_packets = |
| CreatePacketList(kSize1, num_of_packets_in_frame); |
| |
| PacketList second_frame_packets = |
| CreatePacketList(kSize2, num_of_packets_in_frame); |
| |
| PacketList third_frame_packets = |
| CreatePacketList(kSize3, num_of_packets_in_frame); |
| |
| PacketList fourth_frame_packets = |
| CreatePacketList(kSize4, num_of_packets_in_frame); |
| |
| base::TimeDelta timeout_10ms = base::TimeDelta::FromMilliseconds(10); |
| |
| // Check that the first burst of the frame go out on the wire. |
| mock_transport_.AddExpectedSize(kSize1, 3); |
| EXPECT_TRUE(paced_sender_->SendPackets(first_frame_packets)); |
| |
| mock_transport_.AddExpectedSize(kSize1, 3); |
| testing_clock_.Advance(timeout_10ms); |
| task_runner_->RunTasks(); |
| |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(6)); |
| |
| // Add second frame, after 16 ms. |
| EXPECT_TRUE(paced_sender_->SendPackets(second_frame_packets)); |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(4)); |
| |
| mock_transport_.AddExpectedSize(kSize1, 3); |
| mock_transport_.AddExpectedSize(kSize2, 1); |
| testing_clock_.Advance(timeout_10ms); |
| task_runner_->RunTasks(); |
| |
| mock_transport_.AddExpectedSize(kSize2, 4); |
| testing_clock_.Advance(timeout_10ms); |
| task_runner_->RunTasks(); |
| |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(3)); |
| |
| // Add third frame, after 33 ms. |
| EXPECT_TRUE(paced_sender_->SendPackets(third_frame_packets)); |
| mock_transport_.AddExpectedSize(kSize2, 4); |
| mock_transport_.AddExpectedSize(kSize3, 1); |
| |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(7)); |
| task_runner_->RunTasks(); |
| |
| // Add fourth frame, after 50 ms. |
| EXPECT_TRUE(paced_sender_->SendPackets(fourth_frame_packets)); |
| |
| mock_transport_.AddExpectedSize(kSize3, 6); |
| testing_clock_.Advance(timeout_10ms); |
| task_runner_->RunTasks(); |
| |
| mock_transport_.AddExpectedSize(kSize3, 2); |
| mock_transport_.AddExpectedSize(kSize4, 4); |
| testing_clock_.Advance(timeout_10ms); |
| task_runner_->RunTasks(); |
| |
| mock_transport_.AddExpectedSize(kSize4, 5); |
| testing_clock_.Advance(timeout_10ms); |
| task_runner_->RunTasks(); |
| |
| testing_clock_.Advance(timeout_10ms); |
| task_runner_->RunTasks(); |
| } |
| |
| } // namespace cast |
| } // namespace media |