blob: cae2a202e0e090835032b99a51ec1ff33d50936d [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"
Bjorn Terelius36411852015-07-30 12:45:18 +020025#include "webrtc/system_wrappers/interface/clock.h"
26#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
Bjorn Terelius36411852015-07-30 12:45:18 +0200279void VerifyLogStartEvent(const rtclog::Event& event) {
280 ASSERT_TRUE(IsValidBasicEvent(event));
Ivo Creusen301aaed2015-10-08 18:07:41 +0200281 EXPECT_EQ(rtclog::Event::LOG_START, event.type());
Bjorn Terelius36411852015-07-30 12:45:18 +0200282}
283
terelius2f9fd5d2015-09-04 03:39:42 -0700284/*
285 * Bit number i of extension_bitvector is set to indicate the
286 * presence of extension number i from kExtensionTypes / kExtensionNames.
287 * The least significant bit extension_bitvector has number 0.
288 */
289size_t GenerateRtpPacket(uint32_t extensions_bitvector,
290 uint32_t csrcs_count,
291 uint8_t* packet,
292 size_t packet_size) {
henrikg91d6ede2015-09-17 00:24:34 -0700293 RTC_CHECK_GE(packet_size, 16 + 4 * csrcs_count + 4 * kNumExtensions);
terelius2f9fd5d2015-09-04 03:39:42 -0700294 Clock* clock = Clock::GetRealTimeClock();
295
Peter Boströmac547a62015-09-17 23:03:57 +0200296 RTPSender rtp_sender(false, // bool audio
terelius2f9fd5d2015-09-04 03:39:42 -0700297 clock, // Clock* clock
298 nullptr, // Transport*
299 nullptr, // RtpAudioFeedback*
300 nullptr, // PacedSender*
301 nullptr, // PacketRouter*
302 nullptr, // SendTimeObserver*
303 nullptr, // BitrateStatisticsObserver*
304 nullptr, // FrameCountObserver*
305 nullptr); // SendSideDelayObserver*
306
307 std::vector<uint32_t> csrcs;
308 for (unsigned i = 0; i < csrcs_count; i++) {
309 csrcs.push_back(rand());
310 }
311 rtp_sender.SetCsrcs(csrcs);
312 rtp_sender.SetSSRC(rand());
313 rtp_sender.SetStartTimestamp(rand(), true);
314 rtp_sender.SetSequenceNumber(rand());
315
316 for (unsigned i = 0; i < kNumExtensions; i++) {
317 if (extensions_bitvector & (1u << i)) {
318 rtp_sender.RegisterRtpHeaderExtension(kExtensionTypes[i], i + 1);
319 }
320 }
321
322 int8_t payload_type = rand() % 128;
323 bool marker_bit = (rand() % 2 == 1);
324 uint32_t capture_timestamp = rand();
325 int64_t capture_time_ms = rand();
326 bool timestamp_provided = (rand() % 2 == 1);
327 bool inc_sequence_number = (rand() % 2 == 1);
328
329 size_t header_size = rtp_sender.BuildRTPheader(
330 packet, payload_type, marker_bit, capture_timestamp, capture_time_ms,
331 timestamp_provided, inc_sequence_number);
332
333 for (size_t i = header_size; i < packet_size; i++) {
334 packet[i] = rand();
335 }
336
337 return header_size;
338}
339
340void GenerateRtcpPacket(uint8_t* packet, size_t packet_size) {
341 for (size_t i = 0; i < packet_size; i++) {
342 packet[i] = rand();
343 }
344}
345
346void GenerateVideoReceiveConfig(uint32_t extensions_bitvector,
347 VideoReceiveStream::Config* config) {
Bjorn Terelius36411852015-07-30 12:45:18 +0200348 // Create a map from a payload type to an encoder name.
349 VideoReceiveStream::Decoder decoder;
350 decoder.payload_type = rand();
351 decoder.payload_name = (rand() % 2 ? "VP8" : "H264");
352 config->decoders.push_back(decoder);
353 // Add SSRCs for the stream.
354 config->rtp.remote_ssrc = rand();
355 config->rtp.local_ssrc = rand();
356 // Add extensions and settings for RTCP.
pbosda903ea2015-10-02 02:36:56 -0700357 config->rtp.rtcp_mode =
358 rand() % 2 ? RtcpMode::kCompound : RtcpMode::kReducedSize;
terelius2f9fd5d2015-09-04 03:39:42 -0700359 config->rtp.rtcp_xr.receiver_reference_time_report = (rand() % 2 == 1);
360 config->rtp.remb = (rand() % 2 == 1);
Bjorn Terelius36411852015-07-30 12:45:18 +0200361 // Add a map from a payload type to a new ssrc and a new payload type for RTX.
362 VideoReceiveStream::Config::Rtp::Rtx rtx_pair;
363 rtx_pair.ssrc = rand();
364 rtx_pair.payload_type = rand();
365 config->rtp.rtx.insert(std::make_pair(rand(), rtx_pair));
terelius2f9fd5d2015-09-04 03:39:42 -0700366 // Add header extensions.
367 for (unsigned i = 0; i < kNumExtensions; i++) {
368 if (extensions_bitvector & (1u << i)) {
369 config->rtp.extensions.push_back(
370 RtpExtension(kExtensionNames[i], rand()));
371 }
372 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200373}
374
terelius2f9fd5d2015-09-04 03:39:42 -0700375void GenerateVideoSendConfig(uint32_t extensions_bitvector,
376 VideoSendStream::Config* config) {
Bjorn Terelius36411852015-07-30 12:45:18 +0200377 // Create a map from a payload type to an encoder name.
378 config->encoder_settings.payload_type = rand();
379 config->encoder_settings.payload_name = (rand() % 2 ? "VP8" : "H264");
380 // Add SSRCs for the stream.
381 config->rtp.ssrcs.push_back(rand());
382 // Add a map from a payload type to new ssrcs and a new payload type for RTX.
383 config->rtp.rtx.ssrcs.push_back(rand());
384 config->rtp.rtx.payload_type = rand();
385 // Add a CNAME.
386 config->rtp.c_name = "some.user@some.host";
terelius2f9fd5d2015-09-04 03:39:42 -0700387 // Add header extensions.
388 for (unsigned i = 0; i < kNumExtensions; i++) {
389 if (extensions_bitvector & (1u << i)) {
390 config->rtp.extensions.push_back(
391 RtpExtension(kExtensionNames[i], rand()));
392 }
393 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200394}
395
terelius1adce142015-10-16 08:51:08 -0700396// Test for the RtcEventLog class. Dumps some RTP packets and other events
397// to disk, then reads them back to see if they match.
terelius2f9fd5d2015-09-04 03:39:42 -0700398void LogSessionAndReadBack(size_t rtp_count,
399 size_t rtcp_count,
Ivo Creusen301aaed2015-10-08 18:07:41 +0200400 size_t playout_count,
terelius2f9fd5d2015-09-04 03:39:42 -0700401 uint32_t extensions_bitvector,
402 uint32_t csrcs_count,
terelius1adce142015-10-16 08:51:08 -0700403 unsigned int random_seed) {
terelius2f9fd5d2015-09-04 03:39:42 -0700404 ASSERT_LE(rtcp_count, rtp_count);
Ivo Creusen301aaed2015-10-08 18:07:41 +0200405 ASSERT_LE(playout_count, rtp_count);
terelius2f9fd5d2015-09-04 03:39:42 -0700406 std::vector<rtc::Buffer> rtp_packets;
407 std::vector<rtc::Buffer> rtcp_packets;
408 std::vector<size_t> rtp_header_sizes;
Ivo Creusenae856f22015-09-17 16:30:16 +0200409 std::vector<uint32_t> playout_ssrcs;
Bjorn Terelius36411852015-07-30 12:45:18 +0200410
solenberg4fbae2b2015-08-28 04:07:10 -0700411 VideoReceiveStream::Config receiver_config(nullptr);
412 VideoSendStream::Config sender_config(nullptr);
Bjorn Terelius36411852015-07-30 12:45:18 +0200413
414 srand(random_seed);
415
416 // Create rtp_count RTP packets containing random data.
Bjorn Terelius36411852015-07-30 12:45:18 +0200417 for (size_t i = 0; i < rtp_count; i++) {
terelius2f9fd5d2015-09-04 03:39:42 -0700418 size_t packet_size = 1000 + rand() % 64;
419 rtp_packets.push_back(rtc::Buffer(packet_size));
420 size_t header_size = GenerateRtpPacket(extensions_bitvector, csrcs_count,
421 rtp_packets[i].data(), packet_size);
422 rtp_header_sizes.push_back(header_size);
Bjorn Terelius36411852015-07-30 12:45:18 +0200423 }
terelius2f9fd5d2015-09-04 03:39:42 -0700424 // Create rtcp_count RTCP packets containing random data.
425 for (size_t i = 0; i < rtcp_count; i++) {
426 size_t packet_size = 1000 + rand() % 64;
427 rtcp_packets.push_back(rtc::Buffer(packet_size));
428 GenerateRtcpPacket(rtcp_packets[i].data(), packet_size);
Bjorn Terelius36411852015-07-30 12:45:18 +0200429 }
Ivo Creusen301aaed2015-10-08 18:07:41 +0200430 // Create playout_count random SSRCs to use when logging AudioPlayout events.
431 for (size_t i = 0; i < playout_count; i++) {
Ivo Creusenae856f22015-09-17 16:30:16 +0200432 playout_ssrcs.push_back(static_cast<uint32_t>(rand()));
433 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200434 // Create configurations for the video streams.
terelius2f9fd5d2015-09-04 03:39:42 -0700435 GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config);
436 GenerateVideoSendConfig(extensions_bitvector, &sender_config);
437 const int config_count = 2;
Bjorn Terelius36411852015-07-30 12:45:18 +0200438
439 // Find the name of the current test, in order to use it as a temporary
440 // filename.
441 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
442 const std::string temp_filename =
443 test::OutputPath() + test_info->test_case_name() + test_info->name();
444
445 // When log_dumper goes out of scope, it causes the log file to be flushed
446 // to disk.
447 {
448 rtc::scoped_ptr<RtcEventLog> log_dumper(RtcEventLog::Create());
449 log_dumper->LogVideoReceiveStreamConfig(receiver_config);
450 log_dumper->LogVideoSendStreamConfig(sender_config);
Ivo Creusen301aaed2015-10-08 18:07:41 +0200451 size_t rtcp_index = 1, playout_index = 1;
terelius2f9fd5d2015-09-04 03:39:42 -0700452 for (size_t i = 1; i <= rtp_count; i++) {
Bjorn Terelius36411852015-07-30 12:45:18 +0200453 log_dumper->LogRtpHeader(
454 (i % 2 == 0), // Every second packet is incoming.
455 (i % 3 == 0) ? MediaType::AUDIO : MediaType::VIDEO,
terelius2f9fd5d2015-09-04 03:39:42 -0700456 rtp_packets[i - 1].data(), rtp_packets[i - 1].size());
457 if (i * rtcp_count >= rtcp_index * rtp_count) {
458 log_dumper->LogRtcpPacket(
459 rtcp_index % 2 == 0, // Every second packet is incoming
460 rtcp_index % 3 == 0 ? MediaType::AUDIO : MediaType::VIDEO,
461 rtcp_packets[rtcp_index - 1].data(),
462 rtcp_packets[rtcp_index - 1].size());
463 rtcp_index++;
464 }
Ivo Creusen301aaed2015-10-08 18:07:41 +0200465 if (i * playout_count >= playout_index * rtp_count) {
466 log_dumper->LogAudioPlayout(playout_ssrcs[playout_index - 1]);
467 playout_index++;
terelius2f9fd5d2015-09-04 03:39:42 -0700468 }
469 if (i == rtp_count / 2) {
470 log_dumper->StartLogging(temp_filename, 10000000);
471 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200472 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200473 }
474
Bjorn Terelius36411852015-07-30 12:45:18 +0200475 // Read the generated file from disk.
476 rtclog::EventStream parsed_stream;
477
478 ASSERT_TRUE(RtcEventLog::ParseRtcEventLog(temp_filename, &parsed_stream));
479
terelius1adce142015-10-16 08:51:08 -0700480 // Verify that what we read back from the event log is the same as
481 // what we wrote down. For RTCP we log the full packets, but for
482 // RTP we should only log the header.
terelius2f9fd5d2015-09-04 03:39:42 -0700483 const int event_count =
Ivo Creusen301aaed2015-10-08 18:07:41 +0200484 config_count + playout_count + rtcp_count + rtp_count + 1;
Bjorn Terelius36411852015-07-30 12:45:18 +0200485 EXPECT_EQ(event_count, parsed_stream.stream_size());
486 VerifyReceiveStreamConfig(parsed_stream.stream(0), receiver_config);
487 VerifySendStreamConfig(parsed_stream.stream(1), sender_config);
Ivo Creusen301aaed2015-10-08 18:07:41 +0200488 size_t event_index = config_count, rtcp_index = 1, playout_index = 1;
terelius2f9fd5d2015-09-04 03:39:42 -0700489 for (size_t i = 1; i <= rtp_count; i++) {
490 VerifyRtpEvent(parsed_stream.stream(event_index),
Bjorn Terelius36411852015-07-30 12:45:18 +0200491 (i % 2 == 0), // Every second packet is incoming.
492 (i % 3 == 0) ? MediaType::AUDIO : MediaType::VIDEO,
terelius2f9fd5d2015-09-04 03:39:42 -0700493 rtp_packets[i - 1].data(), rtp_header_sizes[i - 1],
494 rtp_packets[i - 1].size());
495 event_index++;
496 if (i * rtcp_count >= rtcp_index * rtp_count) {
497 VerifyRtcpEvent(parsed_stream.stream(event_index),
498 rtcp_index % 2 == 0, // Every second packet is incoming.
499 rtcp_index % 3 == 0 ? MediaType::AUDIO : MediaType::VIDEO,
500 rtcp_packets[rtcp_index - 1].data(),
501 rtcp_packets[rtcp_index - 1].size());
502 event_index++;
503 rtcp_index++;
504 }
Ivo Creusen301aaed2015-10-08 18:07:41 +0200505 if (i * playout_count >= playout_index * rtp_count) {
Ivo Creusenae856f22015-09-17 16:30:16 +0200506 VerifyPlayoutEvent(parsed_stream.stream(event_index),
Ivo Creusen301aaed2015-10-08 18:07:41 +0200507 playout_ssrcs[playout_index - 1]);
terelius2f9fd5d2015-09-04 03:39:42 -0700508 event_index++;
Ivo Creusen301aaed2015-10-08 18:07:41 +0200509 playout_index++;
terelius2f9fd5d2015-09-04 03:39:42 -0700510 }
511 if (i == rtp_count / 2) {
512 VerifyLogStartEvent(parsed_stream.stream(event_index));
513 event_index++;
514 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200515 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200516
517 // Clean up temporary file - can be pretty slow.
518 remove(temp_filename.c_str());
519}
520
521TEST(RtcEventLogTest, LogSessionAndReadBack) {
terelius2f9fd5d2015-09-04 03:39:42 -0700522 // Log 5 RTP, 2 RTCP, and 0 playout events with no header extensions or CSRCS.
523 LogSessionAndReadBack(5, 2, 0, 0, 0, 321);
524
525 // Enable AbsSendTime and TransportSequenceNumbers
526 uint32_t extensions = 0;
527 for (uint32_t i = 0; i < kNumExtensions; i++) {
528 if (kExtensionTypes[i] == RTPExtensionType::kRtpExtensionAbsoluteSendTime ||
529 kExtensionTypes[i] ==
530 RTPExtensionType::kRtpExtensionTransportSequenceNumber) {
531 extensions |= 1u << i;
532 }
533 }
534 LogSessionAndReadBack(8, 2, 0, extensions, 0, 3141592653u);
535
536 extensions = (1u << kNumExtensions) - 1; // Enable all header extensions
537 LogSessionAndReadBack(9, 2, 3, extensions, 2, 2718281828u);
538
539 // Try all combinations of header extensions and up to 2 CSRCS.
540 for (extensions = 0; extensions < (1u << kNumExtensions); extensions++) {
541 for (uint32_t csrcs_count = 0; csrcs_count < 3; csrcs_count++) {
542 LogSessionAndReadBack(5 + extensions, // Number of RTP packets.
543 2 + csrcs_count, // Number of RTCP packets.
544 3 + csrcs_count, // Number of playout events
545 extensions, // Bit vector choosing extensions
546 csrcs_count, // Number of contributing sources
547 rand());
548 }
549 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200550}
551
terelius1adce142015-10-16 08:51:08 -0700552// Tests that the event queue works correctly, i.e. drops old RTP, RTCP and
553// debug events, but keeps config events even if they are older than the limit.
554void DropOldEvents(uint32_t extensions_bitvector,
555 uint32_t csrcs_count,
556 unsigned int random_seed) {
557 rtc::Buffer old_rtp_packet;
558 rtc::Buffer recent_rtp_packet;
559 rtc::Buffer old_rtcp_packet;
560 rtc::Buffer recent_rtcp_packet;
561
562 VideoReceiveStream::Config receiver_config(nullptr);
563 VideoSendStream::Config sender_config(nullptr);
564
565 srand(random_seed);
566
567 // Create two RTP packets containing random data.
568 size_t packet_size = 1000 + rand() % 64;
569 old_rtp_packet.SetSize(packet_size);
570 GenerateRtpPacket(extensions_bitvector, csrcs_count, old_rtp_packet.data(),
571 packet_size);
572 packet_size = 1000 + rand() % 64;
573 recent_rtp_packet.SetSize(packet_size);
574 size_t recent_header_size = GenerateRtpPacket(
575 extensions_bitvector, csrcs_count, recent_rtp_packet.data(), packet_size);
576
577 // Create two RTCP packets containing random data.
578 packet_size = 1000 + rand() % 64;
579 old_rtcp_packet.SetSize(packet_size);
580 GenerateRtcpPacket(old_rtcp_packet.data(), packet_size);
581 packet_size = 1000 + rand() % 64;
582 recent_rtcp_packet.SetSize(packet_size);
583 GenerateRtcpPacket(recent_rtcp_packet.data(), packet_size);
584
585 // Create configurations for the video streams.
586 GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config);
587 GenerateVideoSendConfig(extensions_bitvector, &sender_config);
588
589 // Find the name of the current test, in order to use it as a temporary
590 // filename.
591 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
592 const std::string temp_filename =
593 test::OutputPath() + test_info->test_case_name() + test_info->name();
594
595 // The log file will be flushed to disk when the log_dumper goes out of scope.
596 {
597 rtc::scoped_ptr<RtcEventLog> log_dumper(RtcEventLog::Create());
598 // Reduce the time old events are stored to 50 ms.
599 log_dumper->SetBufferDuration(50000);
600 log_dumper->LogVideoReceiveStreamConfig(receiver_config);
601 log_dumper->LogVideoSendStreamConfig(sender_config);
602 log_dumper->LogRtpHeader(false, MediaType::AUDIO, old_rtp_packet.data(),
603 old_rtp_packet.size());
604 log_dumper->LogRtcpPacket(true, MediaType::AUDIO, old_rtcp_packet.data(),
605 old_rtcp_packet.size());
606 // Sleep 55 ms to let old events be removed from the queue.
607 rtc::Thread::SleepMs(55);
608 log_dumper->StartLogging(temp_filename, 10000000);
609 log_dumper->LogRtpHeader(true, MediaType::VIDEO, recent_rtp_packet.data(),
610 recent_rtp_packet.size());
611 log_dumper->LogRtcpPacket(false, MediaType::VIDEO,
612 recent_rtcp_packet.data(),
613 recent_rtcp_packet.size());
614 }
615
616 // Read the generated file from disk.
617 rtclog::EventStream parsed_stream;
618 ASSERT_TRUE(RtcEventLog::ParseRtcEventLog(temp_filename, &parsed_stream));
619
620 // Verify that what we read back from the event log is the same as
621 // what we wrote. Old RTP and RTCP events should have been discarded,
622 // but old configuration events should still be available.
623 EXPECT_EQ(5, parsed_stream.stream_size());
624 VerifyReceiveStreamConfig(parsed_stream.stream(0), receiver_config);
625 VerifySendStreamConfig(parsed_stream.stream(1), sender_config);
626 VerifyLogStartEvent(parsed_stream.stream(2));
627 VerifyRtpEvent(parsed_stream.stream(3), true, MediaType::VIDEO,
628 recent_rtp_packet.data(), recent_header_size,
629 recent_rtp_packet.size());
630 VerifyRtcpEvent(parsed_stream.stream(4), false, MediaType::VIDEO,
631 recent_rtcp_packet.data(), recent_rtcp_packet.size());
632
633 // Clean up temporary file - can be pretty slow.
634 remove(temp_filename.c_str());
635}
636
637TEST(RtcEventLogTest, DropOldEvents) {
638 // Enable all header extensions
639 uint32_t extensions = (1u << kNumExtensions) - 1;
640 uint32_t csrcs_count = 2;
641 DropOldEvents(extensions, csrcs_count, 141421356);
642 DropOldEvents(extensions, csrcs_count, 173205080);
643}
644
Bjorn Terelius36411852015-07-30 12:45:18 +0200645} // namespace webrtc
646
647#endif // ENABLE_RTC_EVENT_LOG