Home | History | Annotate | Download | only in net
      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 
     20 namespace media {
     21 namespace cast {
     22 
     23 namespace {
     24 const int64 kStartMillisecond = INT64_C(12345678900000);
     25 const uint32 kVideoSsrc = 1;
     26 const uint32 kAudioSsrc = 2;
     27 }  // namespace
     28 
     29 class 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 
     69 class 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 
    165 TEST_F(CastTransportSenderImplTest, InitWithoutLogging) {
    166   InitWithoutLogging();
    167   task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50));
    168   EXPECT_EQ(0, num_times_callback_called_);
    169 }
    170 
    171 TEST_F(CastTransportSenderImplTest, InitWithLogging) {
    172   InitWithLogging();
    173   task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50));
    174   EXPECT_EQ(5, num_times_callback_called_);
    175 }
    176 
    177 TEST_F(CastTransportSenderImplTest, InitWithOptions) {
    178   InitWithOptions();
    179   task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50));
    180   EXPECT_EQ(0, num_times_callback_called_);
    181 }
    182 
    183 TEST_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 
    228 TEST_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 
    266 TEST_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 
    304 TEST_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