// 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/memory/scoped_ptr.h" #include "base/test/simple_test_tick_clock.h" #include "media/cast/cast_defines.h" #include "media/cast/cast_environment.h" #include "media/cast/net/pacing/paced_sender.h" #include "media/cast/rtcp/rtcp_sender.h" #include "media/cast/rtcp/rtcp_utility.h" #include "media/cast/rtcp/test_rtcp_packet_builder.h" #include "media/cast/test/fake_task_runner.h" #include "testing/gmock/include/gmock/gmock.h" namespace media { namespace cast { namespace { static const uint32 kSendingSsrc = 0x12345678; static const uint32 kMediaSsrc = 0x87654321; static const std::string kCName("test@10.1.1.1"); } // namespace class TestRtcpTransport : public PacedPacketSender { public: TestRtcpTransport() : expected_packet_length_(0), packet_count_(0) { } virtual bool SendRtcpPacket(const Packet& packet) OVERRIDE { EXPECT_EQ(expected_packet_length_, packet.size()); EXPECT_EQ(0, memcmp(expected_packet_, &(packet[0]), packet.size())); packet_count_++; return true; } virtual bool SendPackets(const PacketList& packets) OVERRIDE { return false; } virtual bool ResendPackets(const PacketList& packets) OVERRIDE { return false; } void SetExpectedRtcpPacket(const uint8* rtcp_buffer, size_t length) { expected_packet_length_ = length; memcpy(expected_packet_, rtcp_buffer, length); } int packet_count() const { return packet_count_; } private: uint8 expected_packet_[kIpPacketSize]; size_t expected_packet_length_; int packet_count_; }; class RtcpSenderTest : public ::testing::Test { protected: RtcpSenderTest() : task_runner_(new test::FakeTaskRunner(&testing_clock_)), cast_environment_(new CastEnvironment(&testing_clock_, task_runner_, task_runner_, task_runner_, task_runner_, task_runner_, GetDefaultCastLoggingConfig())), rtcp_sender_(new RtcpSender(cast_environment_, &test_transport_, kSendingSsrc, kCName)) { } base::SimpleTestTickClock testing_clock_; TestRtcpTransport test_transport_; scoped_refptr<test::FakeTaskRunner> task_runner_; scoped_refptr<CastEnvironment> cast_environment_; scoped_ptr<RtcpSender> rtcp_sender_; }; TEST_F(RtcpSenderTest, RtcpSenderReport) { RtcpSenderInfo sender_info; sender_info.ntp_seconds = kNtpHigh; sender_info.ntp_fraction = kNtpLow; sender_info.rtp_timestamp = kRtpTimestamp; sender_info.send_packet_count = kSendPacketCount; sender_info.send_octet_count = kSendOctetCount; // Sender report + c_name. TestRtcpPacketBuilder p; p.AddSr(kSendingSsrc, 0); p.AddSdesCname(kSendingSsrc, kCName); test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); rtcp_sender_->SendRtcpFromRtpSender(RtcpSender::kRtcpSr, &sender_info, NULL, NULL); EXPECT_EQ(1, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpReceiverReport) { // Empty receiver report + c_name. TestRtcpPacketBuilder p1; p1.AddRr(kSendingSsrc, 0); p1.AddSdesCname(kSendingSsrc, kCName); test_transport_.SetExpectedRtcpPacket(p1.Packet(), p1.Length()); rtcp_sender_->SendRtcpFromRtpReceiver(RtcpSender::kRtcpRr, NULL, NULL, NULL, NULL); EXPECT_EQ(1, test_transport_.packet_count()); // Receiver report with report block + c_name. TestRtcpPacketBuilder p2; p2.AddRr(kSendingSsrc, 1); p2.AddRb(kMediaSsrc); p2.AddSdesCname(kSendingSsrc, kCName); test_transport_.SetExpectedRtcpPacket(p2.Packet(), p2.Length()); RtcpReportBlock report_block; // Initialize remote_ssrc to a "clearly illegal" value. report_block.remote_ssrc = 0xDEAD; report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender. report_block.fraction_lost = kLoss >> 24; report_block.cumulative_lost = kLoss; // 24 bits valid. report_block.extended_high_sequence_number = kExtendedMax; report_block.jitter = kTestJitter; report_block.last_sr = kLastSr; report_block.delay_since_last_sr = kDelayLastSr; rtcp_sender_->SendRtcpFromRtpReceiver(RtcpSender::kRtcpRr, &report_block, NULL, NULL, NULL); EXPECT_EQ(2, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpSenderReportWithDlrr) { RtcpSenderInfo sender_info; sender_info.ntp_seconds = kNtpHigh; sender_info.ntp_fraction = kNtpLow; sender_info.rtp_timestamp = kRtpTimestamp; sender_info.send_packet_count = kSendPacketCount; sender_info.send_octet_count = kSendOctetCount; // Sender report + c_name + dlrr. TestRtcpPacketBuilder p1; p1.AddSr(kSendingSsrc, 0); p1.AddSdesCname(kSendingSsrc, kCName); p1.AddXrHeader(kSendingSsrc); p1.AddXrDlrrBlock(kSendingSsrc); test_transport_.SetExpectedRtcpPacket(p1.Packet(), p1.Length()); RtcpDlrrReportBlock dlrr_rb; dlrr_rb.last_rr = kLastRr; dlrr_rb.delay_since_last_rr = kDelayLastRr; rtcp_sender_->SendRtcpFromRtpSender( RtcpSender::kRtcpSr | RtcpSender::kRtcpDlrr, &sender_info, &dlrr_rb, NULL); EXPECT_EQ(1, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpSenderReportWithDlrrAndLog) { RtcpSenderInfo sender_info; sender_info.ntp_seconds = kNtpHigh; sender_info.ntp_fraction = kNtpLow; sender_info.rtp_timestamp = kRtpTimestamp; sender_info.send_packet_count = kSendPacketCount; sender_info.send_octet_count = kSendOctetCount; // Sender report + c_name + dlrr + sender log. TestRtcpPacketBuilder p; p.AddSr(kSendingSsrc, 0); p.AddSdesCname(kSendingSsrc, kCName); p.AddXrHeader(kSendingSsrc); p.AddXrDlrrBlock(kSendingSsrc); p.AddSenderLog(kSendingSsrc); p.AddSenderFrameLog(kRtcpSenderFrameStatusSentToNetwork, kRtpTimestamp); test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpDlrrReportBlock dlrr_rb; dlrr_rb.last_rr = kLastRr; dlrr_rb.delay_since_last_rr = kDelayLastRr; RtcpSenderFrameLogMessage sender_frame_log; sender_frame_log.frame_status = kRtcpSenderFrameStatusSentToNetwork; sender_frame_log.rtp_timestamp = kRtpTimestamp; RtcpSenderLogMessage sender_log; sender_log.push_back(sender_frame_log); rtcp_sender_->SendRtcpFromRtpSender( RtcpSender::kRtcpSr | RtcpSender::kRtcpDlrr | RtcpSender::kRtcpSenderLog, &sender_info, &dlrr_rb, &sender_log); EXPECT_EQ(1, test_transport_.packet_count()); EXPECT_TRUE(sender_log.empty()); } TEST_F(RtcpSenderTest, RtcpSenderReporWithTooManyLogFrames) { RtcpSenderInfo sender_info; sender_info.ntp_seconds = kNtpHigh; sender_info.ntp_fraction = kNtpLow; sender_info.rtp_timestamp = kRtpTimestamp; sender_info.send_packet_count = kSendPacketCount; sender_info.send_octet_count = kSendOctetCount; // Sender report + c_name + sender log. TestRtcpPacketBuilder p; p.AddSr(kSendingSsrc, 0); p.AddSdesCname(kSendingSsrc, kCName); p.AddSenderLog(kSendingSsrc); for (int i = 0; i < 359; ++i) { p.AddSenderFrameLog(kRtcpSenderFrameStatusSentToNetwork, kRtpTimestamp + i * 90); } test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpSenderLogMessage sender_log; for (int j = 0; j < 400; ++j) { RtcpSenderFrameLogMessage sender_frame_log; sender_frame_log.frame_status = kRtcpSenderFrameStatusSentToNetwork; sender_frame_log.rtp_timestamp = kRtpTimestamp + j * 90; sender_log.push_back(sender_frame_log); } rtcp_sender_->SendRtcpFromRtpSender( RtcpSender::kRtcpSr | RtcpSender::kRtcpSenderLog, &sender_info, NULL, &sender_log); EXPECT_EQ(1, test_transport_.packet_count()); EXPECT_EQ(41u, sender_log.size()); } TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtr) { // Receiver report with report block + c_name. TestRtcpPacketBuilder p; p.AddRr(kSendingSsrc, 1); p.AddRb(kMediaSsrc); p.AddSdesCname(kSendingSsrc, kCName); p.AddXrHeader(kSendingSsrc); p.AddXrRrtrBlock(); test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpReportBlock report_block; // Initialize remote_ssrc to a "clearly illegal" value. report_block.remote_ssrc = 0xDEAD; report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender. report_block.fraction_lost = kLoss >> 24; report_block.cumulative_lost = kLoss; // 24 bits valid. report_block.extended_high_sequence_number = kExtendedMax; report_block.jitter = kTestJitter; report_block.last_sr = kLastSr; report_block.delay_since_last_sr = kDelayLastSr; RtcpReceiverReferenceTimeReport rrtr; rrtr.ntp_seconds = kNtpHigh; rrtr.ntp_fraction = kNtpLow; rtcp_sender_->SendRtcpFromRtpReceiver( RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr, &report_block, &rrtr, NULL, NULL); EXPECT_EQ(1, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpReceiverReportWithCast) { // Receiver report with report block + c_name. TestRtcpPacketBuilder p; p.AddRr(kSendingSsrc, 1); p.AddRb(kMediaSsrc); p.AddSdesCname(kSendingSsrc, kCName); p.AddCast(kSendingSsrc, kMediaSsrc); test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpReportBlock report_block; // Initialize remote_ssrc to a "clearly illegal" value. report_block.remote_ssrc = 0xDEAD; report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender. report_block.fraction_lost = kLoss >> 24; report_block.cumulative_lost = kLoss; // 24 bits valid. report_block.extended_high_sequence_number = kExtendedMax; report_block.jitter = kTestJitter; report_block.last_sr = kLastSr; report_block.delay_since_last_sr = kDelayLastSr; RtcpCastMessage cast_message(kMediaSsrc); cast_message.ack_frame_id_ = kAckFrameId; PacketIdSet missing_packets; cast_message.missing_frames_and_packets_[kLostFrameId] = missing_packets; missing_packets.insert(kLostPacketId1); missing_packets.insert(kLostPacketId2); missing_packets.insert(kLostPacketId3); cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] = missing_packets; rtcp_sender_->SendRtcpFromRtpReceiver( RtcpSender::kRtcpRr | RtcpSender::kRtcpCast, &report_block, NULL, &cast_message, NULL); EXPECT_EQ(1, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtraAndCastMessage) { TestRtcpPacketBuilder p; p.AddRr(kSendingSsrc, 1); p.AddRb(kMediaSsrc); p.AddSdesCname(kSendingSsrc, kCName); p.AddXrHeader(kSendingSsrc); p.AddXrRrtrBlock(); p.AddCast(kSendingSsrc, kMediaSsrc); test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpReportBlock report_block; // Initialize remote_ssrc to a "clearly illegal" value. report_block.remote_ssrc = 0xDEAD; report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender. report_block.fraction_lost = kLoss >> 24; report_block.cumulative_lost = kLoss; // 24 bits valid. report_block.extended_high_sequence_number = kExtendedMax; report_block.jitter = kTestJitter; report_block.last_sr = kLastSr; report_block.delay_since_last_sr = kDelayLastSr; RtcpReceiverReferenceTimeReport rrtr; rrtr.ntp_seconds = kNtpHigh; rrtr.ntp_fraction = kNtpLow; RtcpCastMessage cast_message(kMediaSsrc); cast_message.ack_frame_id_ = kAckFrameId; PacketIdSet missing_packets; cast_message.missing_frames_and_packets_[kLostFrameId] = missing_packets; missing_packets.insert(kLostPacketId1); missing_packets.insert(kLostPacketId2); missing_packets.insert(kLostPacketId3); cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] = missing_packets; rtcp_sender_->SendRtcpFromRtpReceiver( RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr | RtcpSender::kRtcpCast, &report_block, &rrtr, &cast_message, NULL); EXPECT_EQ(1, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) { static const uint32 kTimeBaseMs = 12345678; static const uint32 kTimeDelayMs = 10; static const uint32 kDelayDeltaMs = 123; TestRtcpPacketBuilder p; p.AddRr(kSendingSsrc, 1); p.AddRb(kMediaSsrc); p.AddSdesCname(kSendingSsrc, kCName); p.AddXrHeader(kSendingSsrc); p.AddXrRrtrBlock(); p.AddCast(kSendingSsrc, kMediaSsrc); test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpReportBlock report_block; // Initialize remote_ssrc to a "clearly illegal" value. report_block.remote_ssrc = 0xDEAD; report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender. report_block.fraction_lost = kLoss >> 24; report_block.cumulative_lost = kLoss; // 24 bits valid. report_block.extended_high_sequence_number = kExtendedMax; report_block.jitter = kTestJitter; report_block.last_sr = kLastSr; report_block.delay_since_last_sr = kDelayLastSr; RtcpReceiverReferenceTimeReport rrtr; rrtr.ntp_seconds = kNtpHigh; rrtr.ntp_fraction = kNtpLow; RtcpCastMessage cast_message(kMediaSsrc); cast_message.ack_frame_id_ = kAckFrameId; PacketIdSet missing_packets; cast_message.missing_frames_and_packets_[kLostFrameId] = missing_packets; missing_packets.insert(kLostPacketId1); missing_packets.insert(kLostPacketId2); missing_packets.insert(kLostPacketId3); cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] = missing_packets; // Test empty Log message. RtcpReceiverLogMessage receiver_log; VLOG(0) << " Test empty Log " ; rtcp_sender_->SendRtcpFromRtpReceiver( RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr | RtcpSender::kRtcpCast | RtcpSender::kRtcpReceiverLog, &report_block, &rrtr, &cast_message, &receiver_log); base::SimpleTestTickClock testing_clock; testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs)); p.AddReceiverLog(kSendingSsrc); p.AddReceiverFrameLog(kRtpTimestamp, 2, kTimeBaseMs); p.AddReceiverEventLog(kDelayDeltaMs, 1, 0); p.AddReceiverEventLog(kLostPacketId1, 6, kTimeDelayMs); test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpReceiverFrameLogMessage frame_log(kRtpTimestamp); RtcpReceiverEventLogMessage event_log; event_log.type = kAckSent; event_log.event_timestamp = testing_clock.NowTicks(); event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs); frame_log.event_log_messages_.push_back(event_log); testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs)); event_log.type = kPacketReceived; event_log.event_timestamp = testing_clock.NowTicks(); event_log.packet_id = kLostPacketId1; frame_log.event_log_messages_.push_back(event_log); receiver_log.push_back(frame_log); VLOG(0) << " Test Log " ; rtcp_sender_->SendRtcpFromRtpReceiver( RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr | RtcpSender::kRtcpCast | RtcpSender::kRtcpReceiverLog, &report_block, &rrtr, &cast_message, &receiver_log); EXPECT_TRUE(receiver_log.empty()); EXPECT_EQ(2, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpReceiverReportWithOversizedFrameLog) { static const uint32 kTimeBaseMs = 12345678; static const uint32 kTimeDelayMs = 10; static const uint32 kDelayDeltaMs = 123; TestRtcpPacketBuilder p; p.AddRr(kSendingSsrc, 1); p.AddRb(kMediaSsrc); p.AddSdesCname(kSendingSsrc, kCName); RtcpReportBlock report_block; // Initialize remote_ssrc to a "clearly illegal" value. report_block.remote_ssrc = 0xDEAD; report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender. report_block.fraction_lost = kLoss >> 24; report_block.cumulative_lost = kLoss; // 24 bits valid. report_block.extended_high_sequence_number = kExtendedMax; report_block.jitter = kTestJitter; report_block.last_sr = kLastSr; report_block.delay_since_last_sr = kDelayLastSr; base::SimpleTestTickClock testing_clock; testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs)); p.AddReceiverLog(kSendingSsrc); p.AddReceiverFrameLog(kRtpTimestamp, 1, kTimeBaseMs); p.AddReceiverEventLog(kDelayDeltaMs, 1, 0); p.AddReceiverFrameLog(kRtpTimestamp + 2345, kRtcpMaxReceiverLogMessages, kTimeBaseMs); for (size_t i = 0; i < kRtcpMaxReceiverLogMessages; ++i) { p.AddReceiverEventLog( kLostPacketId1, 6, static_cast<uint16>(kTimeDelayMs * i)); } test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpReceiverFrameLogMessage frame_1_log(kRtpTimestamp); RtcpReceiverEventLogMessage event_log; event_log.type = kAckSent; event_log.event_timestamp = testing_clock.NowTicks(); event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs); frame_1_log.event_log_messages_.push_back(event_log); RtcpReceiverLogMessage receiver_log; receiver_log.push_back(frame_1_log); RtcpReceiverFrameLogMessage frame_2_log(kRtpTimestamp + 2345); for (int j = 0; j < 300; ++j) { event_log.type = kPacketReceived; event_log.event_timestamp = testing_clock.NowTicks(); event_log.packet_id = kLostPacketId1; frame_2_log.event_log_messages_.push_back(event_log); testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs)); } receiver_log.push_back(frame_2_log); rtcp_sender_->SendRtcpFromRtpReceiver( RtcpSender::kRtcpRr | RtcpSender::kRtcpReceiverLog, &report_block, NULL, NULL, &receiver_log); EXPECT_EQ(1, test_transport_.packet_count()); EXPECT_EQ(1u, receiver_log.size()); EXPECT_EQ(300u - kRtcpMaxReceiverLogMessages, receiver_log.front().event_log_messages_.size()); } TEST_F(RtcpSenderTest, RtcpReceiverReportWithTooManyLogFrames) { static const uint32 kTimeBaseMs = 12345678; static const uint32 kTimeDelayMs = 10; static const uint32 kDelayDeltaMs = 123; TestRtcpPacketBuilder p; p.AddRr(kSendingSsrc, 1); p.AddRb(kMediaSsrc); p.AddSdesCname(kSendingSsrc, kCName); RtcpReportBlock report_block; // Initialize remote_ssrc to a "clearly illegal" value. report_block.remote_ssrc = 0xDEAD; report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender. report_block.fraction_lost = kLoss >> 24; report_block.cumulative_lost = kLoss; // 24 bits valid. report_block.extended_high_sequence_number = kExtendedMax; report_block.jitter = kTestJitter; report_block.last_sr = kLastSr; report_block.delay_since_last_sr = kDelayLastSr; base::SimpleTestTickClock testing_clock; testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs)); p.AddReceiverLog(kSendingSsrc); for (int i = 0; i < 119; ++i) { p.AddReceiverFrameLog(kRtpTimestamp, 1, kTimeBaseMs + i * kTimeDelayMs); p.AddReceiverEventLog(kDelayDeltaMs, 1, 0); } test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length()); RtcpReceiverLogMessage receiver_log; for (int j = 0; j < 200; ++j) { RtcpReceiverFrameLogMessage frame_log(kRtpTimestamp); RtcpReceiverEventLogMessage event_log; event_log.type = kAckSent; event_log.event_timestamp = testing_clock.NowTicks(); event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs); frame_log.event_log_messages_.push_back(event_log); receiver_log.push_back(frame_log); testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs)); } rtcp_sender_->SendRtcpFromRtpReceiver( RtcpSender::kRtcpRr | RtcpSender::kRtcpReceiverLog, &report_block, NULL, NULL, &receiver_log); EXPECT_EQ(1, test_transport_.packet_count()); EXPECT_EQ(81u, receiver_log.size()); } } // namespace cast } // namespace media