Home | History | Annotate | Download | only in framer
      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 <stdint.h>
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/test/simple_test_tick_clock.h"
      9 #include "media/cast/framer/cast_message_builder.h"
     10 #include "media/cast/rtcp/rtcp.h"
     11 #include "media/cast/rtp_receiver/rtp_receiver_defines.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace media {
     15 namespace cast {
     16 
     17 namespace {
     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);
     22 
     23 typedef std::map<uint32, size_t> MissingPacketsMap;
     24 
     25 class NackFeedbackVerification : public RtpPayloadFeedback {
     26  public:
     27   NackFeedbackVerification()
     28       : triggered_(false), missing_packets_(), last_frame_acked_(0) {}
     29 
     30   virtual void CastFeedback(const RtcpCastMessage& cast_feedback) OVERRIDE {
     31     EXPECT_EQ(kSsrc, cast_feedback.media_ssrc_);
     32 
     33     last_frame_acked_ = cast_feedback.ack_frame_id_;
     34 
     35     MissingFramesAndPacketsMap::const_iterator frame_it =
     36         cast_feedback.missing_frames_and_packets_.begin();
     37 
     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));
     46       } else {
     47         missing_packets_.insert(
     48             std::make_pair(frame_it->first, frame_it->second.size()));
     49       }
     50       ++frame_it;
     51     }
     52     triggered_ = true;
     53   }
     54 
     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())
     59       return 0;
     60 
     61     return it->second;
     62   }
     63 
     64   // Holds value for one call.
     65   bool triggered() {
     66     bool ret_val = triggered_;
     67     triggered_ = false;
     68     return ret_val;
     69   }
     70 
     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   DISALLOW_COPY_AND_ASSIGN(NackFeedbackVerification);
     79 };
     80 }  // namespace
     81 
     82 class CastMessageBuilderTest : public ::testing::Test {
     83  protected:
     84   CastMessageBuilderTest()
     85       : cast_msg_builder_(new CastMessageBuilder(&testing_clock_,
     86                                                  &feedback_,
     87                                                  &frame_id_map_,
     88                                                  kSsrc,
     89                                                  true,
     90                                                  0)) {
     91     rtp_header_.sender_ssrc = kSsrc;
     92     rtp_header_.is_key_frame = false;
     93     testing_clock_.Advance(
     94         base::TimeDelta::FromMilliseconds(kStartMillisecond));
     95   }
     96 
     97   virtual ~CastMessageBuilderTest() {}
     98 
     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;
    102   }
    103 
    104   void SetPacketId(uint16 packet_id) { rtp_header_.packet_id = packet_id; }
    105 
    106   void SetMaxPacketId(uint16 max_packet_id) {
    107     rtp_header_.max_packet_id = max_packet_id;
    108   }
    109 
    110   void SetKeyFrame(bool is_key) { rtp_header_.is_key_frame = is_key; }
    111 
    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);
    116     }
    117     cast_msg_builder_->UpdateCastMessage();
    118   }
    119 
    120   void SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames) {
    121     cast_msg_builder_.reset(new CastMessageBuilder(&testing_clock_,
    122                                                    &feedback_,
    123                                                    &frame_id_map_,
    124                                                    kSsrc,
    125                                                    false,
    126                                                    max_unacked_frames));
    127   }
    128 
    129   NackFeedbackVerification feedback_;
    130   scoped_ptr<CastMessageBuilder> cast_msg_builder_;
    131   RtpCastHeader rtp_header_;
    132   FrameIdMap frame_id_map_;
    133   base::SimpleTestTickClock testing_clock_;
    134 
    135   DISALLOW_COPY_AND_ASSIGN(CastMessageBuilderTest);
    136 };
    137 
    138 TEST_F(CastMessageBuilderTest, OneFrameNackList) {
    139   SetFrameIds(0, 0);
    140   SetPacketId(4);
    141   SetMaxPacketId(10);
    142   InsertPacket();
    143   testing_clock_.Advance(
    144       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    145   EXPECT_FALSE(feedback_.triggered());
    146   testing_clock_.Advance(
    147       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    148   SetPacketId(5);
    149   InsertPacket();
    150   EXPECT_TRUE(feedback_.triggered());
    151   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    152 }
    153 
    154 TEST_F(CastMessageBuilderTest, CompleteFrameMissing) {
    155   SetFrameIds(0, 0);
    156   SetPacketId(2);
    157   SetMaxPacketId(5);
    158   InsertPacket();
    159   testing_clock_.Advance(
    160       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    161   SetFrameIds(2, 1);
    162   SetPacketId(2);
    163   SetMaxPacketId(5);
    164   InsertPacket();
    165   EXPECT_TRUE(feedback_.triggered());
    166   EXPECT_EQ(kRtcpCastAllPacketsLost, feedback_.num_missing_packets(1));
    167 }
    168 
    169 TEST_F(CastMessageBuilderTest, RemoveOldFrames) {
    170   SetFrameIds(1, 0);
    171   SetPacketId(0);
    172   SetMaxPacketId(1);
    173   InsertPacket();
    174   EXPECT_FALSE(feedback_.triggered());
    175   testing_clock_.Advance(
    176       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    177   SetFrameIds(2, 1);
    178   SetPacketId(0);
    179   SetMaxPacketId(0);
    180   InsertPacket();
    181   EXPECT_TRUE(feedback_.triggered());
    182   testing_clock_.Advance(
    183       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    184   SetFrameIds(3, 2);
    185   SetPacketId(0);
    186   SetMaxPacketId(5);
    187   InsertPacket();
    188   EXPECT_TRUE(feedback_.triggered());
    189   EXPECT_EQ(2u, feedback_.last_frame_acked());
    190   testing_clock_.Advance(
    191       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    192   SetFrameIds(5, 5);
    193   SetPacketId(0);
    194   SetMaxPacketId(0);
    195   SetKeyFrame(true);
    196   InsertPacket();
    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));
    205   SetFrameIds(1, 0);
    206   SetPacketId(1);
    207   SetMaxPacketId(1);
    208   InsertPacket();
    209   EXPECT_FALSE(feedback_.triggered());
    210   testing_clock_.Advance(
    211       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    212   InsertPacket();
    213   EXPECT_TRUE(feedback_.triggered());
    214   EXPECT_EQ(5u, feedback_.last_frame_acked());
    215 }
    216 
    217 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacket) {
    218   SetFrameIds(0, 0);
    219   SetPacketId(0);
    220   SetMaxPacketId(20);
    221   SetKeyFrame(true);
    222   InsertPacket();
    223   testing_clock_.Advance(
    224       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    225   SetPacketId(5);
    226   InsertPacket();
    227   EXPECT_TRUE(feedback_.triggered());
    228   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    229 }
    230 
    231 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextFrame) {
    232   SetFrameIds(0, 0);
    233   SetPacketId(0);
    234   SetMaxPacketId(20);
    235   SetKeyFrame(true);
    236   InsertPacket();
    237   testing_clock_.Advance(
    238       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    239   SetPacketId(5);
    240   InsertPacket();
    241   testing_clock_.Advance(
    242       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    243   EXPECT_TRUE(feedback_.triggered());
    244   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    245   SetFrameIds(1, 0);
    246   SetMaxPacketId(2);
    247   SetPacketId(0);
    248   SetKeyFrame(false);
    249   InsertPacket();
    250   testing_clock_.Advance(
    251       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    252   EXPECT_TRUE(feedback_.triggered());
    253   EXPECT_EQ(19u, feedback_.num_missing_packets(0));
    254 }
    255 
    256 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextKey) {
    257   SetFrameIds(0, 0);
    258   SetPacketId(0);
    259   SetMaxPacketId(20);
    260   SetKeyFrame(true);
    261   InsertPacket();
    262   testing_clock_.Advance(
    263       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    264   SetPacketId(5);
    265   InsertPacket();
    266   testing_clock_.Advance(
    267       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    268   EXPECT_TRUE(feedback_.triggered());
    269   EXPECT_EQ(4u, feedback_.num_missing_packets(0));
    270   SetFrameIds(1, 1);
    271   SetMaxPacketId(0);
    272   SetPacketId(0);
    273   SetKeyFrame(true);
    274   InsertPacket();
    275   testing_clock_.Advance(
    276       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    277   EXPECT_TRUE(feedback_.triggered());
    278   EXPECT_EQ(0u, feedback_.num_missing_packets(0));
    279 }
    280 
    281 TEST_F(CastMessageBuilderTest, Reset) {
    282   InsertPacket();
    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));
    291 }
    292 
    293 TEST_F(CastMessageBuilderTest, DeltaAfterReset) {
    294   SetFrameIds(0, 0);
    295   SetPacketId(0);
    296   SetMaxPacketId(0);
    297   SetKeyFrame(true);
    298   InsertPacket();
    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();
    304   SetFrameIds(1, 0);
    305   SetPacketId(0);
    306   SetMaxPacketId(0);
    307   SetKeyFrame(true);
    308   EXPECT_FALSE(feedback_.triggered());
    309 }
    310 
    311 TEST_F(CastMessageBuilderTest, BasicRps) {
    312   SetFrameIds(0, 0);
    313   SetPacketId(0);
    314   SetMaxPacketId(0);
    315   SetKeyFrame(true);
    316   InsertPacket();
    317   testing_clock_.Advance(
    318       base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs));
    319   EXPECT_TRUE(feedback_.triggered());
    320   EXPECT_EQ(0u, feedback_.last_frame_acked());
    321   SetFrameIds(3, 0);
    322   SetKeyFrame(false);
    323   InsertPacket();
    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());
    332 }
    333 
    334 TEST_F(CastMessageBuilderTest, InOrderRps) {
    335   // Create a pattern - skip to rps, and don't look back.
    336   SetFrameIds(0, 0);
    337   SetPacketId(0);
    338   SetMaxPacketId(0);
    339   SetKeyFrame(true);
    340   InsertPacket();
    341   testing_clock_.Advance(
    342       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    343   EXPECT_TRUE(feedback_.triggered());
    344   EXPECT_EQ(0u, feedback_.last_frame_acked());
    345   SetFrameIds(1, 0);
    346   SetPacketId(0);
    347   SetMaxPacketId(1);
    348   SetKeyFrame(false);
    349   InsertPacket();
    350   testing_clock_.Advance(
    351       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    352   EXPECT_FALSE(feedback_.triggered());
    353   SetFrameIds(3, 0);
    354   SetPacketId(0);
    355   SetMaxPacketId(0);
    356   SetKeyFrame(false);
    357   InsertPacket();
    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.
    367   SetFrameIds(1, 0);
    368   SetPacketId(1);
    369   SetMaxPacketId(1);
    370   SetKeyFrame(false);
    371   InsertPacket();
    372   testing_clock_.Advance(
    373       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    374   EXPECT_FALSE(feedback_.triggered());
    375   EXPECT_EQ(3u, feedback_.last_frame_acked());
    376 }
    377 
    378 TEST_F(CastMessageBuilderTest, SlowDownAck) {
    379   SetDecoderSlowerThanMaxFrameRate(3);
    380   SetFrameIds(0, 0);
    381   SetPacketId(0);
    382   SetMaxPacketId(0);
    383   SetKeyFrame(true);
    384   InsertPacket();
    385 
    386   uint32 frame_id;
    387   testing_clock_.Advance(
    388       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    389   SetKeyFrame(false);
    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);
    394     InsertPacket();
    395     testing_clock_.Advance(
    396         base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    397   }
    398   // We should now have entered the slowdown ACK state.
    399   uint32 expected_frame_id = 1;
    400   for (; frame_id < 10; ++frame_id) {
    401     if (frame_id % 2) {
    402       ++expected_frame_id;
    403       EXPECT_TRUE(feedback_.triggered());
    404     } else {
    405       EXPECT_FALSE(feedback_.triggered());
    406     }
    407     EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
    408     SetFrameIds(frame_id, frame_id - 1);
    409     InsertPacket();
    410     testing_clock_.Advance(
    411         base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    412   }
    413   EXPECT_FALSE(feedback_.triggered());
    414   EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked());
    415 
    416   // Simulate frame_id being pulled for rendering.
    417   frame_id_map_.RemoveOldFrames(frame_id);
    418   // We should now leave the slowdown ACK state.
    419   ++frame_id;
    420   SetFrameIds(frame_id, frame_id - 1);
    421   InsertPacket();
    422   testing_clock_.Advance(
    423       base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs));
    424   EXPECT_TRUE(feedback_.triggered());
    425   EXPECT_EQ(frame_id, feedback_.last_frame_acked());
    426 }
    427 
    428 }  // namespace cast
    429 }  // namespace media
    430