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