1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <gtest/gtest.h> 6#include <stdint.h> 7 8#include "base/bind.h" 9#include "base/bind_helpers.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/test/simple_test_tick_clock.h" 12#include "base/values.h" 13#include "media/cast/cast_config.h" 14#include "media/cast/net/cast_transport_config.h" 15#include "media/cast/net/cast_transport_sender_impl.h" 16#include "media/cast/net/rtcp/rtcp.h" 17#include "media/cast/test/fake_single_thread_task_runner.h" 18#include "testing/gtest/include/gtest/gtest.h" 19 20namespace media { 21namespace cast { 22 23namespace { 24const int64 kStartMillisecond = INT64_C(12345678900000); 25const uint32 kVideoSsrc = 1; 26const uint32 kAudioSsrc = 2; 27} // namespace 28 29class FakePacketSender : public PacketSender { 30 public: 31 FakePacketSender() 32 : paused_(false), packets_sent_(0), bytes_sent_(0) {} 33 34 virtual bool SendPacket(PacketRef packet, const base::Closure& cb) OVERRIDE { 35 if (paused_) { 36 stored_packet_ = packet; 37 callback_ = cb; 38 return false; 39 } 40 ++packets_sent_; 41 bytes_sent_ += packet->data.size(); 42 return true; 43 } 44 45 virtual int64 GetBytesSent() OVERRIDE { 46 return bytes_sent_; 47 } 48 49 void SetPaused(bool paused) { 50 paused_ = paused; 51 if (!paused && stored_packet_.get()) { 52 SendPacket(stored_packet_, callback_); 53 callback_.Run(); 54 } 55 } 56 57 int packets_sent() const { return packets_sent_; } 58 59 private: 60 bool paused_; 61 base::Closure callback_; 62 PacketRef stored_packet_; 63 int packets_sent_; 64 int64 bytes_sent_; 65 66 DISALLOW_COPY_AND_ASSIGN(FakePacketSender); 67}; 68 69class CastTransportSenderImplTest : public ::testing::Test { 70 protected: 71 CastTransportSenderImplTest() 72 : num_times_callback_called_(0) { 73 testing_clock_.Advance( 74 base::TimeDelta::FromMilliseconds(kStartMillisecond)); 75 task_runner_ = new test::FakeSingleThreadTaskRunner(&testing_clock_); 76 } 77 78 virtual ~CastTransportSenderImplTest() {} 79 80 void InitWithoutLogging() { 81 transport_sender_.reset( 82 new CastTransportSenderImpl(NULL, 83 &testing_clock_, 84 net::IPEndPoint(), 85 make_scoped_ptr(new base::DictionaryValue), 86 base::Bind(&UpdateCastTransportStatus), 87 BulkRawEventsCallback(), 88 base::TimeDelta(), 89 task_runner_, 90 &transport_)); 91 task_runner_->RunTasks(); 92 } 93 94 void InitWithOptions() { 95 scoped_ptr<base::DictionaryValue> options( 96 new base::DictionaryValue); 97 options->SetBoolean("DHCP", true); 98 options->SetBoolean("disable_wifi_scan", true); 99 options->SetBoolean("media_streaming_mode", true); 100 options->SetInteger("pacer_target_burst_size", 20); 101 options->SetInteger("pacer_max_burst_size", 100); 102 transport_sender_.reset( 103 new CastTransportSenderImpl(NULL, 104 &testing_clock_, 105 net::IPEndPoint(), 106 options.Pass(), 107 base::Bind(&UpdateCastTransportStatus), 108 BulkRawEventsCallback(), 109 base::TimeDelta(), 110 task_runner_, 111 &transport_)); 112 task_runner_->RunTasks(); 113 } 114 115 void InitWithLogging() { 116 transport_sender_.reset(new CastTransportSenderImpl( 117 NULL, 118 &testing_clock_, 119 net::IPEndPoint(), 120 make_scoped_ptr(new base::DictionaryValue), 121 base::Bind(&UpdateCastTransportStatus), 122 base::Bind(&CastTransportSenderImplTest::LogRawEvents, 123 base::Unretained(this)), 124 base::TimeDelta::FromMilliseconds(10), 125 task_runner_, 126 &transport_)); 127 task_runner_->RunTasks(); 128 } 129 130 void InitializeVideo() { 131 CastTransportRtpConfig rtp_config; 132 rtp_config.ssrc = kVideoSsrc; 133 rtp_config.feedback_ssrc = 2; 134 rtp_config.rtp_payload_type = 3; 135 transport_sender_->InitializeVideo(rtp_config, 136 RtcpCastMessageCallback(), 137 RtcpRttCallback()); 138 } 139 140 void InitializeAudio() { 141 CastTransportRtpConfig rtp_config; 142 rtp_config.ssrc = kAudioSsrc; 143 rtp_config.feedback_ssrc = 3; 144 rtp_config.rtp_payload_type = 4; 145 transport_sender_->InitializeAudio(rtp_config, 146 RtcpCastMessageCallback(), 147 RtcpRttCallback()); 148 } 149 150 void LogRawEvents(const std::vector<PacketEvent>& packet_events, 151 const std::vector<FrameEvent>& frame_events) { 152 num_times_callback_called_++; 153 } 154 155 static void UpdateCastTransportStatus(CastTransportStatus status) { 156 } 157 158 base::SimpleTestTickClock testing_clock_; 159 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; 160 scoped_ptr<CastTransportSenderImpl> transport_sender_; 161 FakePacketSender transport_; 162 int num_times_callback_called_; 163}; 164 165TEST_F(CastTransportSenderImplTest, InitWithoutLogging) { 166 InitWithoutLogging(); 167 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); 168 EXPECT_EQ(0, num_times_callback_called_); 169} 170 171TEST_F(CastTransportSenderImplTest, InitWithLogging) { 172 InitWithLogging(); 173 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); 174 EXPECT_EQ(5, num_times_callback_called_); 175} 176 177TEST_F(CastTransportSenderImplTest, InitWithOptions) { 178 InitWithOptions(); 179 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); 180 EXPECT_EQ(0, num_times_callback_called_); 181} 182 183TEST_F(CastTransportSenderImplTest, NacksCancelRetransmits) { 184 InitWithoutLogging(); 185 InitializeVideo(); 186 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); 187 188 // A fake frame that will be decomposed into 4 packets. 189 EncodedFrame fake_frame; 190 fake_frame.frame_id = 1; 191 fake_frame.rtp_timestamp = 1; 192 fake_frame.dependency = EncodedFrame::KEY; 193 fake_frame.data.resize(5000, ' '); 194 195 transport_sender_->InsertFrame(kVideoSsrc, fake_frame); 196 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 197 EXPECT_EQ(4, transport_.packets_sent()); 198 199 // Resend packet 0. 200 MissingFramesAndPacketsMap missing_packets; 201 missing_packets[1].insert(0); 202 missing_packets[1].insert(1); 203 missing_packets[1].insert(2); 204 205 transport_.SetPaused(true); 206 DedupInfo dedup_info; 207 dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(10); 208 transport_sender_->ResendPackets( 209 kVideoSsrc, missing_packets, true, dedup_info); 210 211 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 212 213 RtcpCastMessage cast_message; 214 cast_message.media_ssrc = kVideoSsrc; 215 cast_message.ack_frame_id = 1; 216 cast_message.missing_frames_and_packets[1].insert(3); 217 transport_sender_->OnReceivedCastMessage(kVideoSsrc, 218 RtcpCastMessageCallback(), 219 cast_message); 220 transport_.SetPaused(false); 221 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 222 223 // Resend one packet in the socket when unpaused. 224 // Resend one more packet from NACK. 225 EXPECT_EQ(6, transport_.packets_sent()); 226} 227 228TEST_F(CastTransportSenderImplTest, CancelRetransmits) { 229 InitWithoutLogging(); 230 InitializeVideo(); 231 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); 232 233 // A fake frame that will be decomposed into 4 packets. 234 EncodedFrame fake_frame; 235 fake_frame.frame_id = 1; 236 fake_frame.rtp_timestamp = 1; 237 fake_frame.dependency = EncodedFrame::KEY; 238 fake_frame.data.resize(5000, ' '); 239 240 transport_sender_->InsertFrame(kVideoSsrc, fake_frame); 241 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 242 EXPECT_EQ(4, transport_.packets_sent()); 243 244 // Resend all packets for frame 1. 245 MissingFramesAndPacketsMap missing_packets; 246 missing_packets[1].insert(kRtcpCastAllPacketsLost); 247 248 transport_.SetPaused(true); 249 DedupInfo dedup_info; 250 dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(10); 251 transport_sender_->ResendPackets( 252 kVideoSsrc, missing_packets, true, dedup_info); 253 254 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 255 std::vector<uint32> cancel_sending_frames; 256 cancel_sending_frames.push_back(1); 257 transport_sender_->CancelSendingFrames(kVideoSsrc, 258 cancel_sending_frames); 259 transport_.SetPaused(false); 260 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 261 262 // Resend one packet in the socket when unpaused. 263 EXPECT_EQ(5, transport_.packets_sent()); 264} 265 266TEST_F(CastTransportSenderImplTest, Kickstart) { 267 InitWithoutLogging(); 268 InitializeVideo(); 269 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); 270 271 // A fake frame that will be decomposed into 4 packets. 272 EncodedFrame fake_frame; 273 fake_frame.frame_id = 1; 274 fake_frame.rtp_timestamp = 1; 275 fake_frame.dependency = EncodedFrame::KEY; 276 fake_frame.data.resize(5000, ' '); 277 278 transport_.SetPaused(true); 279 transport_sender_->InsertFrame(kVideoSsrc, fake_frame); 280 transport_sender_->ResendFrameForKickstart(kVideoSsrc, 1); 281 transport_.SetPaused(false); 282 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 283 EXPECT_EQ(4, transport_.packets_sent()); 284 285 // Resend 2 packets for frame 1. 286 MissingFramesAndPacketsMap missing_packets; 287 missing_packets[1].insert(0); 288 missing_packets[1].insert(1); 289 290 transport_.SetPaused(true); 291 DedupInfo dedup_info; 292 dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(10); 293 transport_sender_->ResendPackets( 294 kVideoSsrc, missing_packets, true, dedup_info); 295 transport_sender_->ResendFrameForKickstart(kVideoSsrc, 1); 296 transport_.SetPaused(false); 297 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 298 299 // Resend one packet in the socket when unpaused. 300 // Two more retransmission packets sent. 301 EXPECT_EQ(7, transport_.packets_sent()); 302} 303 304TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { 305 InitWithoutLogging(); 306 InitializeAudio(); 307 InitializeVideo(); 308 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); 309 310 // Send two audio frames. 311 EncodedFrame fake_audio; 312 fake_audio.frame_id = 1; 313 fake_audio.reference_time = testing_clock_.NowTicks(); 314 fake_audio.dependency = EncodedFrame::KEY; 315 fake_audio.data.resize(100, ' '); 316 transport_sender_->InsertFrame(kAudioSsrc, fake_audio); 317 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(2)); 318 fake_audio.frame_id = 2; 319 fake_audio.reference_time = testing_clock_.NowTicks(); 320 transport_sender_->InsertFrame(kAudioSsrc, fake_audio); 321 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(2)); 322 EXPECT_EQ(2, transport_.packets_sent()); 323 324 // Ack the first audio frame. 325 RtcpCastMessage cast_message; 326 cast_message.media_ssrc = kAudioSsrc; 327 cast_message.ack_frame_id = 1; 328 transport_sender_->OnReceivedCastMessage(kAudioSsrc, 329 RtcpCastMessageCallback(), 330 cast_message); 331 task_runner_->RunTasks(); 332 EXPECT_EQ(2, transport_.packets_sent()); 333 334 // Send a fake video frame that will be decomposed into 4 packets. 335 EncodedFrame fake_video; 336 fake_video.frame_id = 1; 337 fake_video.dependency = EncodedFrame::KEY; 338 fake_video.data.resize(5000, ' '); 339 transport_sender_->InsertFrame(kVideoSsrc, fake_video); 340 task_runner_->RunTasks(); 341 EXPECT_EQ(6, transport_.packets_sent()); 342 343 // Retransmission is reject because audio is not acked yet. 344 cast_message.media_ssrc = kVideoSsrc; 345 cast_message.ack_frame_id = 0; 346 cast_message.missing_frames_and_packets[1].insert(3); 347 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); 348 transport_sender_->OnReceivedCastMessage(kVideoSsrc, 349 RtcpCastMessageCallback(), 350 cast_message); 351 task_runner_->RunTasks(); 352 EXPECT_EQ(6, transport_.packets_sent()); 353 354 // Ack the second audio frame. 355 cast_message.media_ssrc = kAudioSsrc; 356 cast_message.ack_frame_id = 2; 357 cast_message.missing_frames_and_packets.clear(); 358 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(2)); 359 transport_sender_->OnReceivedCastMessage(kAudioSsrc, 360 RtcpCastMessageCallback(), 361 cast_message); 362 task_runner_->RunTasks(); 363 EXPECT_EQ(6, transport_.packets_sent()); 364 365 // Retransmission of video packet now accepted. 366 cast_message.media_ssrc = kVideoSsrc; 367 cast_message.ack_frame_id = 1; 368 cast_message.missing_frames_and_packets[1].insert(3); 369 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(2)); 370 transport_sender_->OnReceivedCastMessage(kVideoSsrc, 371 RtcpCastMessageCallback(), 372 cast_message); 373 task_runner_->RunTasks(); 374 EXPECT_EQ(7, transport_.packets_sent()); 375} 376 377} // namespace cast 378} // namespace media 379