blob: ff5abad99dd101f8f9ff8187c0000d9809a1b39c [file] [log] [blame]
Bjorn Terelius36411852015-07-30 12:45:18 +02001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifdef ENABLE_RTC_EVENT_LOG
12
13#include <stdio.h>
14#include <string>
15#include <vector>
16
17#include "testing/gtest/include/gtest/gtest.h"
terelius2f9fd5d2015-09-04 03:39:42 -070018#include "webrtc/base/buffer.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020019#include "webrtc/base/checks.h"
20#include "webrtc/base/scoped_ptr.h"
terelius1adce142015-10-16 08:51:08 -070021#include "webrtc/base/thread.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/rtc_event_log.h"
terelius2f9fd5d2015-09-04 03:39:42 -070024#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010025#include "webrtc/system_wrappers/include/clock.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020026#include "webrtc/test/test_suite.h"
27#include "webrtc/test/testsupport/fileutils.h"
28#include "webrtc/test/testsupport/gtest_disable.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020029
30// Files generated at build-time by the protobuf compiler.
31#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
Peter Boström5c389d32015-09-25 13:58:30 +020032#include "external/webrtc/webrtc/call/rtc_event_log.pb.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020033#else
Peter Boström5c389d32015-09-25 13:58:30 +020034#include "webrtc/call/rtc_event_log.pb.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020035#endif
36
37namespace webrtc {
38
terelius2f9fd5d2015-09-04 03:39:42 -070039namespace {
40
41const RTPExtensionType kExtensionTypes[] = {
42 RTPExtensionType::kRtpExtensionTransmissionTimeOffset,
43 RTPExtensionType::kRtpExtensionAudioLevel,
44 RTPExtensionType::kRtpExtensionAbsoluteSendTime,
45 RTPExtensionType::kRtpExtensionVideoRotation,
46 RTPExtensionType::kRtpExtensionTransportSequenceNumber};
47const char* kExtensionNames[] = {RtpExtension::kTOffset,
48 RtpExtension::kAudioLevel,
49 RtpExtension::kAbsSendTime,
50 RtpExtension::kVideoRotation,
51 RtpExtension::kTransportSequenceNumber};
52const size_t kNumExtensions = 5;
53
Peter Boström5c389d32015-09-25 13:58:30 +020054} // namespace
terelius2f9fd5d2015-09-04 03:39:42 -070055
Bjorn Terelius36411852015-07-30 12:45:18 +020056// TODO(terelius): Place this definition with other parsing functions?
57MediaType GetRuntimeMediaType(rtclog::MediaType media_type) {
58 switch (media_type) {
59 case rtclog::MediaType::ANY:
60 return MediaType::ANY;
61 case rtclog::MediaType::AUDIO:
62 return MediaType::AUDIO;
63 case rtclog::MediaType::VIDEO:
64 return MediaType::VIDEO;
65 case rtclog::MediaType::DATA:
66 return MediaType::DATA;
67 }
68 RTC_NOTREACHED();
69 return MediaType::ANY;
70}
71
72// Checks that the event has a timestamp, a type and exactly the data field
73// corresponding to the type.
74::testing::AssertionResult IsValidBasicEvent(const rtclog::Event& event) {
75 if (!event.has_timestamp_us())
76 return ::testing::AssertionFailure() << "Event has no timestamp";
77 if (!event.has_type())
78 return ::testing::AssertionFailure() << "Event has no event type";
79 rtclog::Event_EventType type = event.type();
80 if ((type == rtclog::Event::RTP_EVENT) != event.has_rtp_packet())
81 return ::testing::AssertionFailure()
82 << "Event of type " << type << " has "
83 << (event.has_rtp_packet() ? "" : "no ") << "RTP packet";
84 if ((type == rtclog::Event::RTCP_EVENT) != event.has_rtcp_packet())
85 return ::testing::AssertionFailure()
86 << "Event of type " << type << " has "
87 << (event.has_rtcp_packet() ? "" : "no ") << "RTCP packet";
Ivo Creusen301aaed2015-10-08 18:07:41 +020088 if ((type == rtclog::Event::AUDIO_PLAYOUT_EVENT) !=
89 event.has_audio_playout_event())
Bjorn Terelius36411852015-07-30 12:45:18 +020090 return ::testing::AssertionFailure()
91 << "Event of type " << type << " has "
Ivo Creusen301aaed2015-10-08 18:07:41 +020092 << (event.has_audio_playout_event() ? "" : "no ")
93 << "audio_playout event";
Bjorn Terelius36411852015-07-30 12:45:18 +020094 if ((type == rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT) !=
95 event.has_video_receiver_config())
96 return ::testing::AssertionFailure()
97 << "Event of type " << type << " has "
98 << (event.has_video_receiver_config() ? "" : "no ")
99 << "receiver config";
100 if ((type == rtclog::Event::VIDEO_SENDER_CONFIG_EVENT) !=
101 event.has_video_sender_config())
102 return ::testing::AssertionFailure()
103 << "Event of type " << type << " has "
104 << (event.has_video_sender_config() ? "" : "no ") << "sender config";
105 if ((type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT) !=
106 event.has_audio_receiver_config()) {
107 return ::testing::AssertionFailure()
108 << "Event of type " << type << " has "
109 << (event.has_audio_receiver_config() ? "" : "no ")
110 << "audio receiver config";
111 }
112 if ((type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT) !=
113 event.has_audio_sender_config()) {
114 return ::testing::AssertionFailure()
115 << "Event of type " << type << " has "
116 << (event.has_audio_sender_config() ? "" : "no ")
117 << "audio sender config";
118 }
119 return ::testing::AssertionSuccess();
120}
121
122void VerifyReceiveStreamConfig(const rtclog::Event& event,
123 const VideoReceiveStream::Config& config) {
124 ASSERT_TRUE(IsValidBasicEvent(event));
125 ASSERT_EQ(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT, event.type());
126 const rtclog::VideoReceiveConfig& receiver_config =
127 event.video_receiver_config();
128 // Check SSRCs.
129 ASSERT_TRUE(receiver_config.has_remote_ssrc());
130 EXPECT_EQ(config.rtp.remote_ssrc, receiver_config.remote_ssrc());
131 ASSERT_TRUE(receiver_config.has_local_ssrc());
132 EXPECT_EQ(config.rtp.local_ssrc, receiver_config.local_ssrc());
133 // Check RTCP settings.
134 ASSERT_TRUE(receiver_config.has_rtcp_mode());
pbosda903ea2015-10-02 02:36:56 -0700135 if (config.rtp.rtcp_mode == RtcpMode::kCompound)
Bjorn Terelius36411852015-07-30 12:45:18 +0200136 EXPECT_EQ(rtclog::VideoReceiveConfig::RTCP_COMPOUND,
137 receiver_config.rtcp_mode());
138 else
139 EXPECT_EQ(rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE,
140 receiver_config.rtcp_mode());
141 ASSERT_TRUE(receiver_config.has_receiver_reference_time_report());
142 EXPECT_EQ(config.rtp.rtcp_xr.receiver_reference_time_report,
143 receiver_config.receiver_reference_time_report());
144 ASSERT_TRUE(receiver_config.has_remb());
145 EXPECT_EQ(config.rtp.remb, receiver_config.remb());
146 // Check RTX map.
147 ASSERT_EQ(static_cast<int>(config.rtp.rtx.size()),
148 receiver_config.rtx_map_size());
149 for (const rtclog::RtxMap& rtx_map : receiver_config.rtx_map()) {
150 ASSERT_TRUE(rtx_map.has_payload_type());
151 ASSERT_TRUE(rtx_map.has_config());
152 EXPECT_EQ(1u, config.rtp.rtx.count(rtx_map.payload_type()));
153 const rtclog::RtxConfig& rtx_config = rtx_map.config();
154 const VideoReceiveStream::Config::Rtp::Rtx& rtx =
155 config.rtp.rtx.at(rtx_map.payload_type());
156 ASSERT_TRUE(rtx_config.has_rtx_ssrc());
157 ASSERT_TRUE(rtx_config.has_rtx_payload_type());
158 EXPECT_EQ(rtx.ssrc, rtx_config.rtx_ssrc());
159 EXPECT_EQ(rtx.payload_type, rtx_config.rtx_payload_type());
160 }
161 // Check header extensions.
162 ASSERT_EQ(static_cast<int>(config.rtp.extensions.size()),
163 receiver_config.header_extensions_size());
164 for (int i = 0; i < receiver_config.header_extensions_size(); i++) {
165 ASSERT_TRUE(receiver_config.header_extensions(i).has_name());
166 ASSERT_TRUE(receiver_config.header_extensions(i).has_id());
167 const std::string& name = receiver_config.header_extensions(i).name();
168 int id = receiver_config.header_extensions(i).id();
169 EXPECT_EQ(config.rtp.extensions[i].id, id);
170 EXPECT_EQ(config.rtp.extensions[i].name, name);
171 }
172 // Check decoders.
173 ASSERT_EQ(static_cast<int>(config.decoders.size()),
174 receiver_config.decoders_size());
175 for (int i = 0; i < receiver_config.decoders_size(); i++) {
176 ASSERT_TRUE(receiver_config.decoders(i).has_name());
177 ASSERT_TRUE(receiver_config.decoders(i).has_payload_type());
178 const std::string& decoder_name = receiver_config.decoders(i).name();
179 int decoder_type = receiver_config.decoders(i).payload_type();
180 EXPECT_EQ(config.decoders[i].payload_name, decoder_name);
181 EXPECT_EQ(config.decoders[i].payload_type, decoder_type);
182 }
183}
184
185void VerifySendStreamConfig(const rtclog::Event& event,
186 const VideoSendStream::Config& config) {
187 ASSERT_TRUE(IsValidBasicEvent(event));
188 ASSERT_EQ(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT, event.type());
189 const rtclog::VideoSendConfig& sender_config = event.video_sender_config();
190 // Check SSRCs.
191 ASSERT_EQ(static_cast<int>(config.rtp.ssrcs.size()),
192 sender_config.ssrcs_size());
193 for (int i = 0; i < sender_config.ssrcs_size(); i++) {
194 EXPECT_EQ(config.rtp.ssrcs[i], sender_config.ssrcs(i));
195 }
196 // Check header extensions.
197 ASSERT_EQ(static_cast<int>(config.rtp.extensions.size()),
198 sender_config.header_extensions_size());
199 for (int i = 0; i < sender_config.header_extensions_size(); i++) {
200 ASSERT_TRUE(sender_config.header_extensions(i).has_name());
201 ASSERT_TRUE(sender_config.header_extensions(i).has_id());
202 const std::string& name = sender_config.header_extensions(i).name();
203 int id = sender_config.header_extensions(i).id();
204 EXPECT_EQ(config.rtp.extensions[i].id, id);
205 EXPECT_EQ(config.rtp.extensions[i].name, name);
206 }
207 // Check RTX settings.
208 ASSERT_EQ(static_cast<int>(config.rtp.rtx.ssrcs.size()),
209 sender_config.rtx_ssrcs_size());
210 for (int i = 0; i < sender_config.rtx_ssrcs_size(); i++) {
211 EXPECT_EQ(config.rtp.rtx.ssrcs[i], sender_config.rtx_ssrcs(i));
212 }
213 if (sender_config.rtx_ssrcs_size() > 0) {
214 ASSERT_TRUE(sender_config.has_rtx_payload_type());
215 EXPECT_EQ(config.rtp.rtx.payload_type, sender_config.rtx_payload_type());
216 }
217 // Check CNAME.
218 ASSERT_TRUE(sender_config.has_c_name());
219 EXPECT_EQ(config.rtp.c_name, sender_config.c_name());
220 // Check encoder.
221 ASSERT_TRUE(sender_config.has_encoder());
222 ASSERT_TRUE(sender_config.encoder().has_name());
223 ASSERT_TRUE(sender_config.encoder().has_payload_type());
224 EXPECT_EQ(config.encoder_settings.payload_name,
225 sender_config.encoder().name());
226 EXPECT_EQ(config.encoder_settings.payload_type,
227 sender_config.encoder().payload_type());
228}
229
230void VerifyRtpEvent(const rtclog::Event& event,
231 bool incoming,
232 MediaType media_type,
233 uint8_t* header,
234 size_t header_size,
235 size_t total_size) {
236 ASSERT_TRUE(IsValidBasicEvent(event));
237 ASSERT_EQ(rtclog::Event::RTP_EVENT, event.type());
238 const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
239 ASSERT_TRUE(rtp_packet.has_incoming());
240 EXPECT_EQ(incoming, rtp_packet.incoming());
241 ASSERT_TRUE(rtp_packet.has_type());
242 EXPECT_EQ(media_type, GetRuntimeMediaType(rtp_packet.type()));
243 ASSERT_TRUE(rtp_packet.has_packet_length());
244 EXPECT_EQ(total_size, rtp_packet.packet_length());
245 ASSERT_TRUE(rtp_packet.has_header());
246 ASSERT_EQ(header_size, rtp_packet.header().size());
247 for (size_t i = 0; i < header_size; i++) {
248 EXPECT_EQ(header[i], static_cast<uint8_t>(rtp_packet.header()[i]));
249 }
250}
251
252void VerifyRtcpEvent(const rtclog::Event& event,
253 bool incoming,
254 MediaType media_type,
255 uint8_t* packet,
256 size_t total_size) {
257 ASSERT_TRUE(IsValidBasicEvent(event));
258 ASSERT_EQ(rtclog::Event::RTCP_EVENT, event.type());
259 const rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet();
260 ASSERT_TRUE(rtcp_packet.has_incoming());
261 EXPECT_EQ(incoming, rtcp_packet.incoming());
262 ASSERT_TRUE(rtcp_packet.has_type());
263 EXPECT_EQ(media_type, GetRuntimeMediaType(rtcp_packet.type()));
264 ASSERT_TRUE(rtcp_packet.has_packet_data());
265 ASSERT_EQ(total_size, rtcp_packet.packet_data().size());
266 for (size_t i = 0; i < total_size; i++) {
267 EXPECT_EQ(packet[i], static_cast<uint8_t>(rtcp_packet.packet_data()[i]));
268 }
269}
270
Ivo Creusenae856f22015-09-17 16:30:16 +0200271void VerifyPlayoutEvent(const rtclog::Event& event, uint32_t ssrc) {
terelius2f9fd5d2015-09-04 03:39:42 -0700272 ASSERT_TRUE(IsValidBasicEvent(event));
Ivo Creusen301aaed2015-10-08 18:07:41 +0200273 ASSERT_EQ(rtclog::Event::AUDIO_PLAYOUT_EVENT, event.type());
274 const rtclog::AudioPlayoutEvent& playout_event = event.audio_playout_event();
275 ASSERT_TRUE(playout_event.has_local_ssrc());
276 EXPECT_EQ(ssrc, playout_event.local_ssrc());
terelius2f9fd5d2015-09-04 03:39:42 -0700277}
278
terelius006d93d2015-11-05 12:02:15 -0800279void VerifyBweLossEvent(const rtclog::Event& event,
280 int32_t bitrate,
281 uint8_t fraction_loss,
282 int32_t total_packets) {
283 ASSERT_TRUE(IsValidBasicEvent(event));
284 ASSERT_EQ(rtclog::Event::BWE_PACKET_LOSS_EVENT, event.type());
285 const rtclog::BwePacketLossEvent& bwe_event = event.bwe_packet_loss_event();
286 ASSERT_TRUE(bwe_event.has_bitrate());
287 EXPECT_EQ(bitrate, bwe_event.bitrate());
288 ASSERT_TRUE(bwe_event.has_fraction_loss());
289 EXPECT_EQ(fraction_loss, bwe_event.fraction_loss());
290 ASSERT_TRUE(bwe_event.has_total_packets());
291 EXPECT_EQ(total_packets, bwe_event.total_packets());
292}
293
Bjorn Terelius36411852015-07-30 12:45:18 +0200294void VerifyLogStartEvent(const rtclog::Event& event) {
295 ASSERT_TRUE(IsValidBasicEvent(event));
Ivo Creusen301aaed2015-10-08 18:07:41 +0200296 EXPECT_EQ(rtclog::Event::LOG_START, event.type());
Bjorn Terelius36411852015-07-30 12:45:18 +0200297}
298
terelius2f9fd5d2015-09-04 03:39:42 -0700299/*
300 * Bit number i of extension_bitvector is set to indicate the
301 * presence of extension number i from kExtensionTypes / kExtensionNames.
302 * The least significant bit extension_bitvector has number 0.
303 */
304size_t GenerateRtpPacket(uint32_t extensions_bitvector,
305 uint32_t csrcs_count,
306 uint8_t* packet,
307 size_t packet_size) {
henrikg91d6ede2015-09-17 00:24:34 -0700308 RTC_CHECK_GE(packet_size, 16 + 4 * csrcs_count + 4 * kNumExtensions);
terelius2f9fd5d2015-09-04 03:39:42 -0700309 Clock* clock = Clock::GetRealTimeClock();
310
Peter Boströmac547a62015-09-17 23:03:57 +0200311 RTPSender rtp_sender(false, // bool audio
terelius2f9fd5d2015-09-04 03:39:42 -0700312 clock, // Clock* clock
313 nullptr, // Transport*
314 nullptr, // RtpAudioFeedback*
315 nullptr, // PacedSender*
316 nullptr, // PacketRouter*
317 nullptr, // SendTimeObserver*
318 nullptr, // BitrateStatisticsObserver*
319 nullptr, // FrameCountObserver*
320 nullptr); // SendSideDelayObserver*
321
322 std::vector<uint32_t> csrcs;
323 for (unsigned i = 0; i < csrcs_count; i++) {
324 csrcs.push_back(rand());
325 }
326 rtp_sender.SetCsrcs(csrcs);
327 rtp_sender.SetSSRC(rand());
328 rtp_sender.SetStartTimestamp(rand(), true);
329 rtp_sender.SetSequenceNumber(rand());
330
331 for (unsigned i = 0; i < kNumExtensions; i++) {
332 if (extensions_bitvector & (1u << i)) {
333 rtp_sender.RegisterRtpHeaderExtension(kExtensionTypes[i], i + 1);
334 }
335 }
336
337 int8_t payload_type = rand() % 128;
338 bool marker_bit = (rand() % 2 == 1);
339 uint32_t capture_timestamp = rand();
340 int64_t capture_time_ms = rand();
341 bool timestamp_provided = (rand() % 2 == 1);
342 bool inc_sequence_number = (rand() % 2 == 1);
343
344 size_t header_size = rtp_sender.BuildRTPheader(
345 packet, payload_type, marker_bit, capture_timestamp, capture_time_ms,
346 timestamp_provided, inc_sequence_number);
347
348 for (size_t i = header_size; i < packet_size; i++) {
349 packet[i] = rand();
350 }
351
352 return header_size;
353}
354
355void GenerateRtcpPacket(uint8_t* packet, size_t packet_size) {
356 for (size_t i = 0; i < packet_size; i++) {
357 packet[i] = rand();
358 }
359}
360
361void GenerateVideoReceiveConfig(uint32_t extensions_bitvector,
362 VideoReceiveStream::Config* config) {
Bjorn Terelius36411852015-07-30 12:45:18 +0200363 // Create a map from a payload type to an encoder name.
364 VideoReceiveStream::Decoder decoder;
365 decoder.payload_type = rand();
366 decoder.payload_name = (rand() % 2 ? "VP8" : "H264");
367 config->decoders.push_back(decoder);
368 // Add SSRCs for the stream.
369 config->rtp.remote_ssrc = rand();
370 config->rtp.local_ssrc = rand();
371 // Add extensions and settings for RTCP.
pbosda903ea2015-10-02 02:36:56 -0700372 config->rtp.rtcp_mode =
373 rand() % 2 ? RtcpMode::kCompound : RtcpMode::kReducedSize;
terelius2f9fd5d2015-09-04 03:39:42 -0700374 config->rtp.rtcp_xr.receiver_reference_time_report = (rand() % 2 == 1);
375 config->rtp.remb = (rand() % 2 == 1);
Bjorn Terelius36411852015-07-30 12:45:18 +0200376 // Add a map from a payload type to a new ssrc and a new payload type for RTX.
377 VideoReceiveStream::Config::Rtp::Rtx rtx_pair;
378 rtx_pair.ssrc = rand();
379 rtx_pair.payload_type = rand();
380 config->rtp.rtx.insert(std::make_pair(rand(), rtx_pair));
terelius2f9fd5d2015-09-04 03:39:42 -0700381 // Add header extensions.
382 for (unsigned i = 0; i < kNumExtensions; i++) {
383 if (extensions_bitvector & (1u << i)) {
384 config->rtp.extensions.push_back(
385 RtpExtension(kExtensionNames[i], rand()));
386 }
387 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200388}
389
terelius2f9fd5d2015-09-04 03:39:42 -0700390void GenerateVideoSendConfig(uint32_t extensions_bitvector,
391 VideoSendStream::Config* config) {
Bjorn Terelius36411852015-07-30 12:45:18 +0200392 // Create a map from a payload type to an encoder name.
393 config->encoder_settings.payload_type = rand();
394 config->encoder_settings.payload_name = (rand() % 2 ? "VP8" : "H264");
395 // Add SSRCs for the stream.
396 config->rtp.ssrcs.push_back(rand());
397 // Add a map from a payload type to new ssrcs and a new payload type for RTX.
398 config->rtp.rtx.ssrcs.push_back(rand());
399 config->rtp.rtx.payload_type = rand();
400 // Add a CNAME.
401 config->rtp.c_name = "some.user@some.host";
terelius2f9fd5d2015-09-04 03:39:42 -0700402 // Add header extensions.
403 for (unsigned i = 0; i < kNumExtensions; i++) {
404 if (extensions_bitvector & (1u << i)) {
405 config->rtp.extensions.push_back(
406 RtpExtension(kExtensionNames[i], rand()));
407 }
408 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200409}
410
terelius1adce142015-10-16 08:51:08 -0700411// Test for the RtcEventLog class. Dumps some RTP packets and other events
412// to disk, then reads them back to see if they match.
terelius2f9fd5d2015-09-04 03:39:42 -0700413void LogSessionAndReadBack(size_t rtp_count,
414 size_t rtcp_count,
Ivo Creusen301aaed2015-10-08 18:07:41 +0200415 size_t playout_count,
terelius006d93d2015-11-05 12:02:15 -0800416 size_t bwe_loss_count,
terelius2f9fd5d2015-09-04 03:39:42 -0700417 uint32_t extensions_bitvector,
418 uint32_t csrcs_count,
terelius1adce142015-10-16 08:51:08 -0700419 unsigned int random_seed) {
terelius2f9fd5d2015-09-04 03:39:42 -0700420 ASSERT_LE(rtcp_count, rtp_count);
Ivo Creusen301aaed2015-10-08 18:07:41 +0200421 ASSERT_LE(playout_count, rtp_count);
terelius006d93d2015-11-05 12:02:15 -0800422 ASSERT_LE(bwe_loss_count, rtp_count);
terelius2f9fd5d2015-09-04 03:39:42 -0700423 std::vector<rtc::Buffer> rtp_packets;
424 std::vector<rtc::Buffer> rtcp_packets;
425 std::vector<size_t> rtp_header_sizes;
Ivo Creusenae856f22015-09-17 16:30:16 +0200426 std::vector<uint32_t> playout_ssrcs;
terelius006d93d2015-11-05 12:02:15 -0800427 std::vector<std::pair<int32_t, uint8_t> > bwe_loss_updates;
Bjorn Terelius36411852015-07-30 12:45:18 +0200428
solenberg4fbae2b2015-08-28 04:07:10 -0700429 VideoReceiveStream::Config receiver_config(nullptr);
430 VideoSendStream::Config sender_config(nullptr);
Bjorn Terelius36411852015-07-30 12:45:18 +0200431
432 srand(random_seed);
433
434 // Create rtp_count RTP packets containing random data.
Bjorn Terelius36411852015-07-30 12:45:18 +0200435 for (size_t i = 0; i < rtp_count; i++) {
terelius2f9fd5d2015-09-04 03:39:42 -0700436 size_t packet_size = 1000 + rand() % 64;
437 rtp_packets.push_back(rtc::Buffer(packet_size));
438 size_t header_size = GenerateRtpPacket(extensions_bitvector, csrcs_count,
439 rtp_packets[i].data(), packet_size);
440 rtp_header_sizes.push_back(header_size);
Bjorn Terelius36411852015-07-30 12:45:18 +0200441 }
terelius2f9fd5d2015-09-04 03:39:42 -0700442 // Create rtcp_count RTCP packets containing random data.
443 for (size_t i = 0; i < rtcp_count; i++) {
444 size_t packet_size = 1000 + rand() % 64;
445 rtcp_packets.push_back(rtc::Buffer(packet_size));
446 GenerateRtcpPacket(rtcp_packets[i].data(), packet_size);
Bjorn Terelius36411852015-07-30 12:45:18 +0200447 }
Ivo Creusen301aaed2015-10-08 18:07:41 +0200448 // Create playout_count random SSRCs to use when logging AudioPlayout events.
449 for (size_t i = 0; i < playout_count; i++) {
Ivo Creusenae856f22015-09-17 16:30:16 +0200450 playout_ssrcs.push_back(static_cast<uint32_t>(rand()));
451 }
terelius006d93d2015-11-05 12:02:15 -0800452 // Create bwe_loss_count random bitrate updates for BwePacketLoss.
453 for (size_t i = 0; i < bwe_loss_count; i++) {
454 bwe_loss_updates.push_back(std::pair<int32_t, uint8_t>(rand(), rand()));
455 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200456 // Create configurations for the video streams.
terelius2f9fd5d2015-09-04 03:39:42 -0700457 GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config);
458 GenerateVideoSendConfig(extensions_bitvector, &sender_config);
459 const int config_count = 2;
Bjorn Terelius36411852015-07-30 12:45:18 +0200460
461 // Find the name of the current test, in order to use it as a temporary
462 // filename.
463 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
464 const std::string temp_filename =
465 test::OutputPath() + test_info->test_case_name() + test_info->name();
466
467 // When log_dumper goes out of scope, it causes the log file to be flushed
468 // to disk.
469 {
470 rtc::scoped_ptr<RtcEventLog> log_dumper(RtcEventLog::Create());
471 log_dumper->LogVideoReceiveStreamConfig(receiver_config);
472 log_dumper->LogVideoSendStreamConfig(sender_config);
terelius006d93d2015-11-05 12:02:15 -0800473 size_t rtcp_index = 1;
474 size_t playout_index = 1;
475 size_t bwe_loss_index = 1;
terelius2f9fd5d2015-09-04 03:39:42 -0700476 for (size_t i = 1; i <= rtp_count; i++) {
Bjorn Terelius36411852015-07-30 12:45:18 +0200477 log_dumper->LogRtpHeader(
478 (i % 2 == 0), // Every second packet is incoming.
479 (i % 3 == 0) ? MediaType::AUDIO : MediaType::VIDEO,
terelius2f9fd5d2015-09-04 03:39:42 -0700480 rtp_packets[i - 1].data(), rtp_packets[i - 1].size());
481 if (i * rtcp_count >= rtcp_index * rtp_count) {
482 log_dumper->LogRtcpPacket(
483 rtcp_index % 2 == 0, // Every second packet is incoming
484 rtcp_index % 3 == 0 ? MediaType::AUDIO : MediaType::VIDEO,
485 rtcp_packets[rtcp_index - 1].data(),
486 rtcp_packets[rtcp_index - 1].size());
487 rtcp_index++;
488 }
Ivo Creusen301aaed2015-10-08 18:07:41 +0200489 if (i * playout_count >= playout_index * rtp_count) {
490 log_dumper->LogAudioPlayout(playout_ssrcs[playout_index - 1]);
491 playout_index++;
terelius2f9fd5d2015-09-04 03:39:42 -0700492 }
terelius006d93d2015-11-05 12:02:15 -0800493 if (i * bwe_loss_count >= bwe_loss_index * rtp_count) {
494 log_dumper->LogBwePacketLossEvent(
495 bwe_loss_updates[bwe_loss_index - 1].first,
496 bwe_loss_updates[bwe_loss_index - 1].second, i);
497 bwe_loss_index++;
498 }
terelius2f9fd5d2015-09-04 03:39:42 -0700499 if (i == rtp_count / 2) {
500 log_dumper->StartLogging(temp_filename, 10000000);
501 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200502 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200503 }
504
Bjorn Terelius36411852015-07-30 12:45:18 +0200505 // Read the generated file from disk.
506 rtclog::EventStream parsed_stream;
507
508 ASSERT_TRUE(RtcEventLog::ParseRtcEventLog(temp_filename, &parsed_stream));
509
terelius1adce142015-10-16 08:51:08 -0700510 // Verify that what we read back from the event log is the same as
511 // what we wrote down. For RTCP we log the full packets, but for
512 // RTP we should only log the header.
terelius006d93d2015-11-05 12:02:15 -0800513 const int event_count = config_count + playout_count + bwe_loss_count +
514 rtcp_count + rtp_count + 1;
Bjorn Terelius36411852015-07-30 12:45:18 +0200515 EXPECT_EQ(event_count, parsed_stream.stream_size());
516 VerifyReceiveStreamConfig(parsed_stream.stream(0), receiver_config);
517 VerifySendStreamConfig(parsed_stream.stream(1), sender_config);
terelius006d93d2015-11-05 12:02:15 -0800518 size_t event_index = config_count;
519 size_t rtcp_index = 1;
520 size_t playout_index = 1;
521 size_t bwe_loss_index = 1;
terelius2f9fd5d2015-09-04 03:39:42 -0700522 for (size_t i = 1; i <= rtp_count; i++) {
523 VerifyRtpEvent(parsed_stream.stream(event_index),
Bjorn Terelius36411852015-07-30 12:45:18 +0200524 (i % 2 == 0), // Every second packet is incoming.
525 (i % 3 == 0) ? MediaType::AUDIO : MediaType::VIDEO,
terelius2f9fd5d2015-09-04 03:39:42 -0700526 rtp_packets[i - 1].data(), rtp_header_sizes[i - 1],
527 rtp_packets[i - 1].size());
528 event_index++;
529 if (i * rtcp_count >= rtcp_index * rtp_count) {
530 VerifyRtcpEvent(parsed_stream.stream(event_index),
531 rtcp_index % 2 == 0, // Every second packet is incoming.
532 rtcp_index % 3 == 0 ? MediaType::AUDIO : MediaType::VIDEO,
533 rtcp_packets[rtcp_index - 1].data(),
534 rtcp_packets[rtcp_index - 1].size());
535 event_index++;
536 rtcp_index++;
537 }
Ivo Creusen301aaed2015-10-08 18:07:41 +0200538 if (i * playout_count >= playout_index * rtp_count) {
Ivo Creusenae856f22015-09-17 16:30:16 +0200539 VerifyPlayoutEvent(parsed_stream.stream(event_index),
Ivo Creusen301aaed2015-10-08 18:07:41 +0200540 playout_ssrcs[playout_index - 1]);
terelius2f9fd5d2015-09-04 03:39:42 -0700541 event_index++;
Ivo Creusen301aaed2015-10-08 18:07:41 +0200542 playout_index++;
terelius2f9fd5d2015-09-04 03:39:42 -0700543 }
terelius006d93d2015-11-05 12:02:15 -0800544 if (i * bwe_loss_count >= bwe_loss_index * rtp_count) {
545 VerifyBweLossEvent(parsed_stream.stream(event_index),
546 bwe_loss_updates[bwe_loss_index - 1].first,
547 bwe_loss_updates[bwe_loss_index - 1].second, i);
548 event_index++;
549 bwe_loss_index++;
550 }
terelius2f9fd5d2015-09-04 03:39:42 -0700551 if (i == rtp_count / 2) {
552 VerifyLogStartEvent(parsed_stream.stream(event_index));
553 event_index++;
554 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200555 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200556
557 // Clean up temporary file - can be pretty slow.
558 remove(temp_filename.c_str());
559}
560
561TEST(RtcEventLogTest, LogSessionAndReadBack) {
terelius006d93d2015-11-05 12:02:15 -0800562 // Log 5 RTP, 2 RTCP, 0 playout events and 0 BWE events
563 // with no header extensions or CSRCS.
564 LogSessionAndReadBack(5, 2, 0, 0, 0, 0, 321);
terelius2f9fd5d2015-09-04 03:39:42 -0700565
terelius006d93d2015-11-05 12:02:15 -0800566 // Enable AbsSendTime and TransportSequenceNumbers.
terelius2f9fd5d2015-09-04 03:39:42 -0700567 uint32_t extensions = 0;
568 for (uint32_t i = 0; i < kNumExtensions; i++) {
569 if (kExtensionTypes[i] == RTPExtensionType::kRtpExtensionAbsoluteSendTime ||
570 kExtensionTypes[i] ==
571 RTPExtensionType::kRtpExtensionTransportSequenceNumber) {
572 extensions |= 1u << i;
573 }
574 }
terelius006d93d2015-11-05 12:02:15 -0800575 LogSessionAndReadBack(8, 2, 0, 0, extensions, 0, 3141592653u);
terelius2f9fd5d2015-09-04 03:39:42 -0700576
terelius006d93d2015-11-05 12:02:15 -0800577 extensions = (1u << kNumExtensions) - 1; // Enable all header extensions.
578 LogSessionAndReadBack(9, 2, 3, 2, extensions, 2, 2718281828u);
terelius2f9fd5d2015-09-04 03:39:42 -0700579
580 // Try all combinations of header extensions and up to 2 CSRCS.
581 for (extensions = 0; extensions < (1u << kNumExtensions); extensions++) {
582 for (uint32_t csrcs_count = 0; csrcs_count < 3; csrcs_count++) {
583 LogSessionAndReadBack(5 + extensions, // Number of RTP packets.
584 2 + csrcs_count, // Number of RTCP packets.
terelius006d93d2015-11-05 12:02:15 -0800585 3 + csrcs_count, // Number of playout events.
586 1 + csrcs_count, // Number of BWE loss events.
587 extensions, // Bit vector choosing extensions.
588 csrcs_count, // Number of contributing sources.
terelius2f9fd5d2015-09-04 03:39:42 -0700589 rand());
590 }
591 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200592}
593
terelius1adce142015-10-16 08:51:08 -0700594// Tests that the event queue works correctly, i.e. drops old RTP, RTCP and
595// debug events, but keeps config events even if they are older than the limit.
596void DropOldEvents(uint32_t extensions_bitvector,
597 uint32_t csrcs_count,
598 unsigned int random_seed) {
599 rtc::Buffer old_rtp_packet;
600 rtc::Buffer recent_rtp_packet;
601 rtc::Buffer old_rtcp_packet;
602 rtc::Buffer recent_rtcp_packet;
603
604 VideoReceiveStream::Config receiver_config(nullptr);
605 VideoSendStream::Config sender_config(nullptr);
606
607 srand(random_seed);
608
609 // Create two RTP packets containing random data.
610 size_t packet_size = 1000 + rand() % 64;
611 old_rtp_packet.SetSize(packet_size);
612 GenerateRtpPacket(extensions_bitvector, csrcs_count, old_rtp_packet.data(),
613 packet_size);
614 packet_size = 1000 + rand() % 64;
615 recent_rtp_packet.SetSize(packet_size);
616 size_t recent_header_size = GenerateRtpPacket(
617 extensions_bitvector, csrcs_count, recent_rtp_packet.data(), packet_size);
618
619 // Create two RTCP packets containing random data.
620 packet_size = 1000 + rand() % 64;
621 old_rtcp_packet.SetSize(packet_size);
622 GenerateRtcpPacket(old_rtcp_packet.data(), packet_size);
623 packet_size = 1000 + rand() % 64;
624 recent_rtcp_packet.SetSize(packet_size);
625 GenerateRtcpPacket(recent_rtcp_packet.data(), packet_size);
626
627 // Create configurations for the video streams.
628 GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config);
629 GenerateVideoSendConfig(extensions_bitvector, &sender_config);
630
631 // Find the name of the current test, in order to use it as a temporary
632 // filename.
633 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
634 const std::string temp_filename =
635 test::OutputPath() + test_info->test_case_name() + test_info->name();
636
637 // The log file will be flushed to disk when the log_dumper goes out of scope.
638 {
639 rtc::scoped_ptr<RtcEventLog> log_dumper(RtcEventLog::Create());
640 // Reduce the time old events are stored to 50 ms.
641 log_dumper->SetBufferDuration(50000);
642 log_dumper->LogVideoReceiveStreamConfig(receiver_config);
643 log_dumper->LogVideoSendStreamConfig(sender_config);
644 log_dumper->LogRtpHeader(false, MediaType::AUDIO, old_rtp_packet.data(),
645 old_rtp_packet.size());
646 log_dumper->LogRtcpPacket(true, MediaType::AUDIO, old_rtcp_packet.data(),
647 old_rtcp_packet.size());
648 // Sleep 55 ms to let old events be removed from the queue.
649 rtc::Thread::SleepMs(55);
650 log_dumper->StartLogging(temp_filename, 10000000);
651 log_dumper->LogRtpHeader(true, MediaType::VIDEO, recent_rtp_packet.data(),
652 recent_rtp_packet.size());
653 log_dumper->LogRtcpPacket(false, MediaType::VIDEO,
654 recent_rtcp_packet.data(),
655 recent_rtcp_packet.size());
656 }
657
658 // Read the generated file from disk.
659 rtclog::EventStream parsed_stream;
660 ASSERT_TRUE(RtcEventLog::ParseRtcEventLog(temp_filename, &parsed_stream));
661
662 // Verify that what we read back from the event log is the same as
663 // what we wrote. Old RTP and RTCP events should have been discarded,
664 // but old configuration events should still be available.
665 EXPECT_EQ(5, parsed_stream.stream_size());
666 VerifyReceiveStreamConfig(parsed_stream.stream(0), receiver_config);
667 VerifySendStreamConfig(parsed_stream.stream(1), sender_config);
668 VerifyLogStartEvent(parsed_stream.stream(2));
669 VerifyRtpEvent(parsed_stream.stream(3), true, MediaType::VIDEO,
670 recent_rtp_packet.data(), recent_header_size,
671 recent_rtp_packet.size());
672 VerifyRtcpEvent(parsed_stream.stream(4), false, MediaType::VIDEO,
673 recent_rtcp_packet.data(), recent_rtcp_packet.size());
674
675 // Clean up temporary file - can be pretty slow.
676 remove(temp_filename.c_str());
677}
678
679TEST(RtcEventLogTest, DropOldEvents) {
680 // Enable all header extensions
681 uint32_t extensions = (1u << kNumExtensions) - 1;
682 uint32_t csrcs_count = 2;
683 DropOldEvents(extensions, csrcs_count, 141421356);
684 DropOldEvents(extensions, csrcs_count, 173205080);
685}
686
Bjorn Terelius36411852015-07-30 12:45:18 +0200687} // namespace webrtc
688
689#endif // ENABLE_RTC_EVENT_LOG