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.
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"
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);
24 typedef std::map
<uint32
, size_t> MissingPacketsMap
;
26 class NackFeedbackVerification
: public RtpPayloadFeedback
{
28 NackFeedbackVerification()
29 : triggered_(false), missing_packets_(), last_frame_acked_(0) {}
31 void CastFeedback(const RtcpCastMessage
& cast_feedback
) final
{
32 EXPECT_EQ(kSsrc
, cast_feedback
.media_ssrc
);
34 last_frame_acked_
= cast_feedback
.ack_frame_id
;
36 MissingFramesAndPacketsMap::const_iterator frame_it
=
37 cast_feedback
.missing_frames_and_packets
.begin();
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
));
48 missing_packets_
.insert(
49 std::make_pair(frame_it
->first
, frame_it
->second
.size()));
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())
65 // Holds value for one call.
67 bool ret_val
= triggered_
;
72 uint32
last_frame_acked() { return last_frame_acked_
; }
76 MissingPacketsMap missing_packets_
; // Missing packets per frame.
77 uint32 last_frame_acked_
;
79 DISALLOW_COPY_AND_ASSIGN(NackFeedbackVerification
);
83 class CastMessageBuilderTest
: public ::testing::Test
{
85 CastMessageBuilderTest()
86 : framer_(&testing_clock_
,
91 cast_msg_builder_(new CastMessageBuilder(&testing_clock_
,
97 rtp_header_
.sender_ssrc
= kSsrc
;
98 rtp_header_
.is_key_frame
= false;
99 testing_clock_
.Advance(
100 base::TimeDelta::FromMilliseconds(kStartMillisecond
));
103 ~CastMessageBuilderTest() override
{}
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
;
110 void SetPacketId(uint16 packet_id
) { rtp_header_
.packet_id
= packet_id
; }
112 void SetMaxPacketId(uint16 max_packet_id
) {
113 rtp_header_
.max_packet_id
= max_packet_id
;
116 void SetKeyFrame(bool is_key
) { rtp_header_
.is_key_frame
= is_key
; }
118 void InsertPacket() {
121 if (framer_
.InsertPacket(&payload
, 1, rtp_header_
, &duplicate
)) {
122 cast_msg_builder_
->CompleteFrameReceived(rtp_header_
.frame_id
);
124 cast_msg_builder_
->UpdateCastMessage();
127 void SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames
) {
128 cast_msg_builder_
.reset(new CastMessageBuilder(&testing_clock_
,
133 max_unacked_frames
));
136 NackFeedbackVerification feedback_
;
138 scoped_ptr
<CastMessageBuilder
> cast_msg_builder_
;
139 RtpCastHeader rtp_header_
;
140 base::SimpleTestTickClock testing_clock_
;
142 DISALLOW_COPY_AND_ASSIGN(CastMessageBuilderTest
);
145 TEST_F(CastMessageBuilderTest
, OneFrameNackList
) {
150 testing_clock_
.Advance(
151 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
152 EXPECT_FALSE(feedback_
.triggered());
153 testing_clock_
.Advance(
154 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
157 EXPECT_TRUE(feedback_
.triggered());
158 EXPECT_EQ(4u, feedback_
.num_missing_packets(0));
161 TEST_F(CastMessageBuilderTest
, CompleteFrameMissing
) {
166 testing_clock_
.Advance(
167 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
172 EXPECT_TRUE(feedback_
.triggered());
173 EXPECT_EQ(kRtcpCastAllPacketsLost
, feedback_
.num_missing_packets(1));
176 TEST_F(CastMessageBuilderTest
, RemoveOldFrames
) {
181 EXPECT_FALSE(feedback_
.triggered());
182 testing_clock_
.Advance(
183 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
188 EXPECT_TRUE(feedback_
.triggered());
189 testing_clock_
.Advance(
190 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
195 EXPECT_TRUE(feedback_
.triggered());
196 EXPECT_EQ(2u, feedback_
.last_frame_acked());
197 testing_clock_
.Advance(
198 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
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
));
216 EXPECT_FALSE(feedback_
.triggered());
217 testing_clock_
.Advance(
218 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
220 EXPECT_TRUE(feedback_
.triggered());
221 EXPECT_EQ(5u, feedback_
.last_frame_acked());
224 TEST_F(CastMessageBuilderTest
, NackUntilMaxReceivedPacket
) {
230 testing_clock_
.Advance(
231 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
234 EXPECT_TRUE(feedback_
.triggered());
235 EXPECT_EQ(4u, feedback_
.num_missing_packets(0));
238 TEST_F(CastMessageBuilderTest
, NackUntilMaxReceivedPacketNextFrame
) {
244 testing_clock_
.Advance(
245 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
248 testing_clock_
.Advance(
249 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
250 EXPECT_TRUE(feedback_
.triggered());
251 EXPECT_EQ(4u, feedback_
.num_missing_packets(0));
257 testing_clock_
.Advance(
258 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
259 EXPECT_TRUE(feedback_
.triggered());
260 EXPECT_EQ(19u, feedback_
.num_missing_packets(0));
263 TEST_F(CastMessageBuilderTest
, NackUntilMaxReceivedPacketNextKey
) {
269 testing_clock_
.Advance(
270 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
273 testing_clock_
.Advance(
274 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
275 EXPECT_TRUE(feedback_
.triggered());
276 EXPECT_EQ(4u, feedback_
.num_missing_packets(0));
282 testing_clock_
.Advance(
283 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
284 EXPECT_TRUE(feedback_
.triggered());
285 EXPECT_EQ(0u, feedback_
.num_missing_packets(0));
288 TEST_F(CastMessageBuilderTest
, Reset
) {
290 testing_clock_
.Advance(
291 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
292 cast_msg_builder_
->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));
300 TEST_F(CastMessageBuilderTest
, DeltaAfterReset
) {
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();
315 EXPECT_FALSE(feedback_
.triggered());
318 TEST_F(CastMessageBuilderTest
, BasicRps
) {
324 testing_clock_
.Advance(
325 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs
));
326 EXPECT_TRUE(feedback_
.triggered());
327 EXPECT_EQ(0u, feedback_
.last_frame_acked());
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());
341 TEST_F(CastMessageBuilderTest
, InOrderRps
) {
342 // Create a pattern - skip to rps, and don't look back.
348 testing_clock_
.Advance(
349 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
350 EXPECT_TRUE(feedback_
.triggered());
351 EXPECT_EQ(0u, feedback_
.last_frame_acked());
357 testing_clock_
.Advance(
358 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
359 EXPECT_FALSE(feedback_
.triggered());
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.
379 testing_clock_
.Advance(
380 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
381 EXPECT_FALSE(feedback_
.triggered());
382 EXPECT_EQ(3u, feedback_
.last_frame_acked());
385 TEST_F(CastMessageBuilderTest
, SlowDownAck
) {
386 SetDecoderSlowerThanMaxFrameRate(3);
394 testing_clock_
.Advance(
395 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
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);
402 testing_clock_
.Advance(
403 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
405 // We should now have entered the slowdown ACK state.
406 uint32 expected_frame_id
= 1;
407 for (; frame_id
< 10; ++frame_id
) {
410 EXPECT_TRUE(feedback_
.triggered());
412 EXPECT_FALSE(feedback_
.triggered());
414 EXPECT_EQ(expected_frame_id
, feedback_
.last_frame_acked());
415 SetFrameIds(frame_id
, frame_id
- 1);
417 testing_clock_
.Advance(
418 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
420 EXPECT_FALSE(feedback_
.triggered());
421 EXPECT_EQ(expected_frame_id
, feedback_
.last_frame_acked());
423 // Simulate frame_id being pulled for rendering.
424 framer_
.RemoveOldFrames(frame_id
);
425 // We should now leave the slowdown ACK state.
427 SetFrameIds(frame_id
, frame_id
- 1);
429 testing_clock_
.Advance(
430 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs
));
431 EXPECT_TRUE(feedback_
.triggered());
432 EXPECT_EQ(frame_id
, feedback_
.last_frame_acked());