1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdint.h> 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/test/simple_test_tick_clock.h" 9 #include "media/cast/net/rtcp/rtcp.h" 10 #include "media/cast/net/rtp/cast_message_builder.h" 11 #include "media/cast/net/rtp/framer.h" 12 #include "media/cast/net/rtp/rtp_receiver_defines.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace media { 16 namespace cast { 17 18 namespace { 19 static const uint32 kSsrc = 0x1234; 20 static const uint32 kShortTimeIncrementMs = 10; 21 static const uint32 kLongTimeIncrementMs = 40; 22 static const int64 kStartMillisecond = INT64_C(12345678900000); 23 24 typedef std::map<uint32, size_t> MissingPacketsMap; 25 26 class NackFeedbackVerification : public RtpPayloadFeedback { 27 public: 28 NackFeedbackVerification() 29 : triggered_(false), missing_packets_(), last_frame_acked_(0) {} 30 31 virtual void CastFeedback(const RtcpCastMessage& cast_feedback) OVERRIDE { 32 EXPECT_EQ(kSsrc, cast_feedback.media_ssrc); 33 34 last_frame_acked_ = cast_feedback.ack_frame_id; 35 36 MissingFramesAndPacketsMap::const_iterator frame_it = 37 cast_feedback.missing_frames_and_packets.begin(); 38 39 // Keep track of the number of missing packets per frame. 40 missing_packets_.clear(); 41 while (frame_it != cast_feedback.missing_frames_and_packets.end()) { 42 // Check for complete frame lost. 43 if ((frame_it->second.size() == 1) && 44 (*frame_it->second.begin() == kRtcpCastAllPacketsLost)) { 45 missing_packets_.insert( 46 std::make_pair(frame_it->first, kRtcpCastAllPacketsLost)); 47 } else { 48 missing_packets_.insert( 49 std::make_pair(frame_it->first, frame_it->second.size())); 50 } 51 ++frame_it; 52 } 53 triggered_ = true; 54 } 55 56 size_t num_missing_packets(uint32 frame_id) { 57 MissingPacketsMap::iterator it; 58 it = missing_packets_.find(frame_id); 59 if (it == missing_packets_.end()) 60 return 0; 61 62 return it->second; 63 } 64 65 // Holds value for one call. 66 bool triggered() { 67 bool ret_val = triggered_; 68 triggered_ = false; 69 return ret_val; 70 } 71 72 uint32 last_frame_acked() { return last_frame_acked_; } 73 74 private: 75 bool triggered_; 76 MissingPacketsMap missing_packets_; // Missing packets per frame. 77 uint32 last_frame_acked_; 78 79 DISALLOW_COPY_AND_ASSIGN(NackFeedbackVerification); 80 }; 81 } // namespace 82 83 class CastMessageBuilderTest : public ::testing::Test { 84 protected: 85 CastMessageBuilderTest() 86 : framer_(&testing_clock_, 87 &feedback_, 88 kSsrc, 89 true, 90 10), 91 cast_msg_builder_(new CastMessageBuilder(&testing_clock_, 92 &feedback_, 93 &framer_, 94 kSsrc, 95 true, 96 0)) { 97 rtp_header_.sender_ssrc = kSsrc; 98 rtp_header_.is_key_frame = false; 99 testing_clock_.Advance( 100 base::TimeDelta::FromMilliseconds(kStartMillisecond)); 101 } 102 103 virtual ~CastMessageBuilderTest() {} 104 105 void SetFrameIds(uint32 frame_id, uint32 reference_frame_id) { 106 rtp_header_.frame_id = frame_id; 107 rtp_header_.reference_frame_id = reference_frame_id; 108 } 109 110 void SetPacketId(uint16 packet_id) { rtp_header_.packet_id = packet_id; } 111 112 void SetMaxPacketId(uint16 max_packet_id) { 113 rtp_header_.max_packet_id = max_packet_id; 114 } 115 116 void SetKeyFrame(bool is_key) { rtp_header_.is_key_frame = is_key; } 117 118 void InsertPacket() { 119 bool duplicate; 120 uint8 payload = 0; 121 if (framer_.InsertPacket(&payload, 1, rtp_header_, &duplicate)) { 122 cast_msg_builder_->CompleteFrameReceived(rtp_header_.frame_id); 123 } 124 cast_msg_builder_->UpdateCastMessage(); 125 } 126 127 void SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames) { 128 cast_msg_builder_.reset(new CastMessageBuilder(&testing_clock_, 129 &feedback_, 130 &framer_, 131 kSsrc, 132 false, 133 max_unacked_frames)); 134 } 135 136 NackFeedbackVerification feedback_; 137 Framer framer_; 138 scoped_ptr<CastMessageBuilder> cast_msg_builder_; 139 RtpCastHeader rtp_header_; 140 base::SimpleTestTickClock testing_clock_; 141 142 DISALLOW_COPY_AND_ASSIGN(CastMessageBuilderTest); 143 }; 144 145 TEST_F(CastMessageBuilderTest, OneFrameNackList) { 146 SetFrameIds(0, 0); 147 SetPacketId(4); 148 SetMaxPacketId(10); 149 InsertPacket(); 150 testing_clock_.Advance( 151 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 152 EXPECT_FALSE(feedback_.triggered()); 153 testing_clock_.Advance( 154 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 155 SetPacketId(5); 156 InsertPacket(); 157 EXPECT_TRUE(feedback_.triggered()); 158 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); 159 } 160 161 TEST_F(CastMessageBuilderTest, CompleteFrameMissing) { 162 SetFrameIds(0, 0); 163 SetPacketId(2); 164 SetMaxPacketId(5); 165 InsertPacket(); 166 testing_clock_.Advance( 167 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 168 SetFrameIds(2, 1); 169 SetPacketId(2); 170 SetMaxPacketId(5); 171 InsertPacket(); 172 EXPECT_TRUE(feedback_.triggered()); 173 EXPECT_EQ(kRtcpCastAllPacketsLost, feedback_.num_missing_packets(1)); 174 } 175 176 TEST_F(CastMessageBuilderTest, RemoveOldFrames) { 177 SetFrameIds(1, 0); 178 SetPacketId(0); 179 SetMaxPacketId(1); 180 InsertPacket(); 181 EXPECT_FALSE(feedback_.triggered()); 182 testing_clock_.Advance( 183 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 184 SetFrameIds(2, 1); 185 SetPacketId(0); 186 SetMaxPacketId(0); 187 InsertPacket(); 188 EXPECT_TRUE(feedback_.triggered()); 189 testing_clock_.Advance( 190 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 191 SetFrameIds(3, 2); 192 SetPacketId(0); 193 SetMaxPacketId(5); 194 InsertPacket(); 195 EXPECT_TRUE(feedback_.triggered()); 196 EXPECT_EQ(2u, feedback_.last_frame_acked()); 197 testing_clock_.Advance( 198 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 199 SetFrameIds(5, 5); 200 SetPacketId(0); 201 SetMaxPacketId(0); 202 SetKeyFrame(true); 203 InsertPacket(); 204 testing_clock_.Advance( 205 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 206 framer_.RemoveOldFrames(5); // Simulate 5 being pulled for rendering. 207 cast_msg_builder_->UpdateCastMessage(); 208 EXPECT_TRUE(feedback_.triggered()); 209 EXPECT_EQ(5u, feedback_.last_frame_acked()); 210 testing_clock_.Advance( 211 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 212 SetFrameIds(1, 0); 213 SetPacketId(1); 214 SetMaxPacketId(1); 215 InsertPacket(); 216 EXPECT_FALSE(feedback_.triggered()); 217 testing_clock_.Advance( 218 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 219 InsertPacket(); 220 EXPECT_TRUE(feedback_.triggered()); 221 EXPECT_EQ(5u, feedback_.last_frame_acked()); 222 } 223 224 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacket) { 225 SetFrameIds(0, 0); 226 SetPacketId(0); 227 SetMaxPacketId(20); 228 SetKeyFrame(true); 229 InsertPacket(); 230 testing_clock_.Advance( 231 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 232 SetPacketId(5); 233 InsertPacket(); 234 EXPECT_TRUE(feedback_.triggered()); 235 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); 236 } 237 238 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextFrame) { 239 SetFrameIds(0, 0); 240 SetPacketId(0); 241 SetMaxPacketId(20); 242 SetKeyFrame(true); 243 InsertPacket(); 244 testing_clock_.Advance( 245 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 246 SetPacketId(5); 247 InsertPacket(); 248 testing_clock_.Advance( 249 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 250 EXPECT_TRUE(feedback_.triggered()); 251 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); 252 SetFrameIds(1, 0); 253 SetMaxPacketId(2); 254 SetPacketId(0); 255 SetKeyFrame(false); 256 InsertPacket(); 257 testing_clock_.Advance( 258 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 259 EXPECT_TRUE(feedback_.triggered()); 260 EXPECT_EQ(19u, feedback_.num_missing_packets(0)); 261 } 262 263 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextKey) { 264 SetFrameIds(0, 0); 265 SetPacketId(0); 266 SetMaxPacketId(20); 267 SetKeyFrame(true); 268 InsertPacket(); 269 testing_clock_.Advance( 270 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 271 SetPacketId(5); 272 InsertPacket(); 273 testing_clock_.Advance( 274 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 275 EXPECT_TRUE(feedback_.triggered()); 276 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); 277 SetFrameIds(1, 1); 278 SetMaxPacketId(0); 279 SetPacketId(0); 280 SetKeyFrame(true); 281 InsertPacket(); 282 testing_clock_.Advance( 283 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 284 EXPECT_TRUE(feedback_.triggered()); 285 EXPECT_EQ(0u, feedback_.num_missing_packets(0)); 286 } 287 288 TEST_F(CastMessageBuilderTest, Reset) { 289 InsertPacket(); 290 testing_clock_.Advance( 291 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 292 cast_msg_builder_->Reset(); 293 framer_.Reset(); 294 // Should reset nack list state and request a key frame. 295 cast_msg_builder_->UpdateCastMessage(); 296 EXPECT_TRUE(feedback_.triggered()); 297 EXPECT_EQ(0u, feedback_.num_missing_packets(0)); 298 } 299 300 TEST_F(CastMessageBuilderTest, DeltaAfterReset) { 301 SetFrameIds(0, 0); 302 SetPacketId(0); 303 SetMaxPacketId(0); 304 SetKeyFrame(true); 305 InsertPacket(); 306 EXPECT_TRUE(feedback_.triggered()); 307 EXPECT_EQ(0u, feedback_.num_missing_packets(0)); 308 testing_clock_.Advance( 309 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 310 cast_msg_builder_->Reset(); 311 SetFrameIds(1, 0); 312 SetPacketId(0); 313 SetMaxPacketId(0); 314 SetKeyFrame(true); 315 EXPECT_FALSE(feedback_.triggered()); 316 } 317 318 TEST_F(CastMessageBuilderTest, BasicRps) { 319 SetFrameIds(0, 0); 320 SetPacketId(0); 321 SetMaxPacketId(0); 322 SetKeyFrame(true); 323 InsertPacket(); 324 testing_clock_.Advance( 325 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 326 EXPECT_TRUE(feedback_.triggered()); 327 EXPECT_EQ(0u, feedback_.last_frame_acked()); 328 SetFrameIds(3, 0); 329 SetKeyFrame(false); 330 InsertPacket(); 331 EXPECT_TRUE(feedback_.triggered()); 332 EXPECT_EQ(3u, feedback_.last_frame_acked()); 333 testing_clock_.Advance( 334 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); 335 framer_.RemoveOldFrames(3); // Simulate 3 being pulled for rendering. 336 cast_msg_builder_->UpdateCastMessage(); 337 EXPECT_TRUE(feedback_.triggered()); 338 EXPECT_EQ(3u, feedback_.last_frame_acked()); 339 } 340 341 TEST_F(CastMessageBuilderTest, InOrderRps) { 342 // Create a pattern - skip to rps, and don't look back. 343 SetFrameIds(0, 0); 344 SetPacketId(0); 345 SetMaxPacketId(0); 346 SetKeyFrame(true); 347 InsertPacket(); 348 testing_clock_.Advance( 349 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 350 EXPECT_TRUE(feedback_.triggered()); 351 EXPECT_EQ(0u, feedback_.last_frame_acked()); 352 SetFrameIds(1, 0); 353 SetPacketId(0); 354 SetMaxPacketId(1); 355 SetKeyFrame(false); 356 InsertPacket(); 357 testing_clock_.Advance( 358 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 359 EXPECT_FALSE(feedback_.triggered()); 360 SetFrameIds(3, 0); 361 SetPacketId(0); 362 SetMaxPacketId(0); 363 SetKeyFrame(false); 364 InsertPacket(); 365 testing_clock_.Advance( 366 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 367 framer_.RemoveOldFrames(3); // Simulate 3 being pulled for rendering. 368 testing_clock_.Advance( 369 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 370 cast_msg_builder_->UpdateCastMessage(); 371 EXPECT_TRUE(feedback_.triggered()); 372 EXPECT_EQ(3u, feedback_.last_frame_acked()); 373 // Make an old frame complete - should not trigger an ack. 374 SetFrameIds(1, 0); 375 SetPacketId(1); 376 SetMaxPacketId(1); 377 SetKeyFrame(false); 378 InsertPacket(); 379 testing_clock_.Advance( 380 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 381 EXPECT_FALSE(feedback_.triggered()); 382 EXPECT_EQ(3u, feedback_.last_frame_acked()); 383 } 384 385 TEST_F(CastMessageBuilderTest, SlowDownAck) { 386 SetDecoderSlowerThanMaxFrameRate(3); 387 SetFrameIds(0, 0); 388 SetPacketId(0); 389 SetMaxPacketId(0); 390 SetKeyFrame(true); 391 InsertPacket(); 392 393 uint32 frame_id; 394 testing_clock_.Advance( 395 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 396 SetKeyFrame(false); 397 for (frame_id = 1; frame_id < 3; ++frame_id) { 398 EXPECT_TRUE(feedback_.triggered()); 399 EXPECT_EQ(frame_id - 1, feedback_.last_frame_acked()); 400 SetFrameIds(frame_id, frame_id - 1); 401 InsertPacket(); 402 testing_clock_.Advance( 403 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 404 } 405 // We should now have entered the slowdown ACK state. 406 uint32 expected_frame_id = 1; 407 for (; frame_id < 10; ++frame_id) { 408 if (frame_id % 2) { 409 ++expected_frame_id; 410 EXPECT_TRUE(feedback_.triggered()); 411 } else { 412 EXPECT_FALSE(feedback_.triggered()); 413 } 414 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked()); 415 SetFrameIds(frame_id, frame_id - 1); 416 InsertPacket(); 417 testing_clock_.Advance( 418 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 419 } 420 EXPECT_FALSE(feedback_.triggered()); 421 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked()); 422 423 // Simulate frame_id being pulled for rendering. 424 framer_.RemoveOldFrames(frame_id); 425 // We should now leave the slowdown ACK state. 426 ++frame_id; 427 SetFrameIds(frame_id, frame_id - 1); 428 InsertPacket(); 429 testing_clock_.Advance( 430 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); 431 EXPECT_TRUE(feedback_.triggered()); 432 EXPECT_EQ(frame_id, feedback_.last_frame_acked()); 433 } 434 435 } // namespace cast 436 } // namespace media 437