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 "base/memory/scoped_ptr.h"
6 #include "base/test/simple_test_tick_clock.h"
7 #include "media/cast/framer/cast_message_builder.h"
8 #include "media/cast/rtcp/rtcp.h"
9 #include "media/cast/rtp_receiver/rtp_receiver_defines.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace media {
13 namespace cast {
14
15 static const uint32 kSsrc = 0x1234;
16 static const uint32 kShortTimeIncrementMs = 10;
17 static const uint32 kLongTimeIncrementMs = 40;
18 static const int64 kStartMillisecond = GG_INT64_C(12345678900000);
19
20 namespace {
21 typedef std::map<uint32, size_t> MissingPacketsMap;
22
23 class NackFeedbackVerification : public RtpPayloadFeedback {
24 public:
NackFeedbackVerification()25 NackFeedbackVerification()
26 : triggered_(false),
27 missing_packets_(),
28 last_frame_acked_(0) {}
29
30
CastFeedback(const RtcpCastMessage & cast_feedback)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
num_missing_packets(uint32 frame_id)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()) return 0;
60
61 return it->second;
62 }
63
64 // Holds value for one call.
triggered()65 bool triggered() {
66 bool ret_val = triggered_;
67 triggered_ = false;
68 return ret_val;
69 }
70
last_frame_acked()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 } // namespace
79
80 class CastMessageBuilderTest : public ::testing::Test {
81 protected:
CastMessageBuilderTest()82 CastMessageBuilderTest()
83 : cast_msg_builder_(new CastMessageBuilder(&testing_clock_,
84 &feedback_,
85 &frame_id_map_,
86 kSsrc,
87 true,
88 0)) {
89 rtp_header_.webrtc.header.ssrc = kSsrc;
90 rtp_header_.is_key_frame = false;
91 testing_clock_.Advance(
92 base::TimeDelta::FromMilliseconds(kStartMillisecond));
93 }
94
~CastMessageBuilderTest()95 virtual ~CastMessageBuilderTest() {}
96
SetFrameId(uint32 frame_id)97 void SetFrameId(uint32 frame_id) {
98 rtp_header_.frame_id = frame_id;
99 }
100
SetPacketId(uint16 packet_id)101 void SetPacketId(uint16 packet_id) {
102 rtp_header_.packet_id = packet_id;
103 }
104
SetMaxPacketId(uint16 max_packet_id)105 void SetMaxPacketId(uint16 max_packet_id) {
106 rtp_header_.max_packet_id = max_packet_id;
107 }
108
SetKeyFrame(bool is_key)109 void SetKeyFrame(bool is_key) {
110 rtp_header_.is_key_frame = is_key;
111 }
112
SetReferenceFrameId(uint32 reference_frame_id)113 void SetReferenceFrameId(uint32 reference_frame_id) {
114 rtp_header_.is_reference = true;
115 rtp_header_.reference_frame_id = reference_frame_id;
116 }
117
InsertPacket()118 void InsertPacket() {
119 bool complete = false;
120 frame_id_map_.InsertPacket(rtp_header_, &complete);
121 if (complete) {
122 cast_msg_builder_->CompleteFrameReceived(rtp_header_.frame_id,
123 rtp_header_.is_key_frame);
124 }
125 cast_msg_builder_->UpdateCastMessage();
126 }
127
SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames)128 void SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames) {
129 cast_msg_builder_.reset(new CastMessageBuilder(&testing_clock_,
130 &feedback_,
131 &frame_id_map_,
132 kSsrc,
133 false,
134 max_unacked_frames));
135 }
136
137 NackFeedbackVerification feedback_;
138 scoped_ptr<CastMessageBuilder> cast_msg_builder_;
139 RtpCastHeader rtp_header_;
140 FrameIdMap frame_id_map_;
141 base::SimpleTestTickClock testing_clock_;
142 };
143
TEST_F(CastMessageBuilderTest,StartWithAKeyFrame)144 TEST_F(CastMessageBuilderTest, StartWithAKeyFrame) {
145 SetFrameId(3);
146 SetPacketId(0);
147 SetMaxPacketId(0);
148 InsertPacket();
149 // Should not trigger ack.
150 EXPECT_FALSE(feedback_.triggered());
151 SetFrameId(5);
152 SetPacketId(0);
153 SetMaxPacketId(0);
154 SetKeyFrame(true);
155 InsertPacket();
156 frame_id_map_.RemoveOldFrames(5); // Simulate 5 being pulled for rendering.
157 testing_clock_.Advance(
158 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
159 cast_msg_builder_->UpdateCastMessage();
160 EXPECT_TRUE(feedback_.triggered());
161 EXPECT_EQ(5u, feedback_.last_frame_acked());
162 }
163
TEST_F(CastMessageBuilderTest,OneFrameNackList)164 TEST_F(CastMessageBuilderTest, OneFrameNackList) {
165 SetFrameId(0);
166 SetPacketId(4);
167 SetMaxPacketId(10);
168 InsertPacket();
169 testing_clock_.Advance(
170 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
171 EXPECT_FALSE(feedback_.triggered());
172 testing_clock_.Advance(
173 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
174 SetPacketId(5);
175 InsertPacket();
176 EXPECT_TRUE(feedback_.triggered());
177 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
178 }
179
TEST_F(CastMessageBuilderTest,CompleteFrameMissing)180 TEST_F(CastMessageBuilderTest, CompleteFrameMissing) {
181 SetFrameId(0);
182 SetPacketId(2);
183 SetMaxPacketId(5);
184 InsertPacket();
185 testing_clock_.Advance(
186 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
187 SetFrameId(2);
188 SetPacketId(2);
189 SetMaxPacketId(5);
190 InsertPacket();
191 EXPECT_TRUE(feedback_.triggered());
192 EXPECT_EQ(kRtcpCastAllPacketsLost, feedback_.num_missing_packets(1));
193 }
194
TEST_F(CastMessageBuilderTest,FastForwardAck)195 TEST_F(CastMessageBuilderTest, FastForwardAck) {
196 SetFrameId(1);
197 SetPacketId(0);
198 SetMaxPacketId(0);
199 InsertPacket();
200 EXPECT_FALSE(feedback_.triggered());
201 testing_clock_.Advance(
202 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
203 SetFrameId(2);
204 SetPacketId(0);
205 SetMaxPacketId(0);
206 InsertPacket();
207 EXPECT_TRUE(feedback_.triggered());
208 EXPECT_EQ(kStartFrameId, feedback_.last_frame_acked());
209 testing_clock_.Advance(
210 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
211 SetFrameId(0);
212 SetPacketId(0);
213 SetMaxPacketId(0);
214 SetKeyFrame(true);
215 InsertPacket();
216 EXPECT_TRUE(feedback_.triggered());
217 EXPECT_EQ(2u, feedback_.last_frame_acked());
218 }
219
TEST_F(CastMessageBuilderTest,RemoveOldFrames)220 TEST_F(CastMessageBuilderTest, RemoveOldFrames) {
221 SetFrameId(1);
222 SetPacketId(0);
223 SetMaxPacketId(1);
224 InsertPacket();
225 EXPECT_FALSE(feedback_.triggered());
226 testing_clock_.Advance(
227 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
228 SetFrameId(2);
229 SetPacketId(0);
230 SetMaxPacketId(0);
231 InsertPacket();
232 EXPECT_TRUE(feedback_.triggered());
233 testing_clock_.Advance(
234 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
235 SetFrameId(3);
236 SetPacketId(0);
237 SetMaxPacketId(5);
238 InsertPacket();
239 EXPECT_TRUE(feedback_.triggered());
240 EXPECT_EQ(kStartFrameId, feedback_.last_frame_acked());
241 testing_clock_.Advance(
242 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
243 SetFrameId(5);
244 SetPacketId(0);
245 SetMaxPacketId(0);
246 SetKeyFrame(true);
247 InsertPacket();
248 testing_clock_.Advance(
249 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
250 frame_id_map_.RemoveOldFrames(5); // Simulate 5 being pulled for rendering.
251 cast_msg_builder_->UpdateCastMessage();
252 EXPECT_TRUE(feedback_.triggered());
253 EXPECT_EQ(5u, feedback_.last_frame_acked());
254 testing_clock_.Advance(
255 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
256 SetFrameId(1);
257 SetPacketId(1);
258 SetMaxPacketId(1);
259 InsertPacket();
260 EXPECT_FALSE(feedback_.triggered());
261 testing_clock_.Advance(
262 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
263 InsertPacket();
264 EXPECT_TRUE(feedback_.triggered());
265 EXPECT_EQ(5u, feedback_.last_frame_acked());
266 }
267
TEST_F(CastMessageBuilderTest,WrapFastForward)268 TEST_F(CastMessageBuilderTest, WrapFastForward) {
269 SetFrameId(254);
270 SetPacketId(0);
271 SetMaxPacketId(1);
272 SetKeyFrame(true);
273 InsertPacket();
274 EXPECT_FALSE(feedback_.triggered());
275 testing_clock_.Advance(
276 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
277 SetFrameId(255);
278 SetPacketId(0);
279 SetMaxPacketId(0);
280 SetKeyFrame(false);
281 InsertPacket();
282 EXPECT_TRUE(feedback_.triggered());
283 EXPECT_EQ(253u, feedback_.last_frame_acked());
284 testing_clock_.Advance(
285 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
286 SetFrameId(256);
287 SetPacketId(0);
288 SetMaxPacketId(0);
289 SetKeyFrame(false);
290 InsertPacket();
291 EXPECT_TRUE(feedback_.triggered());
292 EXPECT_EQ(253u, feedback_.last_frame_acked());
293 testing_clock_.Advance(
294 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
295 SetFrameId(254);
296 SetPacketId(1);
297 SetMaxPacketId(1);
298 SetKeyFrame(true);
299 InsertPacket();
300 EXPECT_TRUE(feedback_.triggered());
301 EXPECT_EQ(256u, feedback_.last_frame_acked());
302 }
303
TEST_F(CastMessageBuilderTest,NackUntilMaxReceivedPacket)304 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacket) {
305 SetFrameId(0);
306 SetPacketId(0);
307 SetMaxPacketId(20);
308 SetKeyFrame(true);
309 InsertPacket();
310 testing_clock_.Advance(
311 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
312 SetPacketId(5);
313 InsertPacket();
314 EXPECT_TRUE(feedback_.triggered());
315 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
316 }
317
TEST_F(CastMessageBuilderTest,NackUntilMaxReceivedPacketNextFrame)318 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextFrame) {
319 SetFrameId(0);
320 SetPacketId(0);
321 SetMaxPacketId(20);
322 SetKeyFrame(true);
323 InsertPacket();
324 testing_clock_.Advance(
325 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
326 SetPacketId(5);
327 InsertPacket();
328 testing_clock_.Advance(
329 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
330 EXPECT_TRUE(feedback_.triggered());
331 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
332 SetFrameId(1);
333 SetMaxPacketId(2);
334 SetPacketId(0);
335 SetKeyFrame(false);
336 InsertPacket();
337 testing_clock_.Advance(
338 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
339 EXPECT_TRUE(feedback_.triggered());
340 EXPECT_EQ(19u, feedback_.num_missing_packets(0));
341 }
342
TEST_F(CastMessageBuilderTest,NackUntilMaxReceivedPacketNextKey)343 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextKey) {
344 SetFrameId(0);
345 SetPacketId(0);
346 SetMaxPacketId(20);
347 SetKeyFrame(true);
348 InsertPacket();
349 testing_clock_.Advance(
350 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
351 SetPacketId(5);
352 InsertPacket();
353 testing_clock_.Advance(
354 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
355 EXPECT_TRUE(feedback_.triggered());
356 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
357 SetFrameId(1);
358 SetMaxPacketId(0);
359 SetPacketId(0);
360 SetKeyFrame(true);
361 InsertPacket();
362 testing_clock_.Advance(
363 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
364 EXPECT_TRUE(feedback_.triggered());
365 EXPECT_EQ(0u, feedback_.num_missing_packets(0));
366 }
367
TEST_F(CastMessageBuilderTest,Reset)368 TEST_F(CastMessageBuilderTest, Reset) {
369 InsertPacket();
370 testing_clock_.Advance(
371 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
372 cast_msg_builder_->Reset();
373 frame_id_map_.Clear();
374 // Should reset nack list state and request a key frame.
375 cast_msg_builder_->UpdateCastMessage();
376 EXPECT_TRUE(feedback_.triggered());
377 EXPECT_EQ(0u, feedback_.num_missing_packets(0));
378 }
379
TEST_F(CastMessageBuilderTest,DeltaAfterReset)380 TEST_F(CastMessageBuilderTest, DeltaAfterReset) {
381 SetFrameId(0);
382 SetPacketId(0);
383 SetMaxPacketId(0);
384 SetKeyFrame(true);
385 InsertPacket();
386 EXPECT_TRUE(feedback_.triggered());
387 EXPECT_EQ(0u, feedback_.num_missing_packets(0));
388 testing_clock_.Advance(
389 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
390 cast_msg_builder_->Reset();
391 SetFrameId(1);
392 SetPacketId(0);
393 SetMaxPacketId(0);
394 SetKeyFrame(true);
395 EXPECT_FALSE(feedback_.triggered());
396 }
397
TEST_F(CastMessageBuilderTest,BasicRps)398 TEST_F(CastMessageBuilderTest, BasicRps) {
399 SetFrameId(0);
400 SetPacketId(0);
401 SetMaxPacketId(0);
402 SetKeyFrame(true);
403 InsertPacket();
404 testing_clock_.Advance(
405 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
406 EXPECT_TRUE(feedback_.triggered());
407 EXPECT_EQ(0u, feedback_.last_frame_acked());
408 SetFrameId(3);
409 SetKeyFrame(false);
410 SetReferenceFrameId(0);
411 InsertPacket();
412 EXPECT_TRUE(feedback_.triggered());
413 EXPECT_EQ(0u, feedback_.last_frame_acked());
414 testing_clock_.Advance(
415 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
416 frame_id_map_.RemoveOldFrames(3); // Simulate 3 being pulled for rendering.
417 cast_msg_builder_->UpdateCastMessage();
418 EXPECT_TRUE(feedback_.triggered());
419 EXPECT_EQ(3u, feedback_.last_frame_acked());
420 }
421
TEST_F(CastMessageBuilderTest,InOrderRps)422 TEST_F(CastMessageBuilderTest, InOrderRps) {
423 // Create a pattern - skip to rps, and don't look back.
424 SetFrameId(0);
425 SetPacketId(0);
426 SetMaxPacketId(0);
427 SetKeyFrame(true);
428 InsertPacket();
429 testing_clock_.Advance(
430 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
431 EXPECT_TRUE(feedback_.triggered());
432 EXPECT_EQ(0u, feedback_.last_frame_acked());
433 SetFrameId(1);
434 SetPacketId(0);
435 SetMaxPacketId(1);
436 SetKeyFrame(false);
437 InsertPacket();
438 testing_clock_.Advance(
439 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
440 EXPECT_FALSE(feedback_.triggered());
441 SetFrameId(3);
442 SetPacketId(0);
443 SetMaxPacketId(0);
444 SetKeyFrame(false);
445 SetReferenceFrameId(0);
446 InsertPacket();
447 testing_clock_.Advance(
448 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
449 frame_id_map_.RemoveOldFrames(3); // Simulate 3 being pulled for rendering.
450 testing_clock_.Advance(
451 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
452 cast_msg_builder_->UpdateCastMessage();
453 EXPECT_TRUE(feedback_.triggered());
454 EXPECT_EQ(3u, feedback_.last_frame_acked());
455 // Make an old frame complete - should not trigger an ack.
456 SetFrameId(1);
457 SetPacketId(1);
458 SetMaxPacketId(1);
459 SetKeyFrame(false);
460 InsertPacket();
461 testing_clock_.Advance(
462 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
463 EXPECT_FALSE(feedback_.triggered());
464 EXPECT_EQ(3u, feedback_.last_frame_acked());
465 }
466
TEST_F(CastMessageBuilderTest,SlowDownAck)467 TEST_F(CastMessageBuilderTest, SlowDownAck) {
468 SetDecoderSlowerThanMaxFrameRate(3);
469 SetFrameId(0);
470 SetPacketId(0);
471 SetMaxPacketId(0);
472 SetKeyFrame(true);
473 InsertPacket();
474
475 uint32 frame_id;
476 testing_clock_.Advance(
477 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
478 SetKeyFrame(false);
479 for (frame_id = 1; frame_id < 3; ++frame_id) {
480 EXPECT_TRUE(feedback_.triggered());
481 EXPECT_EQ(frame_id - 1, feedback_.last_frame_acked());
482 SetFrameId(frame_id);
483 InsertPacket();
484 testing_clock_.Advance(
485 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
486 }
487 // We should now have entered the slowdown ACK state.
488 uint32 expected_frame_id = 1;
489 for (; frame_id < 10; ++frame_id) {
490 if (frame_id % 2) ++expected_frame_id;
491 EXPECT_TRUE(feedback_.triggered());
492 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
493 SetFrameId(frame_id);
494 InsertPacket();
495 testing_clock_.Advance(
496 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
497 }
498 EXPECT_TRUE(feedback_.triggered());
499 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
500
501 // Simulate frame_id being pulled for rendering.
502 frame_id_map_.RemoveOldFrames(frame_id);
503 // We should now leave the slowdown ACK state.
504 ++frame_id;
505 SetFrameId(frame_id);
506 InsertPacket();
507 testing_clock_.Advance(
508 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
509 EXPECT_TRUE(feedback_.triggered());
510 EXPECT_EQ(frame_id, feedback_.last_frame_acked());
511 }
512
513 } // namespace cast
514 } // namespace media
515