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. |
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 IsFlowRestartPending() const { |
| 172 return remoting_sender_->flow_restart_pending_; |
| 173 } |
| 174 |
| 175 bool ProduceDataChunk(size_t offset, size_t size) WARN_UNUSED_RESULT { |
| 176 std::vector<uint8_t> fake_chunk(size); |
| 177 for (size_t i = 0; i < size; ++i) |
| 178 fake_chunk[i] = static_cast<uint8_t>(offset + i); |
| 179 uint32_t num_bytes = fake_chunk.size(); |
| 180 return mojo::WriteDataRaw( |
| 181 producer_end_.get(), fake_chunk.data(), &num_bytes, |
| 182 MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) == MOJO_RESULT_OK; |
| 183 } |
| 184 |
| 185 void PostMojoCallTask_ConsumeDataChunk(size_t offset, size_t size, |
| 186 size_t total_payload_size) { |
| 187 sender_->ConsumeDataChunk(offset, size, total_payload_size); |
| 188 } |
| 189 |
| 190 void PostMojoCallTask_SendFrame() { |
| 191 sender_->SendFrame(); |
| 192 } |
| 193 |
| 194 void PostMojoCallTask_CancelInFlightData() { sender_->CancelInFlightData(); } |
| 195 |
| 196 void TakeSentFrames(std::vector<media::cast::EncodedFrame>* frames) { |
| 197 transport_.TakeSentFrames(frames); |
| 198 } |
| 199 |
| 200 bool ExpectOneFrameWasSent(size_t expected_payload_size) { |
| 201 std::vector<media::cast::EncodedFrame> frames; |
| 202 transport_.TakeSentFrames(&frames); |
| 203 EXPECT_EQ(1u, frames.size()); |
| 204 if (frames.empty()) |
| 205 return false; |
| 206 return ExpectCorrectFrameData(expected_payload_size, frames.front()); |
| 207 } |
| 208 |
| 209 void AckUpToAndIncluding(media::cast::FrameId frame_id) { |
| 210 media::cast::RtcpCastMessage cast_feedback(transport_config_.feedback_ssrc); |
| 211 cast_feedback.ack_frame_id = frame_id; |
| 212 remoting_sender_->OnReceivedCastMessage(cast_feedback); |
| 213 } |
| 214 |
| 215 void AckOldestInFlightFrames(int count) { |
| 216 AckUpToAndIncluding(latest_acked_frame_id() + count); |
| 217 } |
| 218 |
| 219 // Blocks the caller indefinitely, until a kickstart frame is sent, and then |
| 220 // returns the FrameId of the kickstarted-frame. |
| 221 media::cast::FrameId WaitForKickstart() { |
| 222 return transport_.WaitForKickstart(); |
| 223 } |
| 224 |
| 225 bool ExpectNoFramesCanceled() { |
| 226 std::vector<media::cast::FrameId> frame_ids; |
| 227 transport_.TakeCanceledFrameIds(&frame_ids); |
| 228 return frame_ids.empty(); |
| 229 } |
| 230 |
| 231 bool ExpectFramesCanceled(media::cast::FrameId first_frame_id, |
| 232 media::cast::FrameId last_frame_id) { |
| 233 std::vector<media::cast::FrameId> frame_ids; |
| 234 transport_.TakeCanceledFrameIds(&frame_ids); |
| 235 auto begin = frame_ids.begin(); |
| 236 auto end = frame_ids.end(); |
| 237 for (auto fid = first_frame_id; fid <= last_frame_id; ++fid) { |
| 238 auto new_end = std::remove(begin, end, fid); |
| 239 if (new_end == end) |
| 240 return false; |
| 241 end = new_end; |
| 242 } |
| 243 return begin == end; |
| 244 } |
| 245 |
| 246 static bool ExpectCorrectFrameData(size_t expected_payload_size, |
| 247 const media::cast::EncodedFrame& frame) { |
| 248 if (expected_payload_size != frame.data.size()) { |
| 249 ADD_FAILURE() << "Expected frame data size != frame.data.size(): " |
| 250 << expected_payload_size << " vs " << frame.data.size(); |
| 251 return false; |
| 252 } |
| 253 for (size_t i = 0; i < expected_payload_size; ++i) { |
| 254 if (static_cast<uint8_t>(frame.data[i]) != static_cast<uint8_t>(i)) { |
| 255 ADD_FAILURE() << "Frame data byte mismatch at offset " << i; |
| 256 return false; |
| 257 } |
| 258 } |
| 259 return true; |
| 260 } |
| 261 |
| 262 private: |
| 263 void OnError() { |
| 264 CHECK(expecting_error_callback_run_); |
| 265 } |
| 266 |
| 267 content::TestBrowserThreadBundle thread_bundle_; |
152 const scoped_refptr<media::cast::CastEnvironment> cast_environment_; | 268 const scoped_refptr<media::cast::CastEnvironment> cast_environment_; |
153 TestPacketSender* transport_; // Owned by CastTransport. | 269 media::cast::CastTransportRtpConfig transport_config_; |
154 std::unique_ptr<media::cast::CastTransportImpl> transport_sender_; | 270 FakeTransport transport_; |
155 std::unique_ptr<CastRemotingSender> remoting_sender_; | 271 std::unique_ptr<CastRemotingSender> remoting_sender_; |
| 272 media::mojom::RemotingDataStreamSenderPtr sender_; |
| 273 mojo::ScopedDataPipeProducerHandle producer_end_; |
| 274 bool expecting_error_callback_run_; |
156 | 275 |
157 private: | 276 private: |
158 DISALLOW_COPY_AND_ASSIGN(CastRemotingSenderTest); | 277 DISALLOW_COPY_AND_ASSIGN(CastRemotingSenderTest); |
159 }; | 278 }; |
160 | 279 |
161 TEST_F(CastRemotingSenderTest, SendAndAckEncodedFrame) { | 280 TEST_F(CastRemotingSenderTest, SendsFramesViaMojoInterface) { |
162 // Send a fake video frame that will be decomposed into 4 packets. | 281 // One 256-byte chunk pushed through the data pipe to make one frame. |
163 InsertFrame(); | 282 ASSERT_TRUE(ProduceDataChunk(0, 256)); |
164 task_runner_->RunTasks(); | 283 PostMojoCallTask_ConsumeDataChunk(0, 256, 256); |
165 EXPECT_EQ(4, transport_->number_of_rtp_packets()); | 284 PostMojoCallTask_SendFrame(); |
| 285 RunPendingTasks(); |
| 286 EXPECT_TRUE(ExpectOneFrameWasSent(256)); |
| 287 AckOldestInFlightFrames(1); |
| 288 EXPECT_EQ(media::cast::FrameId::first(), latest_acked_frame_id()); |
| 289 |
| 290 // Four 256-byte chunks pushed through the data pipe to make one frame. |
| 291 for (int i = 0; i < 4; ++i) { |
| 292 ASSERT_TRUE(ProduceDataChunk(i * 256, 256)); |
| 293 PostMojoCallTask_ConsumeDataChunk(i * 256, 256, 1024); |
| 294 } |
| 295 PostMojoCallTask_SendFrame(); |
| 296 RunPendingTasks(); |
| 297 EXPECT_TRUE(ExpectOneFrameWasSent(1024)); |
| 298 AckOldestInFlightFrames(1); |
| 299 EXPECT_EQ(media::cast::FrameId::first() + 1, latest_acked_frame_id()); |
| 300 |
| 301 // 10 differently-sized chunks pushed through the data pipe to make one frame |
| 302 // that is larger than the data pipe's total capacity. |
| 303 size_t offset = 0; |
| 304 for (int i = 0; i < 10; ++i) { |
| 305 const size_t chunk_size = 500 + i * 37; |
| 306 ASSERT_TRUE(ProduceDataChunk(offset, chunk_size)); |
| 307 PostMojoCallTask_ConsumeDataChunk(offset, chunk_size, 6665); |
| 308 RunPendingTasks(); |
| 309 offset += chunk_size; |
| 310 } |
| 311 PostMojoCallTask_SendFrame(); |
| 312 RunPendingTasks(); |
| 313 EXPECT_TRUE(ExpectOneFrameWasSent(6665)); |
| 314 AckOldestInFlightFrames(1); |
| 315 EXPECT_EQ(media::cast::FrameId::first() + 2, latest_acked_frame_id()); |
| 316 } |
| 317 |
| 318 TEST_F(CastRemotingSenderTest, SendsMultipleFramesWithDelayedAcks) { |
| 319 // Send 4 frames. |
| 320 for (int i = 0; i < 4; ++i) { |
| 321 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
| 322 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); |
| 323 PostMojoCallTask_SendFrame(); |
| 324 } |
| 325 RunPendingTasks(); |
| 326 EXPECT_EQ(4, NumberOfFramesInFlight()); |
| 327 EXPECT_TRUE(ExpectNoFramesCanceled()); |
| 328 |
| 329 // Ack one frame. |
| 330 AckOldestInFlightFrames(1); |
| 331 EXPECT_EQ(3, NumberOfFramesInFlight()); |
| 332 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first(), |
| 333 media::cast::FrameId::first())); |
| 334 |
| 335 // Ack all. |
| 336 AckOldestInFlightFrames(3); |
| 337 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 338 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first() + 1, |
| 339 media::cast::FrameId::first() + 3)); |
| 340 } |
| 341 |
| 342 TEST_F(CastRemotingSenderTest, KickstartsIfAckNotTimely) { |
| 343 // Send first frame and don't Ack it. Expect the first frame to be |
| 344 // kickstarted. |
| 345 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
| 346 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); |
| 347 PostMojoCallTask_SendFrame(); |
| 348 EXPECT_EQ(media::cast::FrameId::first(), WaitForKickstart()); |
166 EXPECT_EQ(1, NumberOfFramesInFlight()); | 349 EXPECT_EQ(1, NumberOfFramesInFlight()); |
167 | 350 |
168 // Ack the frame. | 351 // Send 3 more frames and don't Ack them either. Expect the 4th frame to be |
169 media::cast::RtcpCastMessage cast_feedback(11); | 352 // kickstarted. |
170 cast_feedback.ack_frame_id = media::cast::FrameId::first(); | 353 for (int i = 0; i < 3; ++i) { |
171 OnReceivedCastMessage(cast_feedback); | 354 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
172 EXPECT_EQ(0, NumberOfFramesInFlight()); | 355 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); |
173 | 356 PostMojoCallTask_SendFrame(); |
174 // Send 4 frames. | 357 } |
175 for (int i = 0; i < 4; ++i) | 358 EXPECT_EQ(media::cast::FrameId::first() + 3, WaitForKickstart()); |
176 InsertFrame(); | |
177 EXPECT_EQ(4, NumberOfFramesInFlight()); | 359 EXPECT_EQ(4, NumberOfFramesInFlight()); |
178 // Ack one frame. | 360 |
179 cast_feedback.ack_frame_id = media::cast::FrameId::first() + 1; | 361 // Ack the first two frames and wait for another kickstart (for the 4th frame |
180 OnReceivedCastMessage(cast_feedback); | 362 // again). |
| 363 AckOldestInFlightFrames(2); |
| 364 EXPECT_EQ(2, NumberOfFramesInFlight()); |
| 365 EXPECT_EQ(media::cast::FrameId::first() + 3, WaitForKickstart()); |
| 366 } |
| 367 |
| 368 TEST_F(CastRemotingSenderTest, CancelsUnsentFrame) { |
| 369 EXPECT_EQ(0u, GetSizeOfNextFrameData()); |
| 370 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
| 371 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); |
| 372 RunPendingTasks(); |
| 373 EXPECT_EQ(16u, GetSizeOfNextFrameData()); |
| 374 PostMojoCallTask_CancelInFlightData(); |
| 375 RunPendingTasks(); |
| 376 EXPECT_EQ(0u, GetSizeOfNextFrameData()); |
| 377 |
| 378 // Since no frames were sent, none should have been passed to the |
| 379 // CastTransport, and none should have been canceled. |
| 380 std::vector<media::cast::EncodedFrame> frames; |
| 381 TakeSentFrames(&frames); |
| 382 EXPECT_TRUE(frames.empty()); |
| 383 EXPECT_TRUE(ExpectNoFramesCanceled()); |
| 384 } |
| 385 |
| 386 // http://crbug.com/647423 |
| 387 #define MAYBE_CancelsFramesInFlight DISABLED_CancelsFramesInFlight |
| 388 TEST_F(CastRemotingSenderTest, MAYBE_CancelsFramesInFlight) { |
| 389 EXPECT_TRUE(IsFlowRestartPending()); |
| 390 |
| 391 // Send 10 frames. |
| 392 for (int i = 0; i < 10; ++i) { |
| 393 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
| 394 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); |
| 395 PostMojoCallTask_SendFrame(); |
| 396 } |
| 397 RunPendingTasks(); |
| 398 EXPECT_FALSE(IsFlowRestartPending()); |
| 399 EXPECT_EQ(10, NumberOfFramesInFlight()); |
| 400 |
| 401 // Ack the first frame. |
| 402 AckOldestInFlightFrames(1); |
| 403 EXPECT_FALSE(IsFlowRestartPending()); |
| 404 EXPECT_EQ(9, NumberOfFramesInFlight()); |
| 405 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first(), |
| 406 media::cast::FrameId::first())); |
| 407 |
| 408 // Cancel all in-flight data. This should cause the remaining 9 frames to be |
| 409 // canceled. |
| 410 PostMojoCallTask_CancelInFlightData(); |
| 411 RunPendingTasks(); |
| 412 EXPECT_TRUE(IsFlowRestartPending()); |
| 413 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 414 EXPECT_TRUE(ExpectFramesCanceled(media::cast::FrameId::first() + 1, |
| 415 media::cast::FrameId::first() + 9)); |
| 416 |
| 417 // Send one more frame and ack it. |
| 418 ASSERT_TRUE(ProduceDataChunk(0, 16)); |
| 419 PostMojoCallTask_ConsumeDataChunk(0, 16, 16); |
| 420 PostMojoCallTask_SendFrame(); |
| 421 RunPendingTasks(); |
| 422 EXPECT_FALSE(IsFlowRestartPending()); |
| 423 EXPECT_EQ(1, NumberOfFramesInFlight()); |
| 424 AckOldestInFlightFrames(1); |
| 425 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 426 |
| 427 // Check that the dependency metadata was set correctly to indicate a frame |
| 428 // that immediately follows a CancelInFlightData() operation. |
| 429 std::vector<media::cast::EncodedFrame> frames; |
| 430 TakeSentFrames(&frames); |
| 431 ASSERT_EQ(11u, frames.size()); |
| 432 for (size_t i = 0; i < 11; ++i) { |
| 433 const media::cast::EncodedFrame& frame = frames[i]; |
| 434 EXPECT_EQ(media::cast::FrameId::first() + i, frame.frame_id); |
| 435 if (i == 0 || i == 10) |
| 436 EXPECT_EQ(media::cast::EncodedFrame::KEY, frame.dependency); |
| 437 else |
| 438 EXPECT_EQ(media::cast::EncodedFrame::DEPENDENT, frame.dependency); |
| 439 } |
| 440 } |
| 441 |
| 442 TEST_F(CastRemotingSenderTest, WaitsForDataBeforeConsumingFromDataPipe) { |
| 443 // Queue up and issue Mojo calls to consume data chunks and send three |
| 444 // frames. Since no data has been pushed into the pipe yet no frames should be |
| 445 // sent. |
| 446 for (int i = 0; i < 3; ++i) { |
| 447 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); |
| 448 PostMojoCallTask_SendFrame(); |
| 449 } |
| 450 RunPendingTasks(); |
| 451 EXPECT_TRUE(IsFlowRestartPending()); |
| 452 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 453 |
| 454 // Push the data for one frame into the data pipe. This should trigger input |
| 455 // processing and allow one frame to be sent. |
| 456 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 457 RunPendingTasks(); // Allow Mojo Watcher to signal CastRemotingSender. |
| 458 EXPECT_FALSE(IsFlowRestartPending()); |
| 459 EXPECT_EQ(1, NumberOfFramesInFlight()); |
| 460 |
| 461 // Now push the data for the other two frames into the data pipe and expect |
| 462 // two more frames to be sent. |
| 463 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 464 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 465 RunPendingTasks(); // Allow Mojo Watcher to signal CastRemotingSender. |
| 466 EXPECT_FALSE(IsFlowRestartPending()); |
181 EXPECT_EQ(3, NumberOfFramesInFlight()); | 467 EXPECT_EQ(3, NumberOfFramesInFlight()); |
182 // Ack all. | 468 } |
183 cast_feedback.received_later_frames.clear(); | 469 |
184 cast_feedback.ack_frame_id = media::cast::FrameId::first() + 4; | 470 TEST_F(CastRemotingSenderTest, WaitsForDataThenDiscardsCanceledData) { |
185 OnReceivedCastMessage(cast_feedback); | 471 // Queue up and issue Mojo calls to consume data chunks and send three |
186 EXPECT_EQ(0, NumberOfFramesInFlight()); | 472 // frames. Since no data has been pushed into the pipe yet no frames should be |
187 } | 473 // sent. |
188 | 474 for (int i = 0; i < 3; ++i) { |
189 TEST_F(CastRemotingSenderTest, CancelFramesInFlight) { | 475 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); |
190 for (int i = 0; i < 10; ++i) | 476 PostMojoCallTask_SendFrame(); |
191 InsertFrame(); | 477 } |
192 EXPECT_EQ(10, NumberOfFramesInFlight()); | 478 RunPendingTasks(); |
193 | 479 EXPECT_EQ(0, NumberOfFramesInFlight()); |
194 media::cast::RtcpCastMessage cast_feedback(11); | 480 |
195 cast_feedback.ack_frame_id = media::cast::FrameId::first(); | 481 // Cancel all in-flight data. |
196 OnReceivedCastMessage(cast_feedback); | 482 PostMojoCallTask_CancelInFlightData(); |
197 EXPECT_EQ(9, NumberOfFramesInFlight()); | 483 RunPendingTasks(); |
198 | 484 |
199 CancelFramesInFlight(); | 485 // Now, push the data for one frame into the data pipe. Because of the |
200 EXPECT_EQ(0, NumberOfFramesInFlight()); | 486 // cancellation, no frames should be sent. |
| 487 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 488 RunPendingTasks(); // Allow Mojo Watcher to signal CastRemotingSender. |
| 489 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 490 |
| 491 // Now push the data for the other two frames into the data pipe and still no |
| 492 // frames should be sent. |
| 493 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 494 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 495 RunPendingTasks(); // Allow Mojo Watcher to signal CastRemotingSender. |
| 496 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 497 |
| 498 // Now issue calls to send another frame and then push the data for it into |
| 499 // the data pipe. Expect to see the frame gets sent since it was provided |
| 500 // after the CancelInFlightData(). |
| 501 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); |
| 502 PostMojoCallTask_SendFrame(); |
| 503 RunPendingTasks(); |
| 504 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 505 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 506 RunPendingTasks(); // Allow Mojo Watcher to signal CastRemotingSender. |
| 507 EXPECT_EQ(1, NumberOfFramesInFlight()); |
| 508 } |
| 509 |
| 510 TEST_F(CastRemotingSenderTest, StopsConsumingWhileTooManyFramesAreInFlight) { |
| 511 EXPECT_TRUE(IsFlowRestartPending()); |
| 512 |
| 513 // Send out a the maximum possible number of unacked frames, but don't ack any |
| 514 // yet. |
| 515 for (int i = 0; i < media::cast::kMaxUnackedFrames; ++i) { |
| 516 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 517 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); |
| 518 PostMojoCallTask_SendFrame(); |
| 519 } |
| 520 RunPendingTasks(); |
| 521 EXPECT_FALSE(IsFlowRestartPending()); |
| 522 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); |
| 523 // Note: All frames should have been sent to the Transport, and so |
| 524 // CastRemotingSender's single-frame data buffer should be empty. |
| 525 EXPECT_EQ(0u, GetSizeOfNextFrameData()); |
| 526 |
| 527 // When the client provides one more frame, CastRemotingSender will begin |
| 528 // queuing input operations instead of sending the the frame to the |
| 529 // CastTransport. |
| 530 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 531 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); |
| 532 PostMojoCallTask_SendFrame(); |
| 533 RunPendingTasks(); |
| 534 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); |
| 535 // Note: The unsent frame resides in CastRemotingSender's single-frame data |
| 536 // buffer. |
| 537 EXPECT_EQ(4u, GetSizeOfNextFrameData()); |
| 538 |
| 539 // Ack the the first frame and expect sending to resume, with one more frame |
| 540 // being sent to the CastTransport. |
| 541 AckOldestInFlightFrames(1); |
| 542 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); |
| 543 // Note: Only one frame was backlogged, and so CastRemotingSender's |
| 544 // single-frame data buffer should be empty. |
| 545 EXPECT_EQ(0u, GetSizeOfNextFrameData()); |
| 546 |
| 547 // Attempting to send another frame will once again cause CastRemotingSender |
| 548 // to queue input operations. |
| 549 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 550 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); |
| 551 PostMojoCallTask_SendFrame(); |
| 552 RunPendingTasks(); |
| 553 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); |
| 554 // Note: Once again, CastRemotingSender's single-frame data buffer contains an |
| 555 // unsent frame. |
| 556 EXPECT_EQ(4u, GetSizeOfNextFrameData()); |
| 557 |
| 558 // Send more frames: Some number of frames will queue-up inside the Mojo data |
| 559 // pipe (the exact number depends on the data pipe's capacity, and how Mojo |
| 560 // manages memory internally). At some point, attempting to produce and push |
| 561 // another frame will fail because the data pipe is full. |
| 562 int num_frames_in_data_pipe = 0; |
| 563 while (ProduceDataChunk(0, 768)) { |
| 564 ++num_frames_in_data_pipe; |
| 565 PostMojoCallTask_ConsumeDataChunk(0, 768, 768); |
| 566 PostMojoCallTask_SendFrame(); |
| 567 RunPendingTasks(); |
| 568 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); |
| 569 // Note: CastRemotingSender's single-frame data buffer should still contain |
| 570 // the unsent 4-byte frame. |
| 571 EXPECT_EQ(4u, GetSizeOfNextFrameData()); |
| 572 } |
| 573 EXPECT_LT(0, num_frames_in_data_pipe); |
| 574 |
| 575 // Ack one frame at a time until the backlog in the Mojo data pipe has |
| 576 // cleared. |
| 577 int remaining_frames_in_data_pipe = num_frames_in_data_pipe; |
| 578 while (remaining_frames_in_data_pipe > 0) { |
| 579 AckOldestInFlightFrames(1); |
| 580 --remaining_frames_in_data_pipe; |
| 581 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); |
| 582 EXPECT_EQ(768u, GetSizeOfNextFrameData()); |
| 583 } |
| 584 |
| 585 // Ack one more frame. There should no longer be a backlog on the input side |
| 586 // of things. |
| 587 AckOldestInFlightFrames(1); |
| 588 RunPendingTasks(); // No additional Mojo method calls should be made here. |
| 589 EXPECT_EQ(media::cast::kMaxUnackedFrames, NumberOfFramesInFlight()); |
| 590 // The single-frame data buffer should be empty to indicate no input backlog. |
| 591 EXPECT_EQ(0u, GetSizeOfNextFrameData()); |
| 592 |
| 593 // Ack all but one frame. |
| 594 AckOldestInFlightFrames(NumberOfFramesInFlight() - 1); |
| 595 EXPECT_EQ(1, NumberOfFramesInFlight()); |
| 596 // ..and one more frame can be sent immediately. |
| 597 ASSERT_TRUE(ProduceDataChunk(0, 4)); |
| 598 PostMojoCallTask_ConsumeDataChunk(0, 4, 4); |
| 599 PostMojoCallTask_SendFrame(); |
| 600 RunPendingTasks(); |
| 601 EXPECT_EQ(2, NumberOfFramesInFlight()); |
| 602 // ...and ack these last two frames. |
| 603 AckOldestInFlightFrames(2); |
| 604 EXPECT_EQ(0, NumberOfFramesInFlight()); |
| 605 |
| 606 // Finally, examine all frames that were sent to the CastTransport, and |
| 607 // confirm their metadata and data is valid. |
| 608 std::vector<media::cast::EncodedFrame> frames; |
| 609 TakeSentFrames(&frames); |
| 610 const size_t total_frames_sent = |
| 611 media::cast::kMaxUnackedFrames + 2 + num_frames_in_data_pipe + 1; |
| 612 ASSERT_EQ(total_frames_sent, frames.size()); |
| 613 media::cast::RtpTimeTicks last_rtp_timestamp = |
| 614 media::cast::RtpTimeTicks() - media::cast::RtpTimeDelta::FromTicks(1); |
| 615 for (size_t i = 0; i < total_frames_sent; ++i) { |
| 616 const media::cast::EncodedFrame& frame = frames[i]; |
| 617 EXPECT_EQ(media::cast::FrameId::first() + i, frame.frame_id); |
| 618 if (i == 0) { |
| 619 EXPECT_EQ(media::cast::EncodedFrame::KEY, frame.dependency); |
| 620 EXPECT_EQ(media::cast::FrameId::first() + i, frame.referenced_frame_id); |
| 621 } else { |
| 622 EXPECT_EQ(media::cast::EncodedFrame::DEPENDENT, frame.dependency); |
| 623 EXPECT_EQ(media::cast::FrameId::first() + i - 1, |
| 624 frame.referenced_frame_id); |
| 625 } |
| 626 |
| 627 // RTP timestamp must be monotonically increasing. |
| 628 EXPECT_GT(frame.rtp_timestamp, last_rtp_timestamp); |
| 629 last_rtp_timestamp = frame.rtp_timestamp; |
| 630 |
| 631 size_t expected_frame_size = 4; |
| 632 if ((i >= media::cast::kMaxUnackedFrames + 2u) && |
| 633 (i < media::cast::kMaxUnackedFrames + 2u + num_frames_in_data_pipe)) { |
| 634 expected_frame_size = 768; |
| 635 } |
| 636 EXPECT_TRUE(ExpectCorrectFrameData(expected_frame_size, frame)); |
| 637 } |
201 } | 638 } |
202 | 639 |
203 } // namespace cast | 640 } // namespace cast |
OLD | NEW |