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/rtp_receiver_defines.h"
12 #include "testing/gtest/include/gtest/gtest.h"
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);
23 typedef std::map<uint32, size_t> MissingPacketsMap;
25 class NackFeedbackVerification : public RtpPayloadFeedback {
27 NackFeedbackVerification()
28 : triggered_(false), missing_packets_(), last_frame_acked_(0) {}
30 virtual void CastFeedback(const RtcpCastMessage& cast_feedback) OVERRIDE {
31 EXPECT_EQ(kSsrc, cast_feedback.media_ssrc);
33 last_frame_acked_ = cast_feedback.ack_frame_id;
35 MissingFramesAndPacketsMap::const_iterator frame_it =
36 cast_feedback.missing_frames_and_packets.begin();
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));
47 missing_packets_.insert(
48 std::make_pair(frame_it->first, frame_it->second.size()));
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())
64 // Holds value for one call.
66 bool ret_val = triggered_;
71 uint32 last_frame_acked() { return last_frame_acked_; }
75 MissingPacketsMap missing_packets_; // Missing packets per frame.
76 uint32 last_frame_acked_;
78 DISALLOW_COPY_AND_ASSIGN(NackFeedbackVerification);
82 class CastMessageBuilderTest : public ::testing::Test {
84 CastMessageBuilderTest()
85 : cast_msg_builder_(new CastMessageBuilder(&testing_clock_,
91 rtp_header_.sender_ssrc = kSsrc;
92 rtp_header_.is_key_frame = false;
93 testing_clock_.Advance(
94 base::TimeDelta::FromMilliseconds(kStartMillisecond));
97 virtual ~CastMessageBuilderTest() {}
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;
104 void SetPacketId(uint16 packet_id) { rtp_header_.packet_id = packet_id; }
106 void SetMaxPacketId(uint16 max_packet_id) {
107 rtp_header_.max_packet_id = max_packet_id;
110 void SetKeyFrame(bool is_key) { rtp_header_.is_key_frame = is_key; }
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);
117 cast_msg_builder_->UpdateCastMessage();
120 void SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames) {
121 cast_msg_builder_.reset(new CastMessageBuilder(&testing_clock_,
126 max_unacked_frames));
129 NackFeedbackVerification feedback_;
130 scoped_ptr<CastMessageBuilder> cast_msg_builder_;
131 RtpCastHeader rtp_header_;
132 FrameIdMap frame_id_map_;
133 base::SimpleTestTickClock testing_clock_;
135 DISALLOW_COPY_AND_ASSIGN(CastMessageBuilderTest);
138 TEST_F(CastMessageBuilderTest, OneFrameNackList) {
143 testing_clock_.Advance(
144 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
145 EXPECT_FALSE(feedback_.triggered());
146 testing_clock_.Advance(
147 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
150 EXPECT_TRUE(feedback_.triggered());
151 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
154 TEST_F(CastMessageBuilderTest, CompleteFrameMissing) {
159 testing_clock_.Advance(
160 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
165 EXPECT_TRUE(feedback_.triggered());
166 EXPECT_EQ(kRtcpCastAllPacketsLost, feedback_.num_missing_packets(1));
169 TEST_F(CastMessageBuilderTest, RemoveOldFrames) {
174 EXPECT_FALSE(feedback_.triggered());
175 testing_clock_.Advance(
176 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
181 EXPECT_TRUE(feedback_.triggered());
182 testing_clock_.Advance(
183 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
188 EXPECT_TRUE(feedback_.triggered());
189 EXPECT_EQ(2u, feedback_.last_frame_acked());
190 testing_clock_.Advance(
191 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
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));
209 EXPECT_FALSE(feedback_.triggered());
210 testing_clock_.Advance(
211 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
213 EXPECT_TRUE(feedback_.triggered());
214 EXPECT_EQ(5u, feedback_.last_frame_acked());
217 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacket) {
223 testing_clock_.Advance(
224 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
227 EXPECT_TRUE(feedback_.triggered());
228 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
231 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextFrame) {
237 testing_clock_.Advance(
238 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
241 testing_clock_.Advance(
242 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
243 EXPECT_TRUE(feedback_.triggered());
244 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
250 testing_clock_.Advance(
251 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
252 EXPECT_TRUE(feedback_.triggered());
253 EXPECT_EQ(19u, feedback_.num_missing_packets(0));
256 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextKey) {
262 testing_clock_.Advance(
263 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
266 testing_clock_.Advance(
267 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
268 EXPECT_TRUE(feedback_.triggered());
269 EXPECT_EQ(4u, feedback_.num_missing_packets(0));
275 testing_clock_.Advance(
276 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
277 EXPECT_TRUE(feedback_.triggered());
278 EXPECT_EQ(0u, feedback_.num_missing_packets(0));
281 TEST_F(CastMessageBuilderTest, Reset) {
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));
293 TEST_F(CastMessageBuilderTest, DeltaAfterReset) {
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();
308 EXPECT_FALSE(feedback_.triggered());
311 TEST_F(CastMessageBuilderTest, BasicRps) {
317 testing_clock_.Advance(
318 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
319 EXPECT_TRUE(feedback_.triggered());
320 EXPECT_EQ(0u, feedback_.last_frame_acked());
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());
334 TEST_F(CastMessageBuilderTest, InOrderRps) {
335 // Create a pattern - skip to rps, and don't look back.
341 testing_clock_.Advance(
342 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
343 EXPECT_TRUE(feedback_.triggered());
344 EXPECT_EQ(0u, feedback_.last_frame_acked());
350 testing_clock_.Advance(
351 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
352 EXPECT_FALSE(feedback_.triggered());
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.
372 testing_clock_.Advance(
373 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
374 EXPECT_FALSE(feedback_.triggered());
375 EXPECT_EQ(3u, feedback_.last_frame_acked());
378 TEST_F(CastMessageBuilderTest, SlowDownAck) {
379 SetDecoderSlowerThanMaxFrameRate(3);
387 testing_clock_.Advance(
388 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
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);
395 testing_clock_.Advance(
396 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
398 // We should now have entered the slowdown ACK state.
399 uint32 expected_frame_id = 1;
400 for (; frame_id < 10; ++frame_id) {
403 EXPECT_TRUE(feedback_.triggered());
405 EXPECT_FALSE(feedback_.triggered());
407 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
408 SetFrameIds(frame_id, frame_id - 1);
410 testing_clock_.Advance(
411 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
413 EXPECT_FALSE(feedback_.triggered());
414 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
416 // Simulate frame_id being pulled for rendering.
417 frame_id_map_.RemoveOldFrames(frame_id);
418 // We should now leave the slowdown ACK state.
420 SetFrameIds(frame_id, frame_id - 1);
422 testing_clock_.Advance(
423 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
424 EXPECT_TRUE(feedback_.triggered());
425 EXPECT_EQ(frame_id, feedback_.last_frame_acked());