Home | History | Annotate | Download | only in rtp
      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.
      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/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"
     14 
     15 namespace media {
     16 namespace cast {
     17 
     18 namespace {
     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);
     23 
     24 typedef std::map<uint32, size_t> MissingPacketsMap;
     25 
     26 class NackFeedbackVerification : public RtpPayloadFeedback {
     27  public:
     28   NackFeedbackVerification()
     29       : triggered_(false), missing_packets_(), last_frame_acked_(0) {}
     30 
     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 
     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())
     60       return 0;
     61 
     62     return it->second;
     63   }
     64 
     65   // Holds value for one call.
     66   bool triggered() {
     67     bool ret_val = triggered_;
     68     triggered_ = false;
     69     return ret_val;
     70   }
     71 
     72   uint32 last_frame_acked() { return last_frame_acked_; }
     73 
     74  private:
     75   bool triggered_;
     76   MissingPacketsMap missing_packets_;  // Missing packets per frame.
     77   uint32 last_frame_acked_;
     78 
     79   DISALLOW_COPY_AND_ASSIGN(NackFeedbackVerification);
     80 };
     81 }  // namespace
     82 
     83 class CastMessageBuilderTest : public ::testing::Test {
     84  protected:
     85   CastMessageBuilderTest()
     86       : framer_(&testing_clock_,
     87                 &feedback_,
     88                 kSsrc,
     89                 true,
     90                 10),
     91         cast_msg_builder_(new CastMessageBuilder(&testing_clock_,
     92                                                  &feedback_,
     93                                                  &framer_,
     94                                                  kSsrc,
     95                                                  true,
     96                                                  0)) {
     97     rtp_header_.sender_ssrc = kSsrc;
     98     rtp_header_.is_key_frame = false;
     99     testing_clock_.Advance(
    100         base::TimeDelta::FromMilliseconds(kStartMillisecond));
    101   }
    102 
    103   virtual ~CastMessageBuilderTest() {}
    104 
    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;
    108   }
    109 
    110   void SetPacketId(uint16 packet_id) { rtp_header_.packet_id = packet_id; }
    111 
    112   void SetMaxPacketId(uint16 max_packet_id) {
    113     rtp_header_.max_packet_id = max_packet_id;
    114   }
    115 
    116   void SetKeyFrame(bool is_key) { rtp_header_.is_key_frame = is_key; }
    117 
    118   void InsertPacket() {
    119     bool duplicate;
    120     uint8 payload = 0;
    121     if (framer_.InsertPacket(&payload, 1, rtp_header_, &duplicate)) {
    122       cast_msg_builder_->CompleteFrameReceived(rtp_header_.frame_id);
    123     }
    124     cast_msg_builder_->UpdateCastMessage();
    125   }
    126 
    127   void SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames) {
    128     cast_msg_builder_.reset(new CastMessageBuilder(&testing_clock_,
    129                                                    &feedback_,
    130                                                    &framer_,
    131                                                    kSsrc,
    132                                                    false,
    133                                                    max_unacked_frames));
    134   }
    135 
    136   NackFeedbackVerification feedback_;
    137   Framer framer_;
    138   scoped_ptr<CastMessageBuilder> cast_msg_builder_;
    139   RtpCastHeader rtp_header_;
    140   base::SimpleTestTickClock testing_clock_;
    141 
    142   DISALLOW_COPY_AND_ASSIGN(CastMessageBuilderTest);
    143 };
    144 
    145 TEST_F(CastMessageBuilderTest, OneFrameNackList) {
    146   SetFrameIds(0, 0);
    147   SetPacketId(4);
    148   SetMaxPacketId(10);
    149   InsertPacket();
    150   testing_clock_.Advance(
    151       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    152   EXPECT_FALSE(feedback_.triggered());
    153   testing_clock_.Advance(
    154       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    155   SetPacketId(5);
    156   InsertPacket();
    157   EXPECT_TRUE(feedback_.triggered());
    158   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    159 }
    160 
    161 TEST_F(CastMessageBuilderTest, CompleteFrameMissing) {
    162   SetFrameIds(0, 0);
    163   SetPacketId(2);
    164   SetMaxPacketId(5);
    165   InsertPacket();
    166   testing_clock_.Advance(
    167       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    168   SetFrameIds(2, 1);
    169   SetPacketId(2);
    170   SetMaxPacketId(5);
    171   InsertPacket();
    172   EXPECT_TRUE(feedback_.triggered());
    173   EXPECT_EQ(kRtcpCastAllPacketsLost, feedback_.num_missing_packets(1));
    174 }
    175 
    176 TEST_F(CastMessageBuilderTest, RemoveOldFrames) {
    177   SetFrameIds(1, 0);
    178   SetPacketId(0);
    179   SetMaxPacketId(1);
    180   InsertPacket();
    181   EXPECT_FALSE(feedback_.triggered());
    182   testing_clock_.Advance(
    183       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    184   SetFrameIds(2, 1);
    185   SetPacketId(0);
    186   SetMaxPacketId(0);
    187   InsertPacket();
    188   EXPECT_TRUE(feedback_.triggered());
    189   testing_clock_.Advance(
    190       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    191   SetFrameIds(3, 2);
    192   SetPacketId(0);
    193   SetMaxPacketId(5);
    194   InsertPacket();
    195   EXPECT_TRUE(feedback_.triggered());
    196   EXPECT_EQ(2u, feedback_.last_frame_acked());
    197   testing_clock_.Advance(
    198       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    199   SetFrameIds(5, 5);
    200   SetPacketId(0);
    201   SetMaxPacketId(0);
    202   SetKeyFrame(true);
    203   InsertPacket();
    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));
    212   SetFrameIds(1, 0);
    213   SetPacketId(1);
    214   SetMaxPacketId(1);
    215   InsertPacket();
    216   EXPECT_FALSE(feedback_.triggered());
    217   testing_clock_.Advance(
    218       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    219   InsertPacket();
    220   EXPECT_TRUE(feedback_.triggered());
    221   EXPECT_EQ(5u, feedback_.last_frame_acked());
    222 }
    223 
    224 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacket) {
    225   SetFrameIds(0, 0);
    226   SetPacketId(0);
    227   SetMaxPacketId(20);
    228   SetKeyFrame(true);
    229   InsertPacket();
    230   testing_clock_.Advance(
    231       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    232   SetPacketId(5);
    233   InsertPacket();
    234   EXPECT_TRUE(feedback_.triggered());
    235   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    236 }
    237 
    238 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextFrame) {
    239   SetFrameIds(0, 0);
    240   SetPacketId(0);
    241   SetMaxPacketId(20);
    242   SetKeyFrame(true);
    243   InsertPacket();
    244   testing_clock_.Advance(
    245       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    246   SetPacketId(5);
    247   InsertPacket();
    248   testing_clock_.Advance(
    249       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    250   EXPECT_TRUE(feedback_.triggered());
    251   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    252   SetFrameIds(1, 0);
    253   SetMaxPacketId(2);
    254   SetPacketId(0);
    255   SetKeyFrame(false);
    256   InsertPacket();
    257   testing_clock_.Advance(
    258       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    259   EXPECT_TRUE(feedback_.triggered());
    260   EXPECT_EQ(19u, feedback_.num_missing_packets(0));
    261 }
    262 
    263 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextKey) {
    264   SetFrameIds(0, 0);
    265   SetPacketId(0);
    266   SetMaxPacketId(20);
    267   SetKeyFrame(true);
    268   InsertPacket();
    269   testing_clock_.Advance(
    270       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    271   SetPacketId(5);
    272   InsertPacket();
    273   testing_clock_.Advance(
    274       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    275   EXPECT_TRUE(feedback_.triggered());
    276   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    277   SetFrameIds(1, 1);
    278   SetMaxPacketId(0);
    279   SetPacketId(0);
    280   SetKeyFrame(true);
    281   InsertPacket();
    282   testing_clock_.Advance(
    283       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    284   EXPECT_TRUE(feedback_.triggered());
    285   EXPECT_EQ(0u, feedback_.num_missing_packets(0));
    286 }
    287 
    288 TEST_F(CastMessageBuilderTest, Reset) {
    289   InsertPacket();
    290   testing_clock_.Advance(
    291       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    292   cast_msg_builder_->Reset();
    293   framer_.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));
    298 }
    299 
    300 TEST_F(CastMessageBuilderTest, DeltaAfterReset) {
    301   SetFrameIds(0, 0);
    302   SetPacketId(0);
    303   SetMaxPacketId(0);
    304   SetKeyFrame(true);
    305   InsertPacket();
    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();
    311   SetFrameIds(1, 0);
    312   SetPacketId(0);
    313   SetMaxPacketId(0);
    314   SetKeyFrame(true);
    315   EXPECT_FALSE(feedback_.triggered());
    316 }
    317 
    318 TEST_F(CastMessageBuilderTest, BasicRps) {
    319   SetFrameIds(0, 0);
    320   SetPacketId(0);
    321   SetMaxPacketId(0);
    322   SetKeyFrame(true);
    323   InsertPacket();
    324   testing_clock_.Advance(
    325       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    326   EXPECT_TRUE(feedback_.triggered());
    327   EXPECT_EQ(0u, feedback_.last_frame_acked());
    328   SetFrameIds(3, 0);
    329   SetKeyFrame(false);
    330   InsertPacket();
    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());
    339 }
    340 
    341 TEST_F(CastMessageBuilderTest, InOrderRps) {
    342   // Create a pattern - skip to rps, and don't look back.
    343   SetFrameIds(0, 0);
    344   SetPacketId(0);
    345   SetMaxPacketId(0);
    346   SetKeyFrame(true);
    347   InsertPacket();
    348   testing_clock_.Advance(
    349       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    350   EXPECT_TRUE(feedback_.triggered());
    351   EXPECT_EQ(0u, feedback_.last_frame_acked());
    352   SetFrameIds(1, 0);
    353   SetPacketId(0);
    354   SetMaxPacketId(1);
    355   SetKeyFrame(false);
    356   InsertPacket();
    357   testing_clock_.Advance(
    358       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    359   EXPECT_FALSE(feedback_.triggered());
    360   SetFrameIds(3, 0);
    361   SetPacketId(0);
    362   SetMaxPacketId(0);
    363   SetKeyFrame(false);
    364   InsertPacket();
    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.
    374   SetFrameIds(1, 0);
    375   SetPacketId(1);
    376   SetMaxPacketId(1);
    377   SetKeyFrame(false);
    378   InsertPacket();
    379   testing_clock_.Advance(
    380       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    381   EXPECT_FALSE(feedback_.triggered());
    382   EXPECT_EQ(3u, feedback_.last_frame_acked());
    383 }
    384 
    385 TEST_F(CastMessageBuilderTest, SlowDownAck) {
    386   SetDecoderSlowerThanMaxFrameRate(3);
    387   SetFrameIds(0, 0);
    388   SetPacketId(0);
    389   SetMaxPacketId(0);
    390   SetKeyFrame(true);
    391   InsertPacket();
    392 
    393   uint32 frame_id;
    394   testing_clock_.Advance(
    395       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    396   SetKeyFrame(false);
    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);
    401     InsertPacket();
    402     testing_clock_.Advance(
    403         base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    404   }
    405   // We should now have entered the slowdown ACK state.
    406   uint32 expected_frame_id = 1;
    407   for (; frame_id < 10; ++frame_id) {
    408     if (frame_id % 2) {
    409       ++expected_frame_id;
    410       EXPECT_TRUE(feedback_.triggered());
    411     } else {
    412       EXPECT_FALSE(feedback_.triggered());
    413     }
    414     EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
    415     SetFrameIds(frame_id, frame_id - 1);
    416     InsertPacket();
    417     testing_clock_.Advance(
    418         base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    419   }
    420   EXPECT_FALSE(feedback_.triggered());
    421   EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
    422 
    423   // Simulate frame_id being pulled for rendering.
    424   framer_.RemoveOldFrames(frame_id);
    425   // We should now leave the slowdown ACK state.
    426   ++frame_id;
    427   SetFrameIds(frame_id, frame_id - 1);
    428   InsertPacket();
    429   testing_clock_.Advance(
    430       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    431   EXPECT_TRUE(feedback_.triggered());
    432   EXPECT_EQ(frame_id, feedback_.last_frame_acked());
    433 }
    434 
    435 }  // namespace cast
    436 }  // namespace media
    437