Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Side by Side Diff: chrome/browser/media/cast_remoting_sender_unittest.cc

Issue 2310753002: Media Remoting: Data/Control plumbing between renderer and Media Router. (Closed)
Patch Set: xjz's PS4 comments addressed. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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.
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 IsFlowControlInStartingState() const {
172 return remoting_sender_->flow_control_state_ ==
173 CastRemotingSender::STARTING;
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);
dcheng 2016/09/20 08:20:13 It might make things slightly easier to just make
miu 2016/09/21 03:15:50 Required by the style guide: https://google.github
dcheng 2016/09/22 02:29:15 From https://google.github.io/styleguide/cppguide.
miu 2016/09/22 08:39:14 Ah, okay. Good to know.
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 // http://crbug.com/647423
396 #define MAYBE_CancelsFramesInFlight DISABLED_CancelsFramesInFlight
397 TEST_F(CastRemotingSenderTest, MAYBE_CancelsFramesInFlight) {
398 EXPECT_TRUE(IsFlowControlInStartingState());
399
400 // Send 10 frames.
401 for (int i = 0; i < 10; ++i) {
402 ASSERT_TRUE(ProduceDataChunk(0, 16));
403 PostMojoCallTask_ConsumeDataChunk(0, 16, 16);
404 PostMojoCallTask_SendFrame();
405 }
406 RunPendingTasks();
407 EXPECT_TRUE(IsFlowControlInConsumingState());
408 EXPECT_EQ(10, NumberOfFramesInFlight());
409
410 // Ack the first frame.
411 AckOldestInFlightFrames(1);
412 EXPECT_TRUE(IsFlowControlInConsumingState());
413 EXPECT_EQ(9, NumberOfFramesInFlight());
414 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first(),
415 media::cast::FrameId::first()));
416
417 // Cancel all in-flight data. This should cause the remaining 9 frames to be
418 // canceled.
419 PostMojoCallTask_CancelInFlightData();
420 RunPendingTasks();
421 EXPECT_TRUE(IsFlowControlInStartingState());
172 EXPECT_EQ(0, NumberOfFramesInFlight()); 422 EXPECT_EQ(0, NumberOfFramesInFlight());
173 423 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first() + 1,
174 // Send 4 frames. 424 media::cast::FrameId::first() + 9));
175 for (int i = 0; i < 4; ++i) 425
176 InsertFrame(); 426 // Send one more frame and ack it.
177 EXPECT_EQ(4, NumberOfFramesInFlight()); 427 ASSERT_TRUE(ProduceDataChunk(0, 16));
178 // Ack one frame. 428 PostMojoCallTask_ConsumeDataChunk(0, 16, 16);
179 cast_feedback.ack_frame_id = media::cast::FrameId::first() + 1; 429 PostMojoCallTask_SendFrame();
180 OnReceivedCastMessage(cast_feedback); 430 RunPendingTasks();
181 EXPECT_EQ(3, NumberOfFramesInFlight()); 431 EXPECT_TRUE(IsFlowControlInConsumingState());
182 // Ack all. 432 EXPECT_EQ(1, NumberOfFramesInFlight());
183 cast_feedback.received_later_frames.clear(); 433 AckOldestInFlightFrames(1);
184 cast_feedback.ack_frame_id = media::cast::FrameId::first() + 4;
185 OnReceivedCastMessage(cast_feedback);
186 EXPECT_EQ(0, NumberOfFramesInFlight()); 434 EXPECT_EQ(0, NumberOfFramesInFlight());
187 } 435
188 436 // Check that the dependency metadata was set correctly to indicate a frame
189 TEST_F(CastRemotingSenderTest, CancelFramesInFlight) { 437 // that immediately follows a CancelInFlightData() operation.
190 for (int i = 0; i < 10; ++i) 438 std::vector<media::cast::EncodedFrame> frames;
191 InsertFrame(); 439 TakeSentFrames(&frames);
192 EXPECT_EQ(10, NumberOfFramesInFlight()); 440 ASSERT_EQ(11u, frames.size());
193 441 for (size_t i = 0; i < 11; ++i) {
194 media::cast::RtcpCastMessage cast_feedback(11); 442 const media::cast::EncodedFrame& frame = frames[i];
195 cast_feedback.ack_frame_id = media::cast::FrameId::first(); 443 EXPECT_EQ(media::cast::FrameId::first() + i, frame.frame_id);
196 OnReceivedCastMessage(cast_feedback); 444 if (i == 0 || i == 10)
197 EXPECT_EQ(9, NumberOfFramesInFlight()); 445 EXPECT_EQ(media::cast::EncodedFrame::KEY, frame.dependency);
198 446 else
199 CancelFramesInFlight(); 447 EXPECT_EQ(media::cast::EncodedFrame::DEPENDENT, frame.dependency);
448 }
449 }
450
451 TEST_F(CastRemotingSenderTest, ManagesFlowControl) {
452 EXPECT_TRUE(IsFlowControlInStartingState());
453
454 // Send out a the maximum possible number of unacked frames, but don't ack any
455 // yet.
456 for (int i = 0; i < media::cast::kMaxUnackedFrames; ++i) {
457 ASSERT_TRUE(ProduceDataChunk(0, 4));
458 PostMojoCallTask_ConsumeDataChunk(0, 4, 4);
459 PostMojoCallTask_SendFrame();
460 }
461 RunPendingTasks();
462 EXPECT_TRUE(IsFlowControlInConsumingState());
463 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight());
464 // Note: All frames should have been sent to the Transport, and so
465 // CastRemotingSender's single-frame data buffer should be empty.
466 EXPECT_EQ(0u, GetSizeOfNextFrameData());
467
468 // Attempting to send the next frame will place the CastRemotingSenderTest in
469 // a "paused flow" state.
470 ASSERT_TRUE(ProduceDataChunk(0, 4));
471 PostMojoCallTask_ConsumeDataChunk(0, 4, 4);
472 PostMojoCallTask_SendFrame();
473 RunPendingTasks();
474 EXPECT_TRUE(IsFlowControlInPausedState());
475 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight());
476 // Note: The unsent frame resides in CastRemotingSender's single-frame data
477 // buffer.
478 EXPECT_EQ(4u, GetSizeOfNextFrameData());
479
480 // Ack the the first frame and expect sending to resume, starting with the
481 // frame that triggered the pause.
482 AckOldestInFlightFrames(1);
483 EXPECT_TRUE(IsFlowControlInConsumingState());
484 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight());
485 // Note: The frame causing the earlier pause should have been sent, and so
486 // CastRemotingSender's single-frame data buffer should now be empty.
487 EXPECT_EQ(0u, GetSizeOfNextFrameData());
488
489 // Attempting to send another frame will once again place the
490 // CastRemotingSender in a "paused flow" state.
491 ASSERT_TRUE(ProduceDataChunk(0, 4));
492 PostMojoCallTask_ConsumeDataChunk(0, 4, 4);
493 PostMojoCallTask_SendFrame();
494 RunPendingTasks();
495 EXPECT_TRUE(IsFlowControlInPausedState());
496 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight());
497 // Note: Once again, CastRemotingSender's single-frame data buffer contains an
498 // unsent frame.
499 EXPECT_EQ(4u, GetSizeOfNextFrameData());
500
501 // Send more frames: Some number of frames will queue-up inside the Mojo data
502 // pipe (the exact number depends on the data pipe's capacity, and how Mojo
503 // manages memory internally). At some point, attempting to produce and push
504 // another frame will fail because the data pipe is full.
505 int num_frames_in_data_pipe = 0;
506 while (ProduceDataChunk(0, 768)) {
507 ++num_frames_in_data_pipe;
508 PostMojoCallTask_ConsumeDataChunk(0, 768, 768);
509 PostMojoCallTask_SendFrame();
510 RunPendingTasks();
511 EXPECT_TRUE(IsFlowControlInPausedState());
512 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight());
513 // Note: CastRemotingSender's single-frame data buffer should still contain
514 // the unsent 4-byte frame.
515 EXPECT_EQ(4u, GetSizeOfNextFrameData());
516 }
517 EXPECT_LT(0, num_frames_in_data_pipe);
518
519 // Ack one frame at a time until the backlog in the Mojo data pipe has
520 // cleared. In each iteration, the flow will resume, but then it will become
521 // paused again when Mojo method calls are resumed and cause
522 // CastRemotingSender to pull another frame out of the data pipe.
523 int remaining_frames_in_data_pipe = num_frames_in_data_pipe;
524 while (remaining_frames_in_data_pipe > 0) {
525 AckOldestInFlightFrames(1);
526 EXPECT_TRUE(IsFlowControlInConsumingState());
527 EXPECT_EQ(0u, GetSizeOfNextFrameData());
528 // The following will execute one ConsumeDataChunk() and one SendFrame()
529 // Mojo method call.
530 RunPendingTasks();
531 --remaining_frames_in_data_pipe;
532 EXPECT_TRUE(IsFlowControlInPausedState());
533 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight());
534 EXPECT_EQ(768u, GetSizeOfNextFrameData());
535 }
536
537 // Ack one more frame. This should cause the flow to resume since there are no
538 // longer any frames backlogged on the input side of things.
539 AckOldestInFlightFrames(1);
540 EXPECT_TRUE(IsFlowControlInConsumingState());
541 RunPendingTasks(); // No additional Mojo method calls should be made here.
542 EXPECT_TRUE(IsFlowControlInConsumingState());
543 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight());
544 EXPECT_EQ(0u, GetSizeOfNextFrameData());
545
546 // Ack all but one frame.
547 AckOldestInFlightFrames(NumberOfFramesInFlight() - 1);
548 EXPECT_TRUE(IsFlowControlInConsumingState());
549 EXPECT_EQ(1, NumberOfFramesInFlight());
550 // ..and one more frame can be sent without pausing.
551 ASSERT_TRUE(ProduceDataChunk(0, 4));
552 PostMojoCallTask_ConsumeDataChunk(0, 4, 4);
553 PostMojoCallTask_SendFrame();
554 RunPendingTasks();
555 EXPECT_TRUE(IsFlowControlInConsumingState());
556 EXPECT_EQ(2, NumberOfFramesInFlight());
557 // ...and ack these last two frames.
558 AckOldestInFlightFrames(2);
559 EXPECT_TRUE(IsFlowControlInConsumingState());
200 EXPECT_EQ(0, NumberOfFramesInFlight()); 560 EXPECT_EQ(0, NumberOfFramesInFlight());
561
562 // Finally, examine all frames that were sent to the CastTransport, and
563 // confirm their metadata and data is valid.
564 std::vector<media::cast::EncodedFrame> frames;
565 TakeSentFrames(&frames);
566 const size_t total_frames_sent =
567 media::cast::kMaxUnackedFrames + 2 + num_frames_in_data_pipe + 1;
568 ASSERT_EQ(total_frames_sent, frames.size());
569 media::cast::RtpTimeTicks last_rtp_timestamp =
570 media::cast::RtpTimeTicks() - media::cast::RtpTimeDelta::FromTicks(1);
571 for (size_t i = 0; i < total_frames_sent; ++i) {
572 const media::cast::EncodedFrame& frame = frames[i];
573 EXPECT_EQ(media::cast::FrameId::first() + i, frame.frame_id);
574 if (i == 0) {
575 EXPECT_EQ(media::cast::EncodedFrame::KEY, frame.dependency);
576 EXPECT_EQ(media::cast::FrameId::first() + i, frame.referenced_frame_id);
577 } else {
578 EXPECT_EQ(media::cast::EncodedFrame::DEPENDENT, frame.dependency);
579 EXPECT_EQ(media::cast::FrameId::first() + i - 1,
580 frame.referenced_frame_id);
581 }
582
583 // RTP timestamp must be monotonically increasing.
584 EXPECT_GT(frame.rtp_timestamp, last_rtp_timestamp);
585 last_rtp_timestamp = frame.rtp_timestamp;
586
587 size_t expected_frame_size = 4;
588 if ((i >= static_cast<size_t>(media::cast::kMaxUnackedFrames + 2)) &&
dcheng 2016/09/20 08:20:13 These casts might be avoidable by writing media::c
miu 2016/09/21 03:15:50 Done. Good idea.
589 (i < static_cast<size_t>(media::cast::kMaxUnackedFrames + 2 +
590 num_frames_in_data_pipe))) {
591 expected_frame_size = 768;
592 }
593 EXPECT_TRUE(ExpectCorrectFrameData(expected_frame_size, frame));
594 }
201 } 595 }
202 596
203 } // namespace cast 597 } // namespace cast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698