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 <gtest/gtest.h> 6 7 #include "base/rand_util.h" 8 #include "base/test/simple_test_tick_clock.h" 9 #include "base/time/tick_clock.h" 10 #include "base/time/time.h" 11 #include "media/cast/logging/logging_impl.h" 12 13 14 namespace media { 15 namespace cast { 16 17 // Insert frame duration- one second. 18 const int64 kIntervalTime1S = 1; 19 // Test frame rate goal - 30fps. 20 const int kFrameIntervalMs = 33; 21 22 static const int64 kStartMillisecond = GG_INT64_C(12345678900000); 23 24 class TestLogging : public ::testing::Test { 25 protected: 26 TestLogging() 27 // Enable logging, disable tracing and uma. 28 : logging_(&testing_clock_, true, false, false) { 29 testing_clock_.Advance( 30 base::TimeDelta::FromMilliseconds(kStartMillisecond)); 31 } 32 33 virtual ~TestLogging() {} 34 35 LoggingImpl logging_; 36 base::SimpleTestTickClock testing_clock_; 37 }; 38 39 TEST_F(TestLogging, BasicFrameLogging) { 40 base::TimeTicks start_time = testing_clock_.NowTicks(); 41 base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; 42 uint32 rtp_timestamp = 0; 43 uint32 frame_id = 0; 44 do { 45 logging_.InsertFrameEvent(kAudioFrameCaptured, rtp_timestamp, frame_id); 46 testing_clock_.Advance( 47 base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); 48 rtp_timestamp += kFrameIntervalMs * 90; 49 ++frame_id; 50 time_interval = testing_clock_.NowTicks() - start_time; 51 } while (time_interval.InSeconds() < kIntervalTime1S); 52 // Get logging data. 53 FrameRawMap frame_map = logging_.GetFrameRawData(); 54 // Size of map should be equal to the number of frames logged. 55 EXPECT_EQ(frame_id, frame_map.size()); 56 // Verify stats. 57 const FrameStatsMap* frame_stats = logging_.GetFrameStatsData(); 58 // Size of stats equals the number of events. 59 EXPECT_EQ(1u, frame_stats->size()); 60 FrameStatsMap::const_iterator it = frame_stats->find(kAudioFrameCaptured); 61 EXPECT_TRUE(it != frame_stats->end()); 62 EXPECT_NEAR(30.3, it->second->framerate_fps, 0.1); 63 EXPECT_EQ(0, it->second->bitrate_kbps); 64 EXPECT_EQ(0, it->second->max_delay_ms); 65 EXPECT_EQ(0, it->second->min_delay_ms); 66 EXPECT_EQ(0, it->second->avg_delay_ms); 67 } 68 69 TEST_F(TestLogging, FrameLoggingWithSize) { 70 // Average packet size. 71 const int kBaseFrameSizeBytes = 25000; 72 const int kRandomSizeInterval = 100; 73 base::TimeTicks start_time = testing_clock_.NowTicks(); 74 base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; 75 uint32 rtp_timestamp = 0; 76 uint32 frame_id = 0; 77 do { 78 int size = kBaseFrameSizeBytes + 79 base::RandInt(-kRandomSizeInterval, kRandomSizeInterval); 80 logging_.InsertFrameEventWithSize( 81 kAudioFrameCaptured, rtp_timestamp, frame_id, size); 82 testing_clock_.Advance( 83 base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); 84 rtp_timestamp += kFrameIntervalMs * 90; 85 ++frame_id; 86 time_interval = testing_clock_.NowTicks() - start_time; 87 } while (time_interval.InSeconds() < kIntervalTime1S); 88 // Get logging data. 89 FrameRawMap frame_map = logging_.GetFrameRawData(); 90 // Size of map should be equal to the number of frames logged. 91 EXPECT_EQ(frame_id, frame_map.size()); 92 // Verify stats. 93 const FrameStatsMap* frame_stats = logging_.GetFrameStatsData(); 94 // Size of stats equals the number of events. 95 EXPECT_EQ(1u, frame_stats->size()); 96 FrameStatsMap::const_iterator it = frame_stats->find(kAudioFrameCaptured); 97 EXPECT_TRUE(it != frame_stats->end()); 98 EXPECT_NEAR(30.3, it->second->framerate_fps, 0.1); 99 EXPECT_NEAR(8 * kBaseFrameSizeBytes / (kFrameIntervalMs * 1000), 100 it->second->bitrate_kbps, kRandomSizeInterval); 101 EXPECT_EQ(0, it->second->max_delay_ms); 102 EXPECT_EQ(0, it->second->min_delay_ms); 103 EXPECT_EQ(0, it->second->avg_delay_ms); 104 } 105 106 TEST_F(TestLogging, FrameLoggingWithDelay) { 107 // Average packet size. 108 const int kPlayoutDelayMs = 50; 109 const int kRandomSizeInterval = 20; 110 base::TimeTicks start_time = testing_clock_.NowTicks(); 111 base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; 112 uint32 rtp_timestamp = 0; 113 uint32 frame_id = 0; 114 do { 115 int delay = kPlayoutDelayMs + 116 base::RandInt(-kRandomSizeInterval, kRandomSizeInterval); 117 logging_.InsertFrameEventWithDelay( 118 kAudioFrameCaptured, rtp_timestamp, frame_id, 119 base::TimeDelta::FromMilliseconds(delay)); 120 testing_clock_.Advance( 121 base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); 122 rtp_timestamp += kFrameIntervalMs * 90; 123 ++frame_id; 124 time_interval = testing_clock_.NowTicks() - start_time; 125 } while (time_interval.InSeconds() < kIntervalTime1S); 126 // Get logging data. 127 FrameRawMap frame_map = logging_.GetFrameRawData(); 128 // Size of map should be equal to the number of frames logged. 129 EXPECT_EQ(frame_id, frame_map.size()); 130 // Verify stats. 131 const FrameStatsMap* frame_stats = logging_.GetFrameStatsData(); 132 // Size of stats equals the number of events. 133 EXPECT_EQ(1u, frame_stats->size()); 134 FrameStatsMap::const_iterator it = frame_stats->find(kAudioFrameCaptured); 135 EXPECT_TRUE(it != frame_stats->end()); 136 EXPECT_NEAR(30.3, it->second->framerate_fps, 0.1); 137 EXPECT_EQ(0, it->second->bitrate_kbps); 138 EXPECT_GE(kPlayoutDelayMs + kRandomSizeInterval, it->second->max_delay_ms); 139 EXPECT_LE(kPlayoutDelayMs - kRandomSizeInterval, it->second->min_delay_ms); 140 EXPECT_NEAR(kPlayoutDelayMs, it->second->avg_delay_ms, 141 0.2 * kRandomSizeInterval); 142 } 143 144 TEST_F(TestLogging, MultipleEventFrameLogging) { 145 base::TimeTicks start_time = testing_clock_.NowTicks(); 146 base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; 147 uint32 rtp_timestamp = 0; 148 uint32 frame_id = 0; 149 do { 150 logging_.InsertFrameEvent(kAudioFrameCaptured, rtp_timestamp, frame_id); 151 if (frame_id % 2) { 152 logging_.InsertFrameEventWithSize( 153 kAudioFrameEncoded, rtp_timestamp, frame_id, 1500); 154 } else if (frame_id % 3) { 155 logging_.InsertFrameEvent(kVideoFrameDecoded, rtp_timestamp, frame_id); 156 } else { 157 logging_.InsertFrameEventWithDelay( 158 kVideoRenderDelay, rtp_timestamp, frame_id, 159 base::TimeDelta::FromMilliseconds(20)); 160 } 161 testing_clock_.Advance( 162 base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); 163 rtp_timestamp += kFrameIntervalMs * 90; 164 ++frame_id; 165 time_interval = testing_clock_.NowTicks() - start_time; 166 } while (time_interval.InSeconds() < kIntervalTime1S); 167 // Get logging data. 168 FrameRawMap frame_map = logging_.GetFrameRawData(); 169 // Size of map should be equal to the number of frames logged. 170 EXPECT_EQ(frame_id, frame_map.size()); 171 // Multiple events captured per frame. 172 } 173 174 TEST_F(TestLogging, PacketLogging) { 175 const int kNumPacketsPerFrame = 10; 176 const int kBaseSize = 2500; 177 const int kSizeInterval = 100; 178 base::TimeTicks start_time = testing_clock_.NowTicks(); 179 base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; 180 uint32 rtp_timestamp = 0; 181 uint32 frame_id = 0; 182 do { 183 for (int i = 0; i < kNumPacketsPerFrame; ++i) { 184 int size = kBaseSize + base::RandInt(-kSizeInterval, kSizeInterval); 185 logging_.InsertPacketEvent(kPacketSentToPacer, rtp_timestamp, frame_id, 186 i, kNumPacketsPerFrame, size); 187 } 188 testing_clock_.Advance( 189 base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); 190 rtp_timestamp += kFrameIntervalMs * 90; 191 ++frame_id; 192 time_interval = testing_clock_.NowTicks() - start_time; 193 } while (time_interval.InSeconds() < kIntervalTime1S); 194 // Get logging data. 195 PacketRawMap raw_map = logging_.GetPacketRawData(); 196 // Size of map should be equal to the number of frames logged. 197 EXPECT_EQ(frame_id, raw_map.size()); 198 // Verify stats. 199 const PacketStatsMap* stats_map = logging_.GetPacketStatsData(); 200 // Size of stats equals the number of events. 201 EXPECT_EQ(1u, stats_map->size()); 202 PacketStatsMap::const_iterator it = stats_map->find(kPacketSentToPacer); 203 EXPECT_TRUE(it != stats_map->end()); 204 // We only store the bitrate as a packet statistic. 205 EXPECT_NEAR(8 * kNumPacketsPerFrame * kBaseSize / (kFrameIntervalMs * 1000), 206 it->second, kSizeInterval); 207 } 208 209 TEST_F(TestLogging, GenericLogging) { 210 // Insert multiple generic types. 211 const int kNumRuns = 1000; 212 const int kBaseValue = 20; 213 for (int i = 0; i < kNumRuns; ++i) { 214 int value = kBaseValue + base::RandInt(-5, 5); 215 logging_.InsertGenericEvent(kRtt, value); 216 if (i % 2) { 217 logging_.InsertGenericEvent(kPacketLoss, value); 218 } 219 if (!(i % 4)) { 220 logging_.InsertGenericEvent(kJitter, value); 221 } 222 } 223 GenericRawMap raw_map = logging_.GetGenericRawData(); 224 const GenericStatsMap* stats_map = logging_.GetGenericStatsData(); 225 // Size of generic map = number of different events. 226 EXPECT_EQ(3u, raw_map.size()); 227 EXPECT_EQ(3u, stats_map->size()); 228 // Raw events - size of internal map = number of calls. 229 GenericRawMap::iterator rit = raw_map.find(kRtt); 230 EXPECT_EQ(kNumRuns, rit->second.value.size()); 231 EXPECT_EQ(kNumRuns, rit->second.timestamp.size()); 232 rit = raw_map.find(kPacketLoss); 233 EXPECT_EQ(kNumRuns / 2, rit->second.value.size()); 234 EXPECT_EQ(kNumRuns / 2, rit->second.timestamp.size()); 235 rit = raw_map.find(kJitter); 236 EXPECT_EQ(kNumRuns / 4, rit->second.value.size()); 237 EXPECT_EQ(kNumRuns / 4, rit->second.timestamp.size()); 238 // Stats - one value per event. 239 GenericStatsMap::const_iterator sit = stats_map->find(kRtt); 240 EXPECT_NEAR(kBaseValue, sit->second, 2.5); 241 sit = stats_map->find(kPacketLoss); 242 EXPECT_NEAR(kBaseValue, sit->second, 2.5); 243 sit = stats_map->find(kJitter); 244 EXPECT_NEAR(kBaseValue, sit->second, 2.5); 245 } 246 247 } // namespace cast 248 } // namespace media 249