Home | History | Annotate | Download | only in video_sender
      1 // Copyright 2013 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 <stdint.h>
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/test/simple_test_tick_clock.h"
     12 #include "media/base/video_frame.h"
     13 #include "media/cast/cast_environment.h"
     14 #include "media/cast/logging/simple_event_subscriber.h"
     15 #include "media/cast/test/fake_single_thread_task_runner.h"
     16 #include "media/cast/test/fake_video_encode_accelerator.h"
     17 #include "media/cast/test/utility/default_config.h"
     18 #include "media/cast/test/utility/video_utility.h"
     19 #include "media/cast/transport/cast_transport_config.h"
     20 #include "media/cast/transport/cast_transport_sender_impl.h"
     21 #include "media/cast/transport/pacing/paced_sender.h"
     22 #include "media/cast/video_sender/video_sender.h"
     23 #include "testing/gmock/include/gmock/gmock.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 
     26 namespace media {
     27 namespace cast {
     28 
     29 namespace {
     30 static const uint8 kPixelValue = 123;
     31 static const int kWidth = 320;
     32 static const int kHeight = 240;
     33 
     34 using testing::_;
     35 using testing::AtLeast;
     36 
     37 void CreateVideoEncodeAccelerator(
     38     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     39     scoped_ptr<VideoEncodeAccelerator> fake_vea,
     40     const ReceiveVideoEncodeAcceleratorCallback& callback) {
     41   callback.Run(task_runner, fake_vea.Pass());
     42 }
     43 
     44 void CreateSharedMemory(
     45     size_t size, const ReceiveVideoEncodeMemoryCallback& callback) {
     46   scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
     47   if (!shm->CreateAndMapAnonymous(size)) {
     48     NOTREACHED();
     49     return;
     50   }
     51   callback.Run(shm.Pass());
     52 }
     53 
     54 class TestPacketSender : public transport::PacketSender {
     55  public:
     56   TestPacketSender()
     57       : number_of_rtp_packets_(0),
     58         number_of_rtcp_packets_(0),
     59         paused_(false) {}
     60 
     61   // A singular packet implies a RTCP packet.
     62   virtual bool SendPacket(transport::PacketRef packet,
     63                           const base::Closure& cb) OVERRIDE {
     64     if (paused_) {
     65       stored_packet_ = packet;
     66       callback_ = cb;
     67       return false;
     68     }
     69     if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
     70       ++number_of_rtcp_packets_;
     71     } else {
     72       // Check that at least one RTCP packet was sent before the first RTP
     73       // packet.  This confirms that the receiver will have the necessary lip
     74       // sync info before it has to calculate the playout time of the first
     75       // frame.
     76       if (number_of_rtp_packets_ == 0)
     77         EXPECT_LE(1, number_of_rtcp_packets_);
     78       ++number_of_rtp_packets_;
     79     }
     80     return true;
     81   }
     82 
     83   int number_of_rtp_packets() const { return number_of_rtp_packets_; }
     84 
     85   int number_of_rtcp_packets() const { return number_of_rtcp_packets_; }
     86 
     87   void SetPause(bool paused) {
     88     paused_ = paused;
     89     if (!paused && stored_packet_) {
     90       SendPacket(stored_packet_, callback_);
     91       callback_.Run();
     92     }
     93   }
     94 
     95  private:
     96   int number_of_rtp_packets_;
     97   int number_of_rtcp_packets_;
     98   bool paused_;
     99   base::Closure callback_;
    100   transport::PacketRef stored_packet_;
    101 
    102   DISALLOW_COPY_AND_ASSIGN(TestPacketSender);
    103 };
    104 
    105 class PeerVideoSender : public VideoSender {
    106  public:
    107   PeerVideoSender(
    108       scoped_refptr<CastEnvironment> cast_environment,
    109       const VideoSenderConfig& video_config,
    110       const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
    111       const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
    112       transport::CastTransportSender* const transport_sender)
    113       : VideoSender(cast_environment,
    114                     video_config,
    115                     create_vea_cb,
    116                     create_video_encode_mem_cb,
    117                     transport_sender) {}
    118   using VideoSender::OnReceivedCastFeedback;
    119 };
    120 }  // namespace
    121 
    122 class VideoSenderTest : public ::testing::Test {
    123  protected:
    124   VideoSenderTest() {
    125     testing_clock_ = new base::SimpleTestTickClock();
    126     testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
    127     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
    128     cast_environment_ =
    129         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
    130                             task_runner_,
    131                             task_runner_,
    132                             task_runner_);
    133     last_pixel_value_ = kPixelValue;
    134     net::IPEndPoint dummy_endpoint;
    135     transport_sender_.reset(new transport::CastTransportSenderImpl(
    136         NULL,
    137         testing_clock_,
    138         dummy_endpoint,
    139         base::Bind(&UpdateCastTransportStatus),
    140         transport::BulkRawEventsCallback(),
    141         base::TimeDelta(),
    142         task_runner_,
    143         &transport_));
    144   }
    145 
    146   virtual ~VideoSenderTest() {}
    147 
    148   virtual void TearDown() OVERRIDE {
    149     video_sender_.reset();
    150     task_runner_->RunTasks();
    151   }
    152 
    153   static void UpdateCastTransportStatus(transport::CastTransportStatus status) {
    154     EXPECT_EQ(transport::TRANSPORT_VIDEO_INITIALIZED, status);
    155   }
    156 
    157   void InitEncoder(bool external) {
    158     VideoSenderConfig video_config;
    159     video_config.rtp_config.ssrc = 1;
    160     video_config.incoming_feedback_ssrc = 2;
    161     video_config.rtcp_c_name = "video_test (at) 10.1.1.1";
    162     video_config.rtp_config.payload_type = 127;
    163     video_config.use_external_encoder = external;
    164     video_config.width = kWidth;
    165     video_config.height = kHeight;
    166     video_config.max_bitrate = 5000000;
    167     video_config.min_bitrate = 1000000;
    168     video_config.start_bitrate = 1000000;
    169     video_config.max_qp = 56;
    170     video_config.min_qp = 0;
    171     video_config.max_frame_rate = 30;
    172     video_config.max_number_of_video_buffers_used = 1;
    173     video_config.codec = transport::kVp8;
    174 
    175     if (external) {
    176       scoped_ptr<VideoEncodeAccelerator> fake_vea(
    177           new test::FakeVideoEncodeAccelerator(task_runner_));
    178       video_sender_.reset(
    179           new PeerVideoSender(cast_environment_,
    180                               video_config,
    181                               base::Bind(&CreateVideoEncodeAccelerator,
    182                                          task_runner_,
    183                                          base::Passed(&fake_vea)),
    184                               base::Bind(&CreateSharedMemory),
    185                               transport_sender_.get()));
    186     } else {
    187       video_sender_.reset(
    188           new PeerVideoSender(cast_environment_,
    189                               video_config,
    190                               CreateDefaultVideoEncodeAcceleratorCallback(),
    191                               CreateDefaultVideoEncodeMemoryCallback(),
    192                               transport_sender_.get()));
    193     }
    194     ASSERT_EQ(STATUS_VIDEO_INITIALIZED, video_sender_->InitializationResult());
    195   }
    196 
    197   scoped_refptr<media::VideoFrame> GetNewVideoFrame() {
    198     gfx::Size size(kWidth, kHeight);
    199     scoped_refptr<media::VideoFrame> video_frame =
    200         media::VideoFrame::CreateFrame(
    201             VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
    202     PopulateVideoFrame(video_frame, last_pixel_value_++);
    203     return video_frame;
    204   }
    205 
    206   scoped_refptr<media::VideoFrame> GetLargeNewVideoFrame() {
    207     gfx::Size size(kWidth, kHeight);
    208     scoped_refptr<media::VideoFrame> video_frame =
    209         media::VideoFrame::CreateFrame(
    210             VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
    211     PopulateVideoFrameWithNoise(video_frame);
    212     return video_frame;
    213   }
    214 
    215   void RunTasks(int during_ms) {
    216     task_runner_->Sleep(base::TimeDelta::FromMilliseconds(during_ms));
    217   }
    218 
    219   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
    220   TestPacketSender transport_;
    221   scoped_ptr<transport::CastTransportSenderImpl> transport_sender_;
    222   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
    223   scoped_ptr<PeerVideoSender> video_sender_;
    224   scoped_refptr<CastEnvironment> cast_environment_;
    225   int last_pixel_value_;
    226 
    227   DISALLOW_COPY_AND_ASSIGN(VideoSenderTest);
    228 };
    229 
    230 TEST_F(VideoSenderTest, BuiltInEncoder) {
    231   InitEncoder(false);
    232   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    233 
    234   const base::TimeTicks capture_time = testing_clock_->NowTicks();
    235   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
    236 
    237   task_runner_->RunTasks();
    238   EXPECT_LE(1, transport_.number_of_rtp_packets());
    239   EXPECT_LE(1, transport_.number_of_rtcp_packets());
    240 }
    241 
    242 TEST_F(VideoSenderTest, ExternalEncoder) {
    243   InitEncoder(true);
    244   task_runner_->RunTasks();
    245 
    246   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    247 
    248   const base::TimeTicks capture_time = testing_clock_->NowTicks();
    249   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
    250 
    251   task_runner_->RunTasks();
    252 
    253   // We need to run the task to cleanup the GPU instance.
    254   video_sender_.reset(NULL);
    255   task_runner_->RunTasks();
    256 }
    257 
    258 TEST_F(VideoSenderTest, RtcpTimer) {
    259   InitEncoder(false);
    260 
    261   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    262 
    263   const base::TimeTicks capture_time = testing_clock_->NowTicks();
    264   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
    265 
    266   // Make sure that we send at least one RTCP packet.
    267   base::TimeDelta max_rtcp_timeout =
    268       base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs * 3 / 2);
    269 
    270   RunTasks(max_rtcp_timeout.InMilliseconds());
    271   EXPECT_LE(1, transport_.number_of_rtp_packets());
    272   EXPECT_LE(1, transport_.number_of_rtcp_packets());
    273   // Build Cast msg and expect RTCP packet.
    274   RtcpCastMessage cast_feedback(1);
    275   cast_feedback.media_ssrc_ = 2;
    276   cast_feedback.ack_frame_id_ = 0;
    277   video_sender_->OnReceivedCastFeedback(cast_feedback);
    278   RunTasks(max_rtcp_timeout.InMilliseconds());
    279   EXPECT_LE(1, transport_.number_of_rtcp_packets());
    280 }
    281 
    282 TEST_F(VideoSenderTest, ResendTimer) {
    283   InitEncoder(false);
    284 
    285   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    286 
    287   const base::TimeTicks capture_time = testing_clock_->NowTicks();
    288   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
    289 
    290   // ACK the key frame.
    291   RtcpCastMessage cast_feedback(1);
    292   cast_feedback.media_ssrc_ = 2;
    293   cast_feedback.ack_frame_id_ = 0;
    294   video_sender_->OnReceivedCastFeedback(cast_feedback);
    295 
    296   video_frame = GetNewVideoFrame();
    297   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
    298 
    299   base::TimeDelta max_resend_timeout =
    300       base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs);
    301 
    302   // Make sure that we do a re-send.
    303   RunTasks(max_resend_timeout.InMilliseconds());
    304   // Should have sent at least 3 packets.
    305   EXPECT_LE(
    306       3,
    307       transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
    308 }
    309 
    310 TEST_F(VideoSenderTest, LogAckReceivedEvent) {
    311   InitEncoder(false);
    312   SimpleEventSubscriber event_subscriber;
    313   cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
    314 
    315   int num_frames = 10;
    316   for (int i = 0; i < num_frames; i++) {
    317     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    318 
    319     const base::TimeTicks capture_time = testing_clock_->NowTicks();
    320     video_sender_->InsertRawVideoFrame(video_frame, capture_time);
    321     RunTasks(33);
    322   }
    323 
    324   task_runner_->RunTasks();
    325 
    326   RtcpCastMessage cast_feedback(1);
    327   cast_feedback.ack_frame_id_ = num_frames - 1;
    328 
    329   video_sender_->OnReceivedCastFeedback(cast_feedback);
    330 
    331   std::vector<FrameEvent> frame_events;
    332   event_subscriber.GetFrameEventsAndReset(&frame_events);
    333 
    334   ASSERT_TRUE(!frame_events.empty());
    335   EXPECT_EQ(FRAME_ACK_RECEIVED, frame_events.rbegin()->type);
    336   EXPECT_EQ(VIDEO_EVENT, frame_events.rbegin()->media_type);
    337   EXPECT_EQ(num_frames - 1u, frame_events.rbegin()->frame_id);
    338 
    339   cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
    340 }
    341 
    342 TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) {
    343   InitEncoder(false);
    344   // Send a stream of frames and don't ACK; by default we shouldn't have more
    345   // than 4 frames in flight.
    346   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    347   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    348   RunTasks(33);
    349 
    350   // Send 3 more frames and record the number of packets sent.
    351   for (int i = 0; i < 3; ++i) {
    352     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    353     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    354     RunTasks(33);
    355   }
    356   const int number_of_packets_sent = transport_.number_of_rtp_packets();
    357 
    358   // Send 3 more frames - they should not be encoded, as we have not received
    359   // any acks.
    360   for (int i = 0; i < 3; ++i) {
    361     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    362     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    363     RunTasks(33);
    364   }
    365 
    366   // We expect a frame to be retransmitted because of duplicated ACKs.
    367   // Only one packet of the frame is re-transmitted.
    368   EXPECT_EQ(number_of_packets_sent + 1,
    369             transport_.number_of_rtp_packets());
    370 
    371   // Start acking and make sure we're back to steady-state.
    372   RtcpCastMessage cast_feedback(1);
    373   cast_feedback.media_ssrc_ = 2;
    374   cast_feedback.ack_frame_id_ = 0;
    375   video_sender_->OnReceivedCastFeedback(cast_feedback);
    376   EXPECT_LE(
    377       4,
    378       transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
    379 
    380   // Empty the pipeline.
    381   RunTasks(100);
    382   // Should have sent at least 7 packets.
    383   EXPECT_LE(
    384       7,
    385       transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
    386 }
    387 
    388 TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
    389   InitEncoder(false);
    390   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    391   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    392   RunTasks(33);
    393   RtcpCastMessage cast_feedback(1);
    394   cast_feedback.media_ssrc_ = 2;
    395   cast_feedback.ack_frame_id_ = 0;
    396 
    397   // Send 3 more frames but don't ACK.
    398   for (int i = 0; i < 3; ++i) {
    399     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    400     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    401     RunTasks(33);
    402   }
    403   const int number_of_packets_sent = transport_.number_of_rtp_packets();
    404 
    405   // Send duplicated ACKs and mix some invalid NACKs.
    406   for (int i = 0; i < 10; ++i) {
    407     RtcpCastMessage ack_feedback(1);
    408     ack_feedback.media_ssrc_ = 2;
    409     ack_feedback.ack_frame_id_ = 0;
    410     RtcpCastMessage nack_feedback(1);
    411     nack_feedback.media_ssrc_ = 2;
    412     nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
    413     video_sender_->OnReceivedCastFeedback(ack_feedback);
    414     video_sender_->OnReceivedCastFeedback(nack_feedback);
    415   }
    416   EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
    417 
    418   // Re-transmit one packet because of duplicated ACKs.
    419   for (int i = 0; i < 3; ++i) {
    420     RtcpCastMessage ack_feedback(1);
    421     ack_feedback.media_ssrc_ = 2;
    422     ack_feedback.ack_frame_id_ = 0;
    423     video_sender_->OnReceivedCastFeedback(ack_feedback);
    424   }
    425   EXPECT_EQ(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
    426 }
    427 
    428 TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
    429   InitEncoder(false);
    430   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    431   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    432   RunTasks(33);
    433   RtcpCastMessage cast_feedback(1);
    434   cast_feedback.media_ssrc_ = 2;
    435   cast_feedback.ack_frame_id_ = 0;
    436 
    437   // Send 2 more frames but don't ACK.
    438   for (int i = 0; i < 2; ++i) {
    439     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
    440     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    441     RunTasks(33);
    442   }
    443   // Pause the transport
    444   transport_.SetPause(true);
    445 
    446   // Insert one more video frame.
    447   video_frame = GetLargeNewVideoFrame();
    448   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    449   RunTasks(33);
    450 
    451   const int number_of_packets_sent = transport_.number_of_rtp_packets();
    452 
    453   // Send duplicated ACKs and mix some invalid NACKs.
    454   for (int i = 0; i < 10; ++i) {
    455     RtcpCastMessage ack_feedback(1);
    456     ack_feedback.media_ssrc_ = 2;
    457     ack_feedback.ack_frame_id_ = 0;
    458     RtcpCastMessage nack_feedback(1);
    459     nack_feedback.media_ssrc_ = 2;
    460     nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
    461     video_sender_->OnReceivedCastFeedback(ack_feedback);
    462     video_sender_->OnReceivedCastFeedback(nack_feedback);
    463   }
    464   EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
    465 
    466   // Re-transmit one packet because of duplicated ACKs.
    467   for (int i = 0; i < 3; ++i) {
    468     RtcpCastMessage ack_feedback(1);
    469     ack_feedback.media_ssrc_ = 2;
    470     ack_feedback.ack_frame_id_ = 0;
    471     video_sender_->OnReceivedCastFeedback(ack_feedback);
    472   }
    473 
    474   transport_.SetPause(false);
    475   RunTasks(100);
    476   EXPECT_LT(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
    477 }
    478 
    479 TEST_F(VideoSenderTest, AcksCancelRetransmits) {
    480   InitEncoder(false);
    481   transport_.SetPause(true);
    482   scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
    483   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    484   RunTasks(33);
    485 
    486   // Frame should be in buffer, waiting. Now let's ack it.
    487   RtcpCastMessage cast_feedback(1);
    488   cast_feedback.media_ssrc_ = 2;
    489   cast_feedback.ack_frame_id_ = 0;
    490   video_sender_->OnReceivedCastFeedback(cast_feedback);
    491 
    492   transport_.SetPause(false);
    493   RunTasks(33);
    494   EXPECT_EQ(0, transport_.number_of_rtp_packets());
    495 }
    496 
    497 TEST_F(VideoSenderTest, NAcksCancelRetransmits) {
    498   InitEncoder(false);
    499   transport_.SetPause(true);
    500   // Send two video frames.
    501   scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
    502   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    503   RunTasks(33);
    504   video_frame = GetLargeNewVideoFrame();
    505   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
    506   RunTasks(33);
    507 
    508   // Frames should be in buffer, waiting. Now let's ack the first one and nack
    509   // one packet in the second one.
    510   RtcpCastMessage cast_feedback(1);
    511   cast_feedback.media_ssrc_ = 2;
    512   cast_feedback.ack_frame_id_ = 0;
    513   PacketIdSet missing_packets;
    514   missing_packets.insert(0);
    515   cast_feedback.missing_frames_and_packets_[1] = missing_packets;
    516   video_sender_->OnReceivedCastFeedback(cast_feedback);
    517 
    518   transport_.SetPause(false);
    519   RunTasks(33);
    520   // Only one packet should be retransmitted.
    521   EXPECT_EQ(1, transport_.number_of_rtp_packets());
    522 }
    523 
    524 }  // namespace cast
    525 }  // namespace media
    526