Home | History | Annotate | Download | only in logging
      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 "base/memory/ref_counted.h"
      6 #include "base/memory/scoped_ptr.h"
      7 #include "base/rand_util.h"
      8 #include "base/test/simple_test_tick_clock.h"
      9 #include "base/time/tick_clock.h"
     10 #include "media/cast/cast_environment.h"
     11 #include "media/cast/logging/logging_defines.h"
     12 #include "media/cast/logging/stats_event_subscriber.h"
     13 #include "media/cast/test/fake_receiver_time_offset_estimator.h"
     14 #include "media/cast/test/fake_single_thread_task_runner.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace {
     18 const int kReceiverOffsetSecs = 100;
     19 }
     20 
     21 namespace media {
     22 namespace cast {
     23 
     24 class StatsEventSubscriberTest : public ::testing::Test {
     25  protected:
     26   StatsEventSubscriberTest()
     27       : sender_clock_(new base::SimpleTestTickClock()),
     28         task_runner_(new test::FakeSingleThreadTaskRunner(sender_clock_)),
     29         cast_environment_(new CastEnvironment(
     30             scoped_ptr<base::TickClock>(sender_clock_).Pass(),
     31             task_runner_,
     32             task_runner_,
     33             task_runner_)),
     34         fake_offset_estimator_(
     35             base::TimeDelta::FromSeconds(kReceiverOffsetSecs)) {
     36     receiver_clock_.Advance(base::TimeDelta::FromSeconds(kReceiverOffsetSecs));
     37     cast_environment_->Logging()->AddRawEventSubscriber(
     38         &fake_offset_estimator_);
     39   }
     40 
     41   virtual ~StatsEventSubscriberTest() {
     42     if (subscriber_.get())
     43       cast_environment_->Logging()->RemoveRawEventSubscriber(subscriber_.get());
     44     cast_environment_->Logging()->RemoveRawEventSubscriber(
     45         &fake_offset_estimator_);
     46   }
     47 
     48   void AdvanceClocks(base::TimeDelta delta) {
     49     sender_clock_->Advance(delta);
     50     receiver_clock_.Advance(delta);
     51   }
     52 
     53   void Init(EventMediaType event_media_type) {
     54     DCHECK(!subscriber_.get());
     55     subscriber_.reset(new StatsEventSubscriber(
     56         event_media_type, cast_environment_->Clock(), &fake_offset_estimator_));
     57     cast_environment_->Logging()->AddRawEventSubscriber(subscriber_.get());
     58   }
     59 
     60   base::SimpleTestTickClock* sender_clock_;  // Owned by CastEnvironment.
     61   base::SimpleTestTickClock receiver_clock_;
     62   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
     63   scoped_refptr<CastEnvironment> cast_environment_;
     64   test::FakeReceiverTimeOffsetEstimator fake_offset_estimator_;
     65   scoped_ptr<StatsEventSubscriber> subscriber_;
     66 };
     67 
     68 TEST_F(StatsEventSubscriberTest, Capture) {
     69   Init(VIDEO_EVENT);
     70 
     71   uint32 rtp_timestamp = 0;
     72   uint32 frame_id = 0;
     73   int num_frames = 10;
     74   base::TimeTicks start_time = sender_clock_->NowTicks();
     75   for (int i = 0; i < num_frames; i++) {
     76     cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
     77                                                    FRAME_CAPTURE_BEGIN,
     78                                                    VIDEO_EVENT,
     79                                                    rtp_timestamp,
     80                                                    frame_id);
     81 
     82     AdvanceClocks(base::TimeDelta::FromMicroseconds(34567));
     83     rtp_timestamp += 90;
     84     frame_id++;
     85   }
     86 
     87   base::TimeTicks end_time = sender_clock_->NowTicks();
     88 
     89   StatsEventSubscriber::StatsMap stats_map;
     90   subscriber_->GetStatsInternal(&stats_map);
     91 
     92   StatsEventSubscriber::StatsMap::iterator it =
     93       stats_map.find(StatsEventSubscriber::CAPTURE_FPS);
     94   ASSERT_NE(it, stats_map.end());
     95 
     96   base::TimeDelta duration = end_time - start_time;
     97   EXPECT_DOUBLE_EQ(
     98       it->second,
     99       static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000);
    100 }
    101 
    102 TEST_F(StatsEventSubscriberTest, Encode) {
    103   Init(VIDEO_EVENT);
    104 
    105   uint32 rtp_timestamp = 0;
    106   uint32 frame_id = 0;
    107   int num_frames = 10;
    108   base::TimeTicks start_time = sender_clock_->NowTicks();
    109   int total_size = 0;
    110   for (int i = 0; i < num_frames; i++) {
    111     int size = 1000 + base::RandInt(-100, 100);
    112     total_size += size;
    113     cast_environment_->Logging()->InsertEncodedFrameEvent(
    114         sender_clock_->NowTicks(),
    115         FRAME_ENCODED, VIDEO_EVENT,
    116         rtp_timestamp,
    117         frame_id,
    118         size,
    119         true,
    120         5678);
    121 
    122     AdvanceClocks(base::TimeDelta::FromMicroseconds(35678));
    123     rtp_timestamp += 90;
    124     frame_id++;
    125   }
    126 
    127   base::TimeTicks end_time = sender_clock_->NowTicks();
    128 
    129   StatsEventSubscriber::StatsMap stats_map;
    130   subscriber_->GetStatsInternal(&stats_map);
    131 
    132   StatsEventSubscriber::StatsMap::iterator it =
    133       stats_map.find(StatsEventSubscriber::ENCODE_FPS);
    134   ASSERT_NE(it, stats_map.end());
    135 
    136   base::TimeDelta duration = end_time - start_time;
    137   EXPECT_DOUBLE_EQ(
    138       it->second,
    139       static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000);
    140 
    141   it = stats_map.find(StatsEventSubscriber::ENCODE_KBPS);
    142   ASSERT_NE(it, stats_map.end());
    143 
    144   EXPECT_DOUBLE_EQ(it->second,
    145               static_cast<double>(total_size) / duration.InMillisecondsF() * 8);
    146 }
    147 
    148 TEST_F(StatsEventSubscriberTest, Decode) {
    149   Init(VIDEO_EVENT);
    150 
    151   uint32 rtp_timestamp = 0;
    152   uint32 frame_id = 0;
    153   int num_frames = 10;
    154   base::TimeTicks start_time = sender_clock_->NowTicks();
    155   for (int i = 0; i < num_frames; i++) {
    156     cast_environment_->Logging()->InsertFrameEvent(receiver_clock_.NowTicks(),
    157                                                    FRAME_DECODED, VIDEO_EVENT,
    158                                                    rtp_timestamp,
    159                                                    frame_id);
    160 
    161     AdvanceClocks(base::TimeDelta::FromMicroseconds(36789));
    162     rtp_timestamp += 90;
    163     frame_id++;
    164   }
    165 
    166   base::TimeTicks end_time = sender_clock_->NowTicks();
    167 
    168   StatsEventSubscriber::StatsMap stats_map;
    169   subscriber_->GetStatsInternal(&stats_map);
    170 
    171   StatsEventSubscriber::StatsMap::iterator it =
    172       stats_map.find(StatsEventSubscriber::DECODE_FPS);
    173   ASSERT_NE(it, stats_map.end());
    174 
    175   base::TimeDelta duration = end_time - start_time;
    176   EXPECT_DOUBLE_EQ(
    177       it->second,
    178       static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000);
    179 }
    180 
    181 TEST_F(StatsEventSubscriberTest, PlayoutDelay) {
    182   Init(VIDEO_EVENT);
    183 
    184   uint32 rtp_timestamp = 0;
    185   uint32 frame_id = 0;
    186   int num_frames = 10;
    187   int total_delay_ms = 0;
    188   for (int i = 0; i < num_frames; i++) {
    189     int delay_ms = base::RandInt(-50, 50);
    190     base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms);
    191     total_delay_ms += delay_ms;
    192     cast_environment_->Logging()->InsertFrameEventWithDelay(
    193         receiver_clock_.NowTicks(),
    194         FRAME_PLAYOUT,
    195         VIDEO_EVENT,
    196         rtp_timestamp,
    197         frame_id,
    198         delay);
    199 
    200     AdvanceClocks(base::TimeDelta::FromMicroseconds(37890));
    201     rtp_timestamp += 90;
    202     frame_id++;
    203   }
    204 
    205   StatsEventSubscriber::StatsMap stats_map;
    206   subscriber_->GetStatsInternal(&stats_map);
    207 
    208   StatsEventSubscriber::StatsMap::iterator it =
    209       stats_map.find(StatsEventSubscriber::AVG_PLAYOUT_DELAY_MS);
    210   ASSERT_NE(it, stats_map.end());
    211 
    212   EXPECT_DOUBLE_EQ(
    213       it->second, static_cast<double>(total_delay_ms) / num_frames);
    214 }
    215 
    216 TEST_F(StatsEventSubscriberTest, E2ELatency) {
    217   Init(VIDEO_EVENT);
    218 
    219   uint32 rtp_timestamp = 0;
    220   uint32 frame_id = 0;
    221   int num_frames = 10;
    222   base::TimeDelta total_latency;
    223   for (int i = 0; i < num_frames; i++) {
    224     cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
    225                                                    FRAME_CAPTURE_BEGIN,
    226                                                    VIDEO_EVENT,
    227                                                    rtp_timestamp,
    228                                                    frame_id);
    229 
    230     int latency_micros = 100000 + base::RandInt(-5000, 50000);
    231     base::TimeDelta latency = base::TimeDelta::FromMicroseconds(latency_micros);
    232     AdvanceClocks(latency);
    233 
    234     int delay_micros = base::RandInt(-50000, 50000);
    235     base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_micros);
    236     total_latency += latency + delay;
    237 
    238     cast_environment_->Logging()->InsertFrameEventWithDelay(
    239         receiver_clock_.NowTicks(),
    240         FRAME_PLAYOUT,
    241         VIDEO_EVENT,
    242         rtp_timestamp,
    243         frame_id,
    244         delay);
    245 
    246     rtp_timestamp += 90;
    247     frame_id++;
    248   }
    249 
    250   StatsEventSubscriber::StatsMap stats_map;
    251   subscriber_->GetStatsInternal(&stats_map);
    252 
    253   StatsEventSubscriber::StatsMap::iterator it =
    254       stats_map.find(StatsEventSubscriber::AVG_E2E_LATENCY_MS);
    255   ASSERT_NE(it, stats_map.end());
    256 
    257   EXPECT_DOUBLE_EQ(
    258       it->second, total_latency.InMillisecondsF() / num_frames);
    259 }
    260 
    261 TEST_F(StatsEventSubscriberTest, Packets) {
    262   Init(VIDEO_EVENT);
    263 
    264   uint32 rtp_timestamp = 0;
    265   int num_packets = 10;
    266   int num_latency_recorded_packets = 0;
    267   base::TimeTicks start_time = sender_clock_->NowTicks();
    268   int total_size = 0;
    269   int retransmit_total_size = 0;
    270   base::TimeDelta total_latency;
    271   int num_packets_sent = 0;
    272   int num_packets_retransmitted = 0;
    273   // Every 2nd packet will be retransmitted once.
    274   // Every 4th packet will be retransmitted twice.
    275   // Every 8th packet will be retransmitted 3 times.
    276   for (int i = 0; i < num_packets; i++) {
    277     int size = 1000 + base::RandInt(-100, 100);
    278     total_size += size;
    279 
    280     cast_environment_->Logging()->InsertPacketEvent(sender_clock_->NowTicks(),
    281                                                     PACKET_SENT_TO_NETWORK,
    282                                                     VIDEO_EVENT,
    283                                                     rtp_timestamp,
    284                                                     0,
    285                                                     i,
    286                                                     num_packets - 1,
    287                                                     size);
    288     num_packets_sent++;
    289 
    290     int latency_micros = 20000 + base::RandInt(-10000, 10000);
    291     base::TimeDelta latency = base::TimeDelta::FromMicroseconds(latency_micros);
    292     // Latency is only recorded for packets that aren't retransmitted.
    293     if (i % 2 != 0) {
    294       total_latency += latency;
    295       num_latency_recorded_packets++;
    296     }
    297 
    298     AdvanceClocks(latency);
    299 
    300     base::TimeTicks received_time = receiver_clock_.NowTicks();
    301 
    302     // Retransmission 1.
    303     AdvanceClocks(base::TimeDelta::FromMicroseconds(12345));
    304     if (i % 2 == 0) {
    305       cast_environment_->Logging()->InsertPacketEvent(
    306           receiver_clock_.NowTicks(),
    307           PACKET_RETRANSMITTED,
    308           VIDEO_EVENT,
    309           rtp_timestamp,
    310           0,
    311           i,
    312           num_packets - 1,
    313           size);
    314       retransmit_total_size += size;
    315       num_packets_sent++;
    316       num_packets_retransmitted++;
    317     }
    318 
    319     // Retransmission 2.
    320     AdvanceClocks(base::TimeDelta::FromMicroseconds(13456));
    321     if (i % 4 == 0) {
    322       cast_environment_->Logging()->InsertPacketEvent(
    323           receiver_clock_.NowTicks(),
    324           PACKET_RETRANSMITTED,
    325           VIDEO_EVENT,
    326           rtp_timestamp,
    327           0,
    328           i,
    329           num_packets - 1,
    330           size);
    331       retransmit_total_size += size;
    332       num_packets_sent++;
    333       num_packets_retransmitted++;
    334     }
    335 
    336     // Retransmission 3.
    337     AdvanceClocks(base::TimeDelta::FromMicroseconds(14567));
    338     if (i % 8 == 0) {
    339       cast_environment_->Logging()->InsertPacketEvent(
    340           receiver_clock_.NowTicks(),
    341           PACKET_RETRANSMITTED,
    342           VIDEO_EVENT,
    343           rtp_timestamp,
    344           0,
    345           i,
    346           num_packets - 1,
    347           size);
    348       retransmit_total_size += size;
    349       num_packets_sent++;
    350       num_packets_retransmitted++;
    351     }
    352 
    353     cast_environment_->Logging()->InsertPacketEvent(received_time,
    354                                                     PACKET_RECEIVED,
    355                                                     VIDEO_EVENT,
    356                                                     rtp_timestamp,
    357                                                     0,
    358                                                     i,
    359                                                     num_packets - 1,
    360                                                     size);
    361   }
    362 
    363   base::TimeTicks end_time = sender_clock_->NowTicks();
    364   base::TimeDelta duration = end_time - start_time;
    365 
    366   StatsEventSubscriber::StatsMap stats_map;
    367   subscriber_->GetStatsInternal(&stats_map);
    368 
    369   // Measure AVG_NETWORK_LATENCY_MS, TRANSMISSION_KBPS, RETRANSMISSION_KBPS,
    370   // and PACKET_LOSS_FRACTION.
    371   StatsEventSubscriber::StatsMap::iterator it =
    372       stats_map.find(StatsEventSubscriber::AVG_NETWORK_LATENCY_MS);
    373   ASSERT_NE(it, stats_map.end());
    374 
    375   EXPECT_DOUBLE_EQ(
    376       it->second,
    377       total_latency.InMillisecondsF() / num_latency_recorded_packets);
    378 
    379   it = stats_map.find(StatsEventSubscriber::TRANSMISSION_KBPS);
    380   ASSERT_NE(it, stats_map.end());
    381 
    382   EXPECT_DOUBLE_EQ(it->second,
    383               static_cast<double>(total_size) / duration.InMillisecondsF() * 8);
    384 
    385   it = stats_map.find(StatsEventSubscriber::RETRANSMISSION_KBPS);
    386   ASSERT_NE(it, stats_map.end());
    387 
    388   EXPECT_DOUBLE_EQ(it->second,
    389               static_cast<double>(retransmit_total_size) /
    390                   duration.InMillisecondsF() * 8);
    391 
    392   it = stats_map.find(StatsEventSubscriber::PACKET_LOSS_FRACTION);
    393   ASSERT_NE(it, stats_map.end());
    394 
    395   EXPECT_DOUBLE_EQ(
    396       it->second,
    397       static_cast<double>(num_packets_retransmitted) / num_packets_sent);
    398 }
    399 
    400 }  // namespace cast
    401 }  // namespace media
    402