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:
TestLogging()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
~TestLogging()33 virtual ~TestLogging() {}
34
35 LoggingImpl logging_;
36 base::SimpleTestTickClock testing_clock_;
37 };
38
TEST_F(TestLogging,BasicFrameLogging)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
TEST_F(TestLogging,FrameLoggingWithSize)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
TEST_F(TestLogging,FrameLoggingWithDelay)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
TEST_F(TestLogging,MultipleEventFrameLogging)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
TEST_F(TestLogging,PacketLogging)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
TEST_F(TestLogging,GenericLogging)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