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:
PeerVideoSender(scoped_refptr<CastEnvironment> cast_environment,const VideoSenderConfig & video_config,VideoEncoderController * const video_encoder_controller,PacedPacketSender * const paced_packet_sender)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:
VideoSenderTest()50 VideoSenderTest() {
51 testing_clock_.Advance(
52 base::TimeDelta::FromMilliseconds(kStartMillisecond));
53 }
54
~VideoSenderTest()55 virtual ~VideoSenderTest() {}
56
InitEncoder(bool external)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
SetUp()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
GetNewVideoFrame()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
TEST_F(VideoSenderTest,BuiltInEncoder)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
TEST_F(VideoSenderTest,ExternalEncoder)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
TEST_F(VideoSenderTest,RtcpTimer)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
TEST_F(VideoSenderTest,ResendTimer)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