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 <vector> 6 7 #include "base/bind.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/test/simple_test_tick_clock.h" 10 #include "media/base/video_frame.h" 11 #include "media/cast/cast_environment.h" 12 #include "media/cast/net/pacing/mock_paced_packet_sender.h" 13 #include "media/cast/net/pacing/paced_sender.h" 14 #include "media/cast/test/fake_task_runner.h" 15 #include "media/cast/test/video_utility.h" 16 #include "media/cast/video_sender/mock_video_encoder_controller.h" 17 #include "media/cast/video_sender/video_sender.h" 18 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 namespace media { 22 namespace cast { 23 24 namespace { 25 static const int64 kStartMillisecond = GG_INT64_C(12345678900000); 26 static const uint8 kPixelValue = 123; 27 static const int kWidth = 320; 28 static const int kHeight = 240; 29 } 30 31 using testing::_; 32 using testing::AtLeast; 33 34 namespace { 35 class PeerVideoSender : public VideoSender { 36 public: 37 PeerVideoSender(scoped_refptr<CastEnvironment> cast_environment, 38 const VideoSenderConfig& video_config, 39 VideoEncoderController* const video_encoder_controller, 40 PacedPacketSender* const paced_packet_sender) 41 : VideoSender(cast_environment, video_config, 42 video_encoder_controller, paced_packet_sender) { 43 } 44 using VideoSender::OnReceivedCastFeedback; 45 }; 46 } // namespace 47 48 class VideoSenderTest : public ::testing::Test { 49 protected: 50 VideoSenderTest() { 51 testing_clock_.Advance( 52 base::TimeDelta::FromMilliseconds(kStartMillisecond)); 53 } 54 55 virtual ~VideoSenderTest() {} 56 57 void InitEncoder(bool external) { 58 VideoSenderConfig video_config; 59 video_config.sender_ssrc = 1; 60 video_config.incoming_feedback_ssrc = 2; 61 video_config.rtp_payload_type = 127; 62 video_config.use_external_encoder = external; 63 video_config.width = kWidth; 64 video_config.height = kHeight; 65 video_config.max_bitrate = 5000000; 66 video_config.min_bitrate = 1000000; 67 video_config.start_bitrate = 1000000; 68 video_config.max_qp = 56; 69 video_config.min_qp = 0; 70 video_config.max_frame_rate = 30; 71 video_config.max_number_of_video_buffers_used = 1; 72 video_config.codec = kVp8; 73 74 if (external) { 75 video_sender_.reset(new PeerVideoSender(cast_environment_, 76 video_config, &mock_video_encoder_controller_, &mock_transport_)); 77 } else { 78 video_sender_.reset(new PeerVideoSender(cast_environment_, video_config, 79 NULL, &mock_transport_)); 80 } 81 } 82 83 virtual void SetUp() { 84 task_runner_ = new test::FakeTaskRunner(&testing_clock_); 85 cast_environment_ = new CastEnvironment(&testing_clock_, task_runner_, 86 task_runner_, task_runner_, task_runner_, task_runner_, 87 GetDefaultCastLoggingConfig()); 88 } 89 90 scoped_refptr<media::VideoFrame> GetNewVideoFrame() { 91 gfx::Size size(kWidth, kHeight); 92 scoped_refptr<media::VideoFrame> video_frame = 93 media::VideoFrame::CreateFrame(VideoFrame::I420, size, gfx::Rect(size), 94 size, base::TimeDelta()); 95 PopulateVideoFrame(video_frame, kPixelValue); 96 return video_frame; 97 } 98 99 MockVideoEncoderController mock_video_encoder_controller_; 100 base::SimpleTestTickClock testing_clock_; 101 MockPacedPacketSender mock_transport_; 102 scoped_refptr<test::FakeTaskRunner> task_runner_; 103 scoped_ptr<PeerVideoSender> video_sender_; 104 scoped_refptr<CastEnvironment> cast_environment_; 105 }; 106 107 TEST_F(VideoSenderTest, BuiltInEncoder) { 108 EXPECT_CALL(mock_transport_, SendPackets(_)).Times(1); 109 110 InitEncoder(false); 111 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame(); 112 113 base::TimeTicks capture_time; 114 video_sender_->InsertRawVideoFrame(video_frame, capture_time); 115 116 task_runner_->RunTasks(); 117 } 118 119 TEST_F(VideoSenderTest, ExternalEncoder) { 120 EXPECT_CALL(mock_transport_, SendPackets(_)).Times(1); 121 EXPECT_CALL(mock_video_encoder_controller_, SkipNextFrame(false)).Times(1); 122 InitEncoder(true); 123 124 EncodedVideoFrame video_frame; 125 base::TimeTicks capture_time; 126 127 video_frame.codec = kVp8; 128 video_frame.key_frame = true; 129 video_frame.frame_id = 0; 130 video_frame.last_referenced_frame_id = 0; 131 video_frame.data.insert(video_frame.data.begin(), 1000, kPixelValue); 132 133 video_sender_->InsertCodedVideoFrame(&video_frame, capture_time, 134 base::Bind(base::DoNothing)); 135 } 136 137 TEST_F(VideoSenderTest, RtcpTimer) { 138 EXPECT_CALL(mock_transport_, SendPackets(_)).Times(AtLeast(1)); 139 EXPECT_CALL(mock_transport_, SendRtcpPacket(_)).Times(1); 140 EXPECT_CALL(mock_video_encoder_controller_, 141 SkipNextFrame(false)).Times(AtLeast(1)); 142 InitEncoder(true); 143 144 EncodedVideoFrame video_frame; 145 base::TimeTicks capture_time; 146 147 video_frame.codec = kVp8; 148 video_frame.key_frame = true; 149 video_frame.frame_id = 0; 150 video_frame.last_referenced_frame_id = 0; 151 video_frame.data.insert(video_frame.data.begin(), 1000, kPixelValue); 152 153 video_sender_->InsertCodedVideoFrame(&video_frame, capture_time, 154 base::Bind(base::DoNothing)); 155 156 // Make sure that we send at least one RTCP packet. 157 base::TimeDelta max_rtcp_timeout = 158 base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs * 3 / 2); 159 160 testing_clock_.Advance(max_rtcp_timeout); 161 task_runner_->RunTasks(); 162 } 163 164 TEST_F(VideoSenderTest, ResendTimer) { 165 EXPECT_CALL(mock_transport_, SendPackets(_)).Times(2); 166 EXPECT_CALL(mock_transport_, ResendPackets(_)).Times(1); 167 168 InitEncoder(false); 169 170 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame(); 171 172 base::TimeTicks capture_time; 173 video_sender_->InsertRawVideoFrame(video_frame, capture_time); 174 175 task_runner_->RunTasks(); 176 177 // ACK the key frame. 178 RtcpCastMessage cast_feedback(1); 179 cast_feedback.media_ssrc_ = 2; 180 cast_feedback.ack_frame_id_ = 0; 181 video_sender_->OnReceivedCastFeedback(cast_feedback); 182 183 video_frame = GetNewVideoFrame(); 184 video_sender_->InsertRawVideoFrame(video_frame, capture_time); 185 186 task_runner_->RunTasks(); 187 188 base::TimeDelta max_resend_timeout = 189 base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs); 190 191 // Make sure that we do a re-send. 192 testing_clock_.Advance(max_resend_timeout); 193 task_runner_->RunTasks(); 194 } 195 196 } // namespace cast 197 } // namespace media 198 199