OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
xjz
2016/09/15 18:01:49
Great job! Awesome tests!!! :)
| |
4 | 4 |
5 #include "chrome/browser/media/cast_remoting_sender.h" | 5 #include "chrome/browser/media/cast_remoting_sender.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | |
9 #include "base/callback_helpers.h" | |
10 #include "base/compiler_specific.h" | |
8 #include "base/macros.h" | 11 #include "base/macros.h" |
9 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
10 #include "base/test/simple_test_tick_clock.h" | 13 #include "base/run_loop.h" |
11 #include "media/base/fake_single_thread_task_runner.h" | 14 #include "base/time/default_tick_clock.h" |
15 #include "content/public/test/test_browser_thread_bundle.h" | |
12 #include "media/cast/cast_environment.h" | 16 #include "media/cast/cast_environment.h" |
13 #include "media/cast/constants.h" | 17 #include "media/cast/constants.h" |
14 #include "media/cast/logging/simple_event_subscriber.h" | 18 #include "media/cast/net/cast_transport.h" |
15 #include "media/cast/net/cast_transport_config.h" | |
16 #include "media/cast/net/cast_transport_impl.h" | |
17 #include "media/cast/net/pacing/paced_sender.h" | |
18 #include "media/cast/test/utility/default_config.h" | 19 #include "media/cast/test/utility/default_config.h" |
19 #include "testing/gmock/include/gmock/gmock.h" | 20 #include "media/mojo/interfaces/remoting.mojom.h" |
21 #include "mojo/public/cpp/system/data_pipe.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
21 | 23 |
22 namespace cast { | 24 namespace cast { |
23 | 25 |
24 namespace { | 26 namespace { |
25 | 27 |
26 // Number of bytes in each faked frame. | 28 // Data pipe capacity is 1KB. |
27 constexpr int kFrameSize = 5000; | 29 constexpr int kDataPipeCapacity = 1024; |
28 | 30 |
29 class TestPacketSender : public media::cast::PacketTransport { | 31 // Implements the CastTransport interface to capture output from the |
32 // CastRemotingSender. | |
33 class FakeTransport : public media::cast::CastTransport { | |
30 public: | 34 public: |
31 TestPacketSender() | 35 FakeTransport() {} |
32 : number_of_rtp_packets_(0), number_of_rtcp_packets_(0), paused_(false) {} | 36 ~FakeTransport() final {} |
33 | 37 |
34 // A singular packet implies a RTCP packet. | 38 void TakeSentFrames(std::vector<media::cast::EncodedFrame>* frames) { |
35 bool SendPacket(media::cast::PacketRef packet, | 39 frames->swap(sent_frames_); |
36 const base::Closure& cb) final { | 40 sent_frames_.clear(); |
37 if (paused_) { | |
38 stored_packet_ = packet; | |
39 callback_ = cb; | |
40 return false; | |
41 } | |
42 if (media::cast::IsRtcpPacket(&packet->data[0], packet->data.size())) { | |
43 ++number_of_rtcp_packets_; | |
44 } else { | |
45 ++number_of_rtp_packets_; | |
46 } | |
47 return true; | |
48 } | 41 } |
49 | 42 |
50 int64_t GetBytesSent() final { return 0; } | 43 void TakeCanceledFrameIds(std::vector<media::cast::FrameId>* frame_ids) { |
51 | 44 frame_ids->swap(canceled_frame_ids_); |
52 void StartReceiving(const media::cast::PacketReceiverCallbackWithStatus& | 45 canceled_frame_ids_.clear(); |
53 packet_receiver) final {} | |
54 | |
55 void StopReceiving() final {} | |
56 | |
57 int number_of_rtp_packets() const { return number_of_rtp_packets_; } | |
58 | |
59 int number_of_rtcp_packets() const { return number_of_rtcp_packets_; } | |
60 | |
61 void SetPause(bool paused) { | |
62 paused_ = paused; | |
63 if (!paused && stored_packet_.get()) { | |
64 SendPacket(stored_packet_, callback_); | |
65 callback_.Run(); | |
66 } | |
67 } | 46 } |
68 | 47 |
48 media::cast::FrameId WaitForKickstart() { | |
49 base::RunLoop run_loop; | |
50 kickstarted_callback_ = run_loop.QuitClosure(); | |
51 run_loop.Run(); | |
52 return kickstarted_frame_id_; | |
53 } | |
54 | |
55 protected: | |
56 void InsertFrame(uint32_t ssrc, | |
57 const media::cast::EncodedFrame& frame) final { | |
58 sent_frames_.push_back(frame); | |
59 } | |
60 | |
61 void CancelSendingFrames( | |
62 uint32_t ssrc, const std::vector<media::cast::FrameId>& frame_ids) final { | |
63 for (media::cast::FrameId frame_id : frame_ids) | |
64 canceled_frame_ids_.push_back(frame_id); | |
65 } | |
66 | |
67 void ResendFrameForKickstart(uint32_t ssrc, | |
68 media::cast::FrameId frame_id) final { | |
69 kickstarted_frame_id_ = frame_id; | |
70 if (!kickstarted_callback_.is_null()) | |
71 base::ResetAndReturn(&kickstarted_callback_).Run(); | |
72 } | |
73 | |
74 // The rest of the interface is not used for these tests. | |
75 void SendSenderReport( | |
76 uint32_t ssrc, base::TimeTicks current_time, | |
77 media::cast::RtpTimeTicks current_time_as_rtp_timestamp) final {} | |
78 void AddValidRtpReceiver(uint32_t rtp_sender_ssrc, | |
79 uint32_t rtp_receiver_ssrc) final {} | |
80 void InitializeRtpReceiverRtcpBuilder( | |
81 uint32_t rtp_receiver_ssrc, | |
82 const media::cast::RtcpTimeData& time_data) final {} | |
83 void AddCastFeedback(const media::cast::RtcpCastMessage& cast_message, | |
84 base::TimeDelta target_delay) final {} | |
85 void AddPli(const media::cast::RtcpPliMessage& pli_message) final {} | |
86 void AddRtcpEvents( | |
87 const media::cast::ReceiverRtcpEventSubscriber::RtcpEvents& e) final {} | |
88 void AddRtpReceiverReport(const media::cast::RtcpReportBlock& b) final {} | |
89 void SendRtcpFromRtpReceiver() final {} | |
90 void SetOptions(const base::DictionaryValue& options) final {} | |
91 | |
69 private: | 92 private: |
70 int number_of_rtp_packets_; | 93 const scoped_refptr<media::cast::CastEnvironment> cast_environment_; |
71 int number_of_rtcp_packets_; | 94 std::vector<media::cast::EncodedFrame> sent_frames_; |
72 bool paused_; | 95 std::vector<media::cast::FrameId> canceled_frame_ids_; |
73 base::Closure callback_; | |
74 media::cast::PacketRef stored_packet_; | |
75 | 96 |
76 DISALLOW_COPY_AND_ASSIGN(TestPacketSender); | 97 base::Closure kickstarted_callback_; |
77 }; | 98 media::cast::FrameId kickstarted_frame_id_; |
78 | 99 |
79 class DummyClient : public media::cast::CastTransport::Client { | 100 DISALLOW_COPY_AND_ASSIGN(FakeTransport); |
80 public: | |
81 DummyClient() {} | |
82 | |
83 void OnStatusChanged(media::cast::CastTransportStatus status) final { | |
84 EXPECT_EQ(media::cast::TRANSPORT_STREAM_INITIALIZED, status); | |
85 }; | |
86 void OnLoggingEventsReceived( | |
87 std::unique_ptr<std::vector<media::cast::FrameEvent>> frame_events, | |
88 std::unique_ptr<std::vector<media::cast::PacketEvent>> packet_events) | |
89 final {} | |
90 void ProcessRtpPacket(std::unique_ptr<media::cast::Packet> packet) final {} | |
91 | |
92 DISALLOW_COPY_AND_ASSIGN(DummyClient); | |
93 }; | 101 }; |
94 | 102 |
95 } // namespace | 103 } // namespace |
96 | 104 |
97 class CastRemotingSenderTest : public ::testing::Test { | 105 class CastRemotingSenderTest : public ::testing::Test { |
98 protected: | 106 protected: |
99 CastRemotingSenderTest() | 107 CastRemotingSenderTest() |
100 : testing_clock_(new base::SimpleTestTickClock()), | 108 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
101 task_runner_(new media::FakeSingleThreadTaskRunner(testing_clock_)), | 109 cast_environment_(new media::cast::CastEnvironment( |
102 cast_environment_( | 110 base::WrapUnique(new base::DefaultTickClock()), |
103 new media::cast::CastEnvironment(base::WrapUnique(testing_clock_), | 111 base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr)), |
104 task_runner_, | 112 expecting_error_callback_run_(false) { |
105 task_runner_, | 113 |
106 task_runner_)) { | |
107 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); | |
108 transport_ = new TestPacketSender(); | |
109 transport_sender_.reset(new media::cast::CastTransportImpl( | |
110 testing_clock_, base::TimeDelta(), base::MakeUnique<DummyClient>(), | |
111 base::WrapUnique(transport_), task_runner_)); | |
112 media::cast::FrameSenderConfig video_config = | 114 media::cast::FrameSenderConfig video_config = |
113 media::cast::GetDefaultVideoSenderConfig(); | 115 media::cast::GetDefaultVideoSenderConfig(); |
114 video_config.rtp_payload_type = media::cast::RtpPayloadType::REMOTE_VIDEO; | 116 video_config.rtp_payload_type = media::cast::RtpPayloadType::REMOTE_VIDEO; |
115 media::cast::CastTransportRtpConfig transport_config; | 117 transport_config_.ssrc = video_config.sender_ssrc; |
116 transport_config.ssrc = video_config.sender_ssrc; | 118 transport_config_.rtp_stream_id = 5; |
117 transport_config.rtp_stream_id = 5; | 119 transport_config_.feedback_ssrc = video_config.receiver_ssrc; |
118 transport_config.feedback_ssrc = video_config.receiver_ssrc; | 120 transport_config_.rtp_payload_type = video_config.rtp_payload_type; |
119 transport_config.rtp_payload_type = video_config.rtp_payload_type; | 121 transport_config_.aes_key = video_config.aes_key; |
120 transport_config.aes_key = video_config.aes_key; | 122 transport_config_.aes_iv_mask = video_config.aes_iv_mask; |
121 transport_config.aes_iv_mask = video_config.aes_iv_mask; | |
122 remoting_sender_.reset(new CastRemotingSender( | 123 remoting_sender_.reset(new CastRemotingSender( |
123 cast_environment_, transport_sender_.get(), transport_config)); | 124 cast_environment_, &transport_, transport_config_)); |
124 task_runner_->RunTasks(); | 125 // Give CastRemotingSender a small RTT measurement to prevent kickstart |
126 // testing from taking too long. | |
127 remoting_sender_->OnReceivedRtt(base::TimeDelta::FromMilliseconds(1)); | |
128 | |
129 const MojoCreateDataPipeOptions data_pipe_options{ | |
130 sizeof(MojoCreateDataPipeOptions), | |
131 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, kDataPipeCapacity }; | |
132 mojo::ScopedDataPipeConsumerHandle consumer_end; | |
133 CHECK_EQ(MOJO_RESULT_OK, | |
134 mojo::CreateDataPipe(&data_pipe_options, &producer_end_, | |
135 &consumer_end)); | |
136 | |
137 CastRemotingSender::FindAndBind( | |
138 transport_config_.rtp_stream_id, std::move(consumer_end), | |
139 GetProxy(&sender_), | |
140 base::Bind(&CastRemotingSenderTest::OnError, base::Unretained(this))); | |
141 | |
142 RunPendingTasks(); | |
125 } | 143 } |
126 | 144 |
127 ~CastRemotingSenderTest() override {} | 145 ~CastRemotingSenderTest() override {} |
128 | 146 |
129 void TearDown() final { | 147 void TearDown() final { |
130 remoting_sender_.reset(); | 148 remoting_sender_.reset(); |
131 task_runner_->RunTasks(); | 149 // Allow any pending tasks to run before destruction. |
132 } | 150 RunPendingTasks(); |
133 | 151 } |
134 void InsertFrame() { | 152 |
135 remoting_sender_->next_frame_data_.resize(kFrameSize); | 153 // Allow pending tasks, such as Mojo method calls, to execute. |
136 remoting_sender_->SendFrame(); | 154 static void RunPendingTasks() { |
137 } | 155 base::RunLoop().RunUntilIdle(); |
138 | 156 } |
139 void OnReceivedCastMessage( | 157 |
140 const media::cast::RtcpCastMessage& cast_feedback) { | 158 protected: |
141 remoting_sender_->OnReceivedCastMessage(cast_feedback); | 159 media::cast::FrameId latest_acked_frame_id() const { |
160 return remoting_sender_->latest_acked_frame_id_; | |
142 } | 161 } |
143 | 162 |
144 int NumberOfFramesInFlight() { | 163 int NumberOfFramesInFlight() { |
145 return remoting_sender_->NumberOfFramesInFlight(); | 164 return remoting_sender_->NumberOfFramesInFlight(); |
146 } | 165 } |
147 | 166 |
148 void CancelFramesInFlight() { remoting_sender_->CancelFramesInFlight(); } | 167 size_t GetSizeOfNextFrameData() { |
149 | 168 return remoting_sender_->next_frame_data_.size(); |
150 base::SimpleTestTickClock* const testing_clock_; // Owned by CastEnvironment. | 169 } |
151 const scoped_refptr<media::FakeSingleThreadTaskRunner> task_runner_; | 170 |
171 bool IsFlowControlInRestartingState() const { | |
172 return remoting_sender_->flow_control_state_ == | |
173 CastRemotingSender::RESTARTING; | |
174 } | |
175 bool IsFlowControlInConsumingState() const { | |
176 return remoting_sender_->flow_control_state_ == | |
177 CastRemotingSender::CONSUMING; | |
178 } | |
179 bool IsFlowControlInPausedState() const { | |
180 return remoting_sender_->flow_control_state_ == | |
181 CastRemotingSender::CONSUME_PAUSED; | |
182 } | |
183 | |
184 bool ProduceDataChunk(size_t offset, size_t size) WARN_UNUSED_RESULT { | |
185 std::vector<uint8_t> fake_chunk(size); | |
186 for (size_t i = 0; i < size; ++i) | |
187 fake_chunk[i] = static_cast<uint8_t>(offset + i); | |
188 uint32_t num_bytes = fake_chunk.size(); | |
189 return mojo::WriteDataRaw( | |
190 producer_end_.get(), fake_chunk.data(), &num_bytes, | |
191 MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) == MOJO_RESULT_OK; | |
192 } | |
193 | |
194 void PostMojoCallTask_ConsumeDataChunk(size_t offset, size_t size, | |
195 size_t total_payload_size) { | |
196 sender_->ConsumeDataChunk(offset, size, total_payload_size); | |
197 } | |
198 | |
199 void PostMojoCallTask_SendFrame() { | |
200 sender_->SendFrame(); | |
201 } | |
202 | |
203 void PostMojoCallTask_CancelInFlightData() { sender_->CancelInFlightData(); } | |
204 | |
205 void TakeSentFrames(std::vector<media::cast::EncodedFrame>* frames) { | |
206 transport_.TakeSentFrames(frames); | |
207 } | |
208 | |
209 bool ExpectOneFrameWasSent(size_t expected_payload_size) { | |
210 std::vector<media::cast::EncodedFrame> frames; | |
211 transport_.TakeSentFrames(&frames); | |
212 EXPECT_EQ(1u, frames.size()); | |
213 if (frames.empty()) | |
214 return false; | |
215 return ExpectCorrectFrameData(expected_payload_size, frames.front()); | |
216 } | |
217 | |
218 void AckUpToAndIncluding(media::cast::FrameId frame_id) { | |
219 media::cast::RtcpCastMessage cast_feedback(transport_config_.feedback_ssrc); | |
220 cast_feedback.ack_frame_id = frame_id; | |
221 remoting_sender_->OnReceivedCastMessage(cast_feedback); | |
222 } | |
223 | |
224 void AckOldestInFlightFrames(int count) { | |
225 AckUpToAndIncluding(latest_acked_frame_id() + count); | |
226 } | |
227 | |
228 // Blocks the caller indefinitely, until a kickstart frame is sent, and then | |
229 // returns the FrameId of the kickstarted-frame. | |
230 media::cast::FrameId WaitForKickstart() { | |
231 return transport_.WaitForKickstart(); | |
232 } | |
233 | |
234 bool ExpectNoFramesCanceled() { | |
235 std::vector<media::cast::FrameId> frame_ids; | |
236 transport_.TakeCanceledFrameIds(&frame_ids); | |
237 return frame_ids.empty(); | |
238 } | |
239 | |
240 bool ExpectFramesCanceled(media::cast::FrameId first_frame_id, | |
241 media::cast::FrameId last_frame_id) { | |
242 std::vector<media::cast::FrameId> frame_ids; | |
243 transport_.TakeCanceledFrameIds(&frame_ids); | |
244 auto begin = frame_ids.begin(); | |
245 auto end = frame_ids.end(); | |
246 for (auto fid = first_frame_id; fid <= last_frame_id; ++fid) { | |
247 auto new_end = std::remove(begin, end, fid); | |
248 if (new_end == end) | |
249 return false; | |
250 end = new_end; | |
251 } | |
252 return begin == end; | |
253 } | |
254 | |
255 static bool ExpectCorrectFrameData(size_t expected_payload_size, | |
256 const media::cast::EncodedFrame& frame) { | |
257 if (expected_payload_size != frame.data.size()) { | |
258 ADD_FAILURE() << "Expected frame data size != frame.data.size(): " | |
259 << expected_payload_size << " vs " << frame.data.size(); | |
260 return false; | |
261 } | |
262 for (size_t i = 0; i < expected_payload_size; ++i) { | |
263 if (static_cast<uint8_t>(frame.data[i]) != static_cast<uint8_t>(i)) { | |
264 ADD_FAILURE() << "Frame data byte mismatch at offset " << i; | |
265 return false; | |
266 } | |
267 } | |
268 return true; | |
269 } | |
270 | |
271 private: | |
272 void OnError() { | |
273 CHECK(expecting_error_callback_run_); | |
274 } | |
275 | |
276 content::TestBrowserThreadBundle thread_bundle_; | |
152 const scoped_refptr<media::cast::CastEnvironment> cast_environment_; | 277 const scoped_refptr<media::cast::CastEnvironment> cast_environment_; |
153 TestPacketSender* transport_; // Owned by CastTransport. | 278 media::cast::CastTransportRtpConfig transport_config_; |
154 std::unique_ptr<media::cast::CastTransportImpl> transport_sender_; | 279 FakeTransport transport_; |
155 std::unique_ptr<CastRemotingSender> remoting_sender_; | 280 std::unique_ptr<CastRemotingSender> remoting_sender_; |
281 media::mojom::RemotingDataStreamSenderPtr sender_; | |
282 mojo::ScopedDataPipeProducerHandle producer_end_; | |
283 bool expecting_error_callback_run_; | |
156 | 284 |
157 private: | 285 private: |
158 DISALLOW_COPY_AND_ASSIGN(CastRemotingSenderTest); | 286 DISALLOW_COPY_AND_ASSIGN(CastRemotingSenderTest); |
159 }; | 287 }; |
160 | 288 |
161 TEST_F(CastRemotingSenderTest, SendAndAckEncodedFrame) { | 289 TEST_F(CastRemotingSenderTest, SendsFramesViaMojoInterface) { |
162 // Send a fake video frame that will be decomposed into 4 packets. | 290 // One 256-byte chunk pushed through the data pipe to make one frame. |
163 InsertFrame(); | 291 ASSERT_TRUE(ProduceDataChunk(0, 256)); |
164 task_runner_->RunTasks(); | 292 PostMojoCallTask_ConsumeDataChunk(0, 256, 256); |
165 EXPECT_EQ(4, transport_->number_of_rtp_packets()); | 293 PostMojoCallTask_SendFrame(); |
294 RunPendingTasks(); | |
295 EXPECT_TRUE(ExpectOneFrameWasSent(256)); | |
296 AckOldestInFlightFrames(1); | |
297 EXPECT_EQ(media::cast::FrameId::first(), latest_acked_frame_id()); | |
298 | |
299 // Four 256-byte chunks pushed through the data pipe to make one frame. | |
300 for (int i = 0; i < 4; ++i) { | |
301 ASSERT_TRUE(ProduceDataChunk(i * 256, 256)); | |
302 PostMojoCallTask_ConsumeDataChunk(i * 256, 256, 1024); | |
303 } | |
304 PostMojoCallTask_SendFrame(); | |
305 RunPendingTasks(); | |
306 EXPECT_TRUE(ExpectOneFrameWasSent(1024)); | |
307 AckOldestInFlightFrames(1); | |
308 EXPECT_EQ(media::cast::FrameId::first() + 1, latest_acked_frame_id()); | |
309 | |
310 // 10 differently-sized chunks pushed through the data pipe to make one frame | |
311 // that is larger than the data pipe's total capacity. | |
312 size_t offset = 0; | |
313 for (int i = 0; i < 10; ++i) { | |
314 const size_t chunk_size = 500 + i * 37; | |
315 ASSERT_TRUE(ProduceDataChunk(offset, chunk_size)); | |
316 PostMojoCallTask_ConsumeDataChunk(offset, chunk_size, 6665); | |
317 RunPendingTasks(); | |
318 offset += chunk_size; | |
319 } | |
320 PostMojoCallTask_SendFrame(); | |
321 RunPendingTasks(); | |
322 EXPECT_TRUE(ExpectOneFrameWasSent(6665)); | |
323 AckOldestInFlightFrames(1); | |
324 EXPECT_EQ(media::cast::FrameId::first() + 2, latest_acked_frame_id()); | |
325 } | |
326 | |
327 TEST_F(CastRemotingSenderTest, SendsMultipleFramesWithDelayedAcks) { | |
328 // Send 4 frames. | |
329 for (int i = 0; i < 4; ++i) { | |
330 ASSERT_TRUE(ProduceDataChunk(0, 16)); | |
331 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); | |
332 PostMojoCallTask_SendFrame(); | |
333 } | |
334 RunPendingTasks(); | |
335 EXPECT_EQ(4, NumberOfFramesInFlight()); | |
336 EXPECT_TRUE(ExpectNoFramesCanceled()); | |
337 | |
338 // Ack one frame. | |
339 AckOldestInFlightFrames(1); | |
340 EXPECT_EQ(3, NumberOfFramesInFlight()); | |
341 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first(), | |
342 media::cast::FrameId::first())); | |
343 | |
344 // Ack all. | |
345 AckOldestInFlightFrames(3); | |
346 EXPECT_EQ(0, NumberOfFramesInFlight()); | |
347 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first() + 1, | |
348 media::cast::FrameId::first() + 3)); | |
349 } | |
350 | |
351 TEST_F(CastRemotingSenderTest, KickstartsIfAckNotTimely) { | |
352 // Send first frame and don't Ack it. Expect the first frame to be | |
353 // kickstarted. | |
354 ASSERT_TRUE(ProduceDataChunk(0, 16)); | |
355 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); | |
356 PostMojoCallTask_SendFrame(); | |
357 EXPECT_EQ(media::cast::FrameId::first(), WaitForKickstart()); | |
166 EXPECT_EQ(1, NumberOfFramesInFlight()); | 358 EXPECT_EQ(1, NumberOfFramesInFlight()); |
167 | 359 |
168 // Ack the frame. | 360 // Send 3 more frames and don't Ack them either. Expect the 4th frame to be |
169 media::cast::RtcpCastMessage cast_feedback(11); | 361 // kickstarted. |
170 cast_feedback.ack_frame_id = media::cast::FrameId::first(); | 362 for (int i = 0; i < 3; ++i) { |
171 OnReceivedCastMessage(cast_feedback); | 363 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
364 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); | |
365 PostMojoCallTask_SendFrame(); | |
366 } | |
367 EXPECT_EQ(media::cast::FrameId::first() + 3, WaitForKickstart()); | |
368 EXPECT_EQ(4, NumberOfFramesInFlight()); | |
369 | |
370 // Ack the first two frames and wait for another kickstart (for the 4th frame | |
371 // again). | |
372 AckOldestInFlightFrames(2); | |
373 EXPECT_EQ(2, NumberOfFramesInFlight()); | |
374 EXPECT_EQ(media::cast::FrameId::first() + 3, WaitForKickstart()); | |
375 } | |
376 | |
377 TEST_F(CastRemotingSenderTest, CancelsUnsentFrame) { | |
378 EXPECT_EQ(0u, GetSizeOfNextFrameData()); | |
379 ASSERT_TRUE(ProduceDataChunk(0, 16)); | |
380 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); | |
381 RunPendingTasks(); | |
382 EXPECT_EQ(16u, GetSizeOfNextFrameData()); | |
383 PostMojoCallTask_CancelInFlightData(); | |
384 RunPendingTasks(); | |
385 EXPECT_EQ(0u, GetSizeOfNextFrameData()); | |
386 | |
387 // Since no frames were sent, none should have been passed to the | |
388 // CastTransport, and none should have been canceled. | |
389 std::vector<media::cast::EncodedFrame> frames; | |
390 TakeSentFrames(&frames); | |
391 EXPECT_TRUE(frames.empty()); | |
392 EXPECT_TRUE(ExpectNoFramesCanceled()); | |
393 } | |
394 | |
395 TEST_F(CastRemotingSenderTest, CancelsFramesInFlight) { | |
396 EXPECT_TRUE(IsFlowControlInRestartingState()); | |
397 | |
398 // Send 10 frames. | |
399 for (int i = 0; i < 10; ++i) { | |
400 ASSERT_TRUE(ProduceDataChunk(0, 16)); | |
401 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); | |
402 PostMojoCallTask_SendFrame(); | |
403 } | |
404 RunPendingTasks(); | |
405 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
406 EXPECT_EQ(10, NumberOfFramesInFlight()); | |
407 | |
408 // Ack the first frame. | |
409 AckOldestInFlightFrames(1); | |
410 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
411 EXPECT_EQ(9, NumberOfFramesInFlight()); | |
412 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first(), | |
413 media::cast::FrameId::first())); | |
414 | |
415 // Cancel all in-flight data. This should cause the remaining 9 frames to be | |
416 // canceled. | |
417 PostMojoCallTask_CancelInFlightData(); | |
418 RunPendingTasks(); | |
419 EXPECT_TRUE(IsFlowControlInRestartingState()); | |
172 EXPECT_EQ(0, NumberOfFramesInFlight()); | 420 EXPECT_EQ(0, NumberOfFramesInFlight()); |
173 | 421 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first() + 1, |
174 // Send 4 frames. | 422 media::cast::FrameId::first() + 9)); |
175 for (int i = 0; i < 4; ++i) | 423 |
176 InsertFrame(); | 424 // Send one more frame and ack it. |
177 EXPECT_EQ(4, NumberOfFramesInFlight()); | 425 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
178 // Ack one frame. | 426 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); |
179 cast_feedback.ack_frame_id = media::cast::FrameId::first() + 1; | 427 PostMojoCallTask_SendFrame(); |
180 OnReceivedCastMessage(cast_feedback); | 428 RunPendingTasks(); |
181 EXPECT_EQ(3, NumberOfFramesInFlight()); | 429 EXPECT_TRUE(IsFlowControlInConsumingState()); |
182 // Ack all. | 430 EXPECT_EQ(1, NumberOfFramesInFlight()); |
183 cast_feedback.received_later_frames.clear(); | 431 AckOldestInFlightFrames(1); |
184 cast_feedback.ack_frame_id = media::cast::FrameId::first() + 4; | |
185 OnReceivedCastMessage(cast_feedback); | |
186 EXPECT_EQ(0, NumberOfFramesInFlight()); | 432 EXPECT_EQ(0, NumberOfFramesInFlight()); |
187 } | 433 |
188 | 434 // Check that the dependency metadata was set correctly to indicate a frame |
189 TEST_F(CastRemotingSenderTest, CancelFramesInFlight) { | 435 // that immediately follows a CancelInFlightData() operation. |
190 for (int i = 0; i < 10; ++i) | 436 std::vector<media::cast::EncodedFrame> frames; |
191 InsertFrame(); | 437 TakeSentFrames(&frames); |
192 EXPECT_EQ(10, NumberOfFramesInFlight()); | 438 ASSERT_EQ(11u, frames.size()); |
193 | 439 for (size_t i = 0; i < 11; ++i) { |
194 media::cast::RtcpCastMessage cast_feedback(11); | 440 const media::cast::EncodedFrame& frame = frames[i]; |
195 cast_feedback.ack_frame_id = media::cast::FrameId::first(); | 441 EXPECT_EQ(media::cast::FrameId::first() + i, frame.frame_id); |
196 OnReceivedCastMessage(cast_feedback); | 442 if (i == 0 || i == 10) |
197 EXPECT_EQ(9, NumberOfFramesInFlight()); | 443 EXPECT_EQ(media::cast::EncodedFrame::KEY, frame.dependency); |
198 | 444 else |
199 CancelFramesInFlight(); | 445 EXPECT_EQ(media::cast::EncodedFrame::DEPENDENT, frame.dependency); |
446 } | |
447 } | |
448 | |
449 TEST_F(CastRemotingSenderTest, ManagesFlowControl) { | |
450 EXPECT_TRUE(IsFlowControlInRestartingState()); | |
451 | |
452 // Send out a the maximum possible number of unacked frames, but don't ack any | |
453 // yet. | |
454 for (int i = 0; i < media::cast::kMaxUnackedFrames; ++i) { | |
455 ASSERT_TRUE(ProduceDataChunk(0, 4)); | |
456 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); | |
457 PostMojoCallTask_SendFrame(); | |
458 } | |
459 RunPendingTasks(); | |
460 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
461 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); | |
462 // Note: All frames should have been sent to the Transport, and so | |
463 // CastRemotingSender's single-frame data buffer should be empty. | |
464 EXPECT_EQ(0u, GetSizeOfNextFrameData()); | |
465 | |
466 // Attempting to send the next frame will place the CastRemotingSenderTest in | |
467 // a "paused flow" state. | |
468 ASSERT_TRUE(ProduceDataChunk(0, 4)); | |
469 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); | |
470 PostMojoCallTask_SendFrame(); | |
471 RunPendingTasks(); | |
472 EXPECT_TRUE(IsFlowControlInPausedState()); | |
473 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); | |
474 // Note: The unsent frame resides in CastRemotingSender's single-frame data | |
475 // buffer. | |
476 EXPECT_EQ(4u, GetSizeOfNextFrameData()); | |
477 | |
478 // Ack the the first frame and expect sending to resume, starting with the | |
479 // frame that triggered the pause. | |
480 AckOldestInFlightFrames(1); | |
481 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
482 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); | |
483 // Note: The frame causing the earlier pause should have been sent, and so | |
484 // CastRemotingSender's single-frame data buffer should now be empty. | |
485 EXPECT_EQ(0u, GetSizeOfNextFrameData()); | |
486 | |
487 // Attempting to send another frame will once again place the | |
488 // CastRemotingSender in a "paused flow" state. | |
489 ASSERT_TRUE(ProduceDataChunk(0, 4)); | |
490 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); | |
491 PostMojoCallTask_SendFrame(); | |
492 RunPendingTasks(); | |
493 EXPECT_TRUE(IsFlowControlInPausedState()); | |
494 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); | |
495 // Note: Once again, CastRemotingSender's single-frame data buffer contains an | |
496 // unsent frame. | |
497 EXPECT_EQ(4u, GetSizeOfNextFrameData()); | |
498 | |
499 // Send more frames: Some number of frames will queue-up inside the Mojo data | |
500 // pipe (the exact number depends on the data pipe's capacity, and how Mojo | |
501 // manages memory internally). At some point, attempting to produce and push | |
502 // another frame will fail because the data pipe is full. | |
503 int num_frames_in_data_pipe = 0; | |
504 while (ProduceDataChunk(0, 768)) { | |
505 ++num_frames_in_data_pipe; | |
506 PostMojoCallTask_ConsumeDataChunk(0, 768, 768); | |
507 PostMojoCallTask_SendFrame(); | |
508 RunPendingTasks(); | |
509 EXPECT_TRUE(IsFlowControlInPausedState()); | |
510 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); | |
511 // Note: CastRemotingSender's single-frame data buffer should still contain | |
512 // the unsent 4-byte frame. | |
513 EXPECT_EQ(4u, GetSizeOfNextFrameData()); | |
514 } | |
515 EXPECT_LT(0, num_frames_in_data_pipe); | |
516 | |
517 // Ack one frame at a time until the backlog in the Mojo data pipe has | |
518 // cleared. In each iteration, the flow will resume, but then it will become | |
519 // paused again when Mojo method calls are resumed and cause | |
520 // CastRemotingSender to pull another frame out of the data pipe. | |
521 int remaining_frames_in_data_pipe = num_frames_in_data_pipe; | |
522 while (remaining_frames_in_data_pipe > 0) { | |
523 AckOldestInFlightFrames(1); | |
524 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
525 EXPECT_EQ(0u, GetSizeOfNextFrameData()); | |
526 // The following will execute one ConsumeDataChunk() and one SendFrame() | |
527 // Mojo method call. | |
528 RunPendingTasks(); | |
529 --remaining_frames_in_data_pipe; | |
530 EXPECT_TRUE(IsFlowControlInPausedState()); | |
531 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); | |
532 EXPECT_EQ(768u, GetSizeOfNextFrameData()); | |
533 } | |
534 | |
535 // Ack one more frame. This should cause the flow to resume since there are no | |
536 // longer any frames backlogged on the input side of things. | |
537 AckOldestInFlightFrames(1); | |
538 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
539 RunPendingTasks(); // No additional Mojo method calls should be made here. | |
540 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
541 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); | |
542 EXPECT_EQ(0u, GetSizeOfNextFrameData()); | |
543 | |
544 // Ack all but one frame. | |
545 AckOldestInFlightFrames(NumberOfFramesInFlight() - 1); | |
546 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
547 EXPECT_EQ(1, NumberOfFramesInFlight()); | |
548 // ..and one more frame can be sent without pausing. | |
549 ASSERT_TRUE(ProduceDataChunk(0, 4)); | |
550 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); | |
551 PostMojoCallTask_SendFrame(); | |
552 RunPendingTasks(); | |
553 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
554 EXPECT_EQ(2, NumberOfFramesInFlight()); | |
555 // ...and ack these last two frames. | |
556 AckOldestInFlightFrames(2); | |
557 EXPECT_TRUE(IsFlowControlInConsumingState()); | |
200 EXPECT_EQ(0, NumberOfFramesInFlight()); | 558 EXPECT_EQ(0, NumberOfFramesInFlight()); |
559 | |
560 // Finally, examine all frames that were sent to the CastTransport, and | |
561 // confirm their metadata and data is valid. | |
562 std::vector<media::cast::EncodedFrame> frames; | |
563 TakeSentFrames(&frames); | |
564 const size_t total_frames_sent = | |
565 media::cast::kMaxUnackedFrames + 2 + num_frames_in_data_pipe + 1; | |
566 ASSERT_EQ(total_frames_sent, frames.size()); | |
567 media::cast::RtpTimeTicks last_rtp_timestamp = | |
568 media::cast::RtpTimeTicks() - media::cast::RtpTimeDelta::FromTicks(1); | |
569 for (size_t i = 0; i < total_frames_sent; ++i) { | |
570 const media::cast::EncodedFrame& frame = frames[i]; | |
571 EXPECT_EQ(media::cast::FrameId::first() + i, frame.frame_id); | |
572 if (i == 0) { | |
573 EXPECT_EQ(media::cast::EncodedFrame::KEY, frame.dependency); | |
574 EXPECT_EQ(media::cast::FrameId::first() + i, frame.referenced_frame_id); | |
575 } else { | |
576 EXPECT_EQ(media::cast::EncodedFrame::DEPENDENT, frame.dependency); | |
577 EXPECT_EQ(media::cast::FrameId::first() + i - 1, | |
578 frame.referenced_frame_id); | |
579 } | |
580 | |
581 // RTP timestamp must be monotonically increasing. | |
582 EXPECT_GT(frame.rtp_timestamp, last_rtp_timestamp); | |
583 last_rtp_timestamp = frame.rtp_timestamp; | |
584 | |
585 size_t expected_frame_size = 4; | |
586 if ((i >= static_cast<size_t>(media::cast::kMaxUnackedFrames + 2)) && | |
587 (i < static_cast<size_t>(media::cast::kMaxUnackedFrames + 2 + | |
588 num_frames_in_data_pipe))) { | |
589 expected_frame_size = 768; | |
590 } | |
591 EXPECT_TRUE(ExpectCorrectFrameData(expected_frame_size, frame)); | |
592 } | |
201 } | 593 } |
202 | 594 |
203 } // namespace cast | 595 } // namespace cast |
OLD | NEW |