• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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