1 /*
2 * Copyright (c) 2017 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 #include <cmath>
12 #include <limits>
13 #include <memory>
14 #include <string>
15 #include <utility>
16
17 #include "api/rtpparameters.h" // RtpExtension
18 #include "logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h"
19 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
20 #include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
21 #include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
22 #include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
23 #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
24 #include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
25 #include "logging/rtc_event_log/events/rtc_event_logging_started.h"
26 #include "logging/rtc_event_log/events/rtc_event_logging_stopped.h"
27 #include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
28 #include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
29 #include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
30 #include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
31 #include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
32 #include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
33 #include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
34 #include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
35 #include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
36 #include "logging/rtc_event_log/rtc_event_log_parser.h"
37 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
38 #include "modules/remote_bitrate_estimator/include/bwe_defines.h"
39 #include "modules/rtp_rtcp/source/rtcp_packet/bye.h" // Arbitrary RTCP message.
40 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
41 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
42 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
43 #include "rtc_base/arraysize.h"
44 #include "rtc_base/numerics/safe_conversions.h"
45 #include "rtc_base/ptr_util.h"
46 #include "rtc_base/random.h"
47 #include "test/gtest.h"
48
49 namespace webrtc {
50
51 namespace {
52 struct ExtensionInfo {
53 RTPExtensionType type;
54 const char* uri;
55 };
56
57 template <typename Extension>
CreateExtensionInfo()58 constexpr ExtensionInfo CreateExtensionInfo() {
59 return {Extension::kId, Extension::kUri};
60 }
61
62 constexpr ExtensionInfo kExtensions[] = {
63 CreateExtensionInfo<TransmissionOffset>(),
64 CreateExtensionInfo<AudioLevel>(),
65 CreateExtensionInfo<AbsoluteSendTime>(),
66 CreateExtensionInfo<VideoOrientation>(),
67 CreateExtensionInfo<TransportSequenceNumber>(),
68 CreateExtensionInfo<PlayoutDelayLimits>(),
69 CreateExtensionInfo<VideoContentTypeExtension>(),
70 CreateExtensionInfo<VideoTimingExtension>(),
71 CreateExtensionInfo<RtpStreamId>(),
72 CreateExtensionInfo<RepairedRtpStreamId>(),
73 CreateExtensionInfo<RtpMid>(),
74 };
75 } // namespace
76
77 class RtcEventLogEncoderTest : public testing::TestWithParam<int> {
78 protected:
RtcEventLogEncoderTest()79 RtcEventLogEncoderTest()
80 : encoder_(new RtcEventLogEncoderLegacy), prng_(GetParam()) {}
81 ~RtcEventLogEncoderTest() override = default;
82
83 // ANA events have some optional fields, so we want to make sure that we get
84 // correct behavior both when all of the values are there, as well as when
85 // only some.
86 void TestRtcEventAudioNetworkAdaptation(
87 std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config);
88
89 // These help prevent code duplication between incoming/outgoing variants.
90 void TestRtcEventRtcpPacket(PacketDirection direction);
91 void TestRtcEventRtpPacket(PacketDirection direction);
92
RandomInt()93 int RandomInt() {
94 // Don't run this on a SNES.
95 static_assert(8 * sizeof(int) >= 32, "Don't run this on a SNES.");
96 int32_t rand = prng_.Rand(0, std::numeric_limits<int32_t>::max());
97 return rtc::saturated_cast<int>(rand);
98 }
99
RandomPositiveInt()100 int RandomPositiveInt() {
101 int32_t rand = prng_.Rand(1, std::numeric_limits<int32_t>::max());
102 return rtc::saturated_cast<int>(rand);
103 }
104
RandomSsrc()105 uint32_t RandomSsrc() {
106 return prng_.Rand(std::numeric_limits<uint32_t>::max());
107 }
108
RandomRtpExtensions()109 std::vector<RtpExtension> RandomRtpExtensions() {
110 RTC_DCHECK(arraysize(kExtensions) >= 2);
111 size_t id_1 = prng_.Rand(0u, arraysize(kExtensions) - 1);
112 size_t id_2 = prng_.Rand(0u, arraysize(kExtensions) - 2);
113 if (id_2 == id_1)
114 id_2 = arraysize(kExtensions) - 1;
115 return std::vector<RtpExtension>{
116 RtpExtension(kExtensions[id_1].uri, kExtensions[id_1].type),
117 RtpExtension(kExtensions[id_2].uri, kExtensions[id_2].type)};
118 }
119
RandomBitrate()120 int RandomBitrate() { return RandomInt(); }
121
122 // TODO(eladalon): Once we have more than once possible encoder, parameterize
123 // encoder selection.
124 std::unique_ptr<RtcEventLogEncoder> encoder_;
125 ParsedRtcEventLog parsed_log_;
126 Random prng_;
127 };
128
TestRtcEventAudioNetworkAdaptation(std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config)129 void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
130 std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config) {
131 auto original_runtime_config = *runtime_config;
132 auto event = rtc::MakeUnique<RtcEventAudioNetworkAdaptation>(
133 std::move(runtime_config));
134 const int64_t timestamp_us = event->timestamp_us_;
135
136 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
137 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
138 ASSERT_EQ(parsed_log_.GetEventType(0),
139 ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT);
140
141 AudioEncoderRuntimeConfig parsed_runtime_config;
142 parsed_log_.GetAudioNetworkAdaptation(0, &parsed_runtime_config);
143
144 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
145 EXPECT_EQ(parsed_runtime_config, original_runtime_config);
146 }
147
TEST_P(RtcEventLogEncoderTest,RtcEventAudioNetworkAdaptationBitrate)148 TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationBitrate) {
149 auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
150 const int bitrate_bps = RandomBitrate();
151 runtime_config->bitrate_bps = bitrate_bps;
152 TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
153 }
154
TEST_P(RtcEventLogEncoderTest,RtcEventAudioNetworkAdaptationFrameLength)155 TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFrameLength) {
156 auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
157 const int frame_length_ms = prng_.Rand(1, 1000);
158 runtime_config->frame_length_ms = frame_length_ms;
159 TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
160 }
161
TEST_P(RtcEventLogEncoderTest,RtcEventAudioNetworkAdaptationPacketLoss)162 TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationPacketLoss) {
163 // To simplify the test, we just check powers of two.
164 const float plr = std::pow(0.5f, prng_.Rand(1, 8));
165 auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
166 runtime_config->uplink_packet_loss_fraction = plr;
167 TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
168 }
169
TEST_P(RtcEventLogEncoderTest,RtcEventAudioNetworkAdaptationFec)170 TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFec) {
171 // The test might be trivially passing for one of the two boolean values, so
172 // for safety's sake, we test both.
173 for (bool fec_enabled : {false, true}) {
174 auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
175 runtime_config->enable_fec = fec_enabled;
176 TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
177 }
178 }
179
TEST_P(RtcEventLogEncoderTest,RtcEventAudioNetworkAdaptationDtx)180 TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationDtx) {
181 // The test might be trivially passing for one of the two boolean values, so
182 // for safety's sake, we test both.
183 for (bool dtx_enabled : {false, true}) {
184 auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
185 runtime_config->enable_dtx = dtx_enabled;
186 TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
187 }
188 }
189
TEST_P(RtcEventLogEncoderTest,RtcEventAudioNetworkAdaptationChannels)190 TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationChannels) {
191 // The test might be trivially passing for one of the two possible values, so
192 // for safety's sake, we test both.
193 for (size_t channels : {1, 2}) {
194 auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
195 runtime_config->num_channels = channels;
196 TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
197 }
198 }
199
TEST_P(RtcEventLogEncoderTest,RtcEventAudioNetworkAdaptationAll)200 TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationAll) {
201 const int bitrate_bps = RandomBitrate();
202 const int frame_length_ms = prng_.Rand(1, 1000);
203 const float plr = std::pow(0.5f, prng_.Rand(1, 8));
204 for (bool fec_enabled : {false, true}) {
205 for (bool dtx_enabled : {false, true}) {
206 for (size_t channels : {1, 2}) {
207 auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
208 runtime_config->bitrate_bps = bitrate_bps;
209 runtime_config->frame_length_ms = frame_length_ms;
210 runtime_config->uplink_packet_loss_fraction = plr;
211 runtime_config->enable_fec = fec_enabled;
212 runtime_config->enable_dtx = dtx_enabled;
213 runtime_config->num_channels = channels;
214
215 TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
216 }
217 }
218 }
219 }
220
TEST_P(RtcEventLogEncoderTest,RtcEventAudioPlayout)221 TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
222 const uint32_t ssrc = RandomSsrc();
223 auto event = rtc::MakeUnique<RtcEventAudioPlayout>(ssrc);
224 const int64_t timestamp_us = event->timestamp_us_;
225
226 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
227 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
228 ASSERT_EQ(parsed_log_.GetEventType(0),
229 ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT);
230
231 uint32_t parsed_ssrc;
232 parsed_log_.GetAudioPlayout(0, &parsed_ssrc);
233
234 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
235 EXPECT_EQ(parsed_ssrc, ssrc);
236 }
237
TEST_P(RtcEventLogEncoderTest,RtcEventAudioReceiveStreamConfig)238 TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
239 auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
240 stream_config->local_ssrc = RandomSsrc();
241 stream_config->remote_ssrc = RandomSsrc();
242 // TODO(eladalon): Verify that the extensions are used correctly when
243 // parsing RTP packets headers. Here and elsewhere.
244 std::vector<RtpExtension> extensions = RandomRtpExtensions();
245 for (const auto& extension : extensions)
246 stream_config->rtp_extensions.push_back(extension);
247
248 auto original_stream_config = *stream_config;
249
250 auto event = rtc::MakeUnique<RtcEventAudioReceiveStreamConfig>(
251 std::move(stream_config));
252 const int64_t timestamp_us = event->timestamp_us_;
253
254 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
255 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
256 ASSERT_EQ(parsed_log_.GetEventType(0),
257 ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT);
258
259 auto parsed_event = parsed_log_.GetAudioReceiveConfig(0);
260 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
261 EXPECT_EQ(parsed_event, original_stream_config);
262 }
263
TEST_P(RtcEventLogEncoderTest,RtcEventAudioSendStreamConfig)264 TEST_P(RtcEventLogEncoderTest, RtcEventAudioSendStreamConfig) {
265 auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
266 stream_config->local_ssrc = RandomSsrc();
267 std::vector<RtpExtension> extensions = RandomRtpExtensions();
268 for (const auto& extension : extensions)
269 stream_config->rtp_extensions.push_back(extension);
270
271 auto original_stream_config = *stream_config;
272
273 auto event =
274 rtc::MakeUnique<RtcEventAudioSendStreamConfig>(std::move(stream_config));
275 const int64_t timestamp_us = event->timestamp_us_;
276
277 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
278 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
279 ASSERT_EQ(parsed_log_.GetEventType(0),
280 ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT);
281
282 auto parsed_event = parsed_log_.GetAudioSendConfig(0);
283 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
284 EXPECT_EQ(parsed_event, original_stream_config);
285 }
286
TEST_P(RtcEventLogEncoderTest,RtcEventBweUpdateDelayBased)287 TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
288 const int32_t bitrate_bps = RandomBitrate();
289 const BandwidthUsage detector_state = static_cast<BandwidthUsage>(
290 prng_.Rand(0, static_cast<int32_t>(BandwidthUsage::kLast) - 1));
291 auto event =
292 rtc::MakeUnique<RtcEventBweUpdateDelayBased>(bitrate_bps, detector_state);
293 const int64_t timestamp_us = event->timestamp_us_;
294
295 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
296 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
297 ASSERT_EQ(parsed_log_.GetEventType(0),
298 ParsedRtcEventLog::DELAY_BASED_BWE_UPDATE);
299
300 auto parsed_event = parsed_log_.GetDelayBasedBweUpdate(0);
301
302 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
303 EXPECT_EQ(parsed_event.bitrate_bps, bitrate_bps);
304 EXPECT_EQ(parsed_event.detector_state, detector_state);
305 }
306
TEST_P(RtcEventLogEncoderTest,RtcEventBweUpdateLossBased)307 TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
308 const int32_t bitrate_bps = RandomBitrate();
309 const uint8_t fraction_loss = rtc::dchecked_cast<uint8_t>(
310 prng_.Rand(0, std::numeric_limits<uint8_t>::max()));
311 const int32_t total_packets = RandomInt();
312
313 auto event = rtc::MakeUnique<RtcEventBweUpdateLossBased>(
314 bitrate_bps, fraction_loss, total_packets);
315 const int64_t timestamp_us = event->timestamp_us_;
316
317 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
318 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
319 ASSERT_EQ(parsed_log_.GetEventType(0),
320 ParsedRtcEventLog::LOSS_BASED_BWE_UPDATE);
321
322 int32_t parsed_bitrate_bps;
323 uint8_t parsed_fraction_loss;
324 int32_t parsed_total_packets;
325 parsed_log_.GetLossBasedBweUpdate(
326 0, &parsed_bitrate_bps, &parsed_fraction_loss, &parsed_total_packets);
327
328 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
329 EXPECT_EQ(parsed_bitrate_bps, bitrate_bps);
330 EXPECT_EQ(parsed_fraction_loss, fraction_loss);
331 EXPECT_EQ(parsed_total_packets, total_packets);
332 }
333
TEST_P(RtcEventLogEncoderTest,RtcEventLoggingStarted)334 TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
335 auto event = rtc::MakeUnique<RtcEventLoggingStarted>();
336 const int64_t timestamp_us = event->timestamp_us_;
337
338 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
339 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
340 ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::LOG_START);
341
342 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
343 }
344
TEST_P(RtcEventLogEncoderTest,RtcEventLoggingStopped)345 TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
346 auto event = rtc::MakeUnique<RtcEventLoggingStopped>();
347 const int64_t timestamp_us = event->timestamp_us_;
348
349 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
350 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
351 ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::LOG_END);
352
353 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
354 }
355
TEST_P(RtcEventLogEncoderTest,RtcEventProbeClusterCreated)356 TEST_P(RtcEventLogEncoderTest, RtcEventProbeClusterCreated) {
357 const int id = RandomPositiveInt();
358 const int bitrate_bps = RandomBitrate();
359 const int min_probes = RandomPositiveInt();
360 const int min_bytes = RandomPositiveInt();
361
362 auto event = rtc::MakeUnique<RtcEventProbeClusterCreated>(
363 id, bitrate_bps, min_probes, min_bytes);
364 const int64_t timestamp_us = event->timestamp_us_;
365
366 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
367 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
368 ASSERT_EQ(parsed_log_.GetEventType(0),
369 ParsedRtcEventLog::BWE_PROBE_CLUSTER_CREATED_EVENT);
370
371 auto parsed_event = parsed_log_.GetBweProbeClusterCreated(0);
372
373 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
374 EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.id), id);
375 EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.bitrate_bps), bitrate_bps);
376 EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.min_packets), min_probes);
377 EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.min_bytes), min_bytes);
378 }
379
TEST_P(RtcEventLogEncoderTest,RtcEventProbeResultFailure)380 TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultFailure) {
381 const int id = RandomPositiveInt();
382 const ProbeFailureReason failure_reason = static_cast<ProbeFailureReason>(
383 prng_.Rand(0, static_cast<int32_t>(ProbeFailureReason::kLast) - 1));
384
385 auto event = rtc::MakeUnique<RtcEventProbeResultFailure>(id, failure_reason);
386 const int64_t timestamp_us = event->timestamp_us_;
387
388 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
389 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
390 ASSERT_EQ(parsed_log_.GetEventType(0),
391 ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT);
392
393 auto parsed_event = parsed_log_.GetBweProbeResult(0);
394
395 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
396 EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.id), id);
397 ASSERT_FALSE(parsed_event.bitrate_bps);
398 ASSERT_TRUE(parsed_event.failure_reason);
399 EXPECT_EQ(parsed_event.failure_reason, failure_reason);
400 }
401
TEST_P(RtcEventLogEncoderTest,RtcEventProbeResultSuccess)402 TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultSuccess) {
403 const int id = RandomPositiveInt();
404 const int bitrate_bps = RandomBitrate();
405
406 auto event = rtc::MakeUnique<RtcEventProbeResultSuccess>(id, bitrate_bps);
407 const int64_t timestamp_us = event->timestamp_us_;
408
409 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
410 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
411 ASSERT_EQ(parsed_log_.GetEventType(0),
412 ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT);
413
414 auto parsed_event = parsed_log_.GetBweProbeResult(0);
415
416 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
417 EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.id), id);
418 ASSERT_TRUE(parsed_event.bitrate_bps);
419 EXPECT_EQ(parsed_event.bitrate_bps, bitrate_bps);
420 ASSERT_FALSE(parsed_event.failure_reason);
421 }
422
TestRtcEventRtcpPacket(PacketDirection direction)423 void RtcEventLogEncoderTest::TestRtcEventRtcpPacket(PacketDirection direction) {
424 rtcp::Bye bye_packet; // Arbitrarily chosen RTCP packet type.
425 bye_packet.SetReason("a man's reach should exceed his grasp");
426 auto rtcp_packet = bye_packet.Build();
427
428 std::unique_ptr<RtcEvent> event;
429 if (direction == PacketDirection::kIncomingPacket) {
430 event = rtc::MakeUnique<RtcEventRtcpPacketIncoming>(rtcp_packet);
431 } else {
432 event = rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(rtcp_packet);
433 }
434 const int64_t timestamp_us = event->timestamp_us_;
435
436 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
437 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
438 ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::RTCP_EVENT);
439
440 PacketDirection parsed_direction;
441 uint8_t parsed_packet[IP_PACKET_SIZE]; // "Parsed" = after event-encoding.
442 size_t parsed_packet_length;
443 parsed_log_.GetRtcpPacket(0, &parsed_direction, parsed_packet,
444 &parsed_packet_length);
445
446 EXPECT_EQ(parsed_direction, direction);
447 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
448 ASSERT_EQ(parsed_packet_length, rtcp_packet.size());
449 ASSERT_EQ(memcmp(parsed_packet, rtcp_packet.data(), parsed_packet_length), 0);
450 }
451
TEST_P(RtcEventLogEncoderTest,RtcEventRtcpPacketIncoming)452 TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
453 TestRtcEventRtcpPacket(PacketDirection::kIncomingPacket);
454 }
455
TEST_P(RtcEventLogEncoderTest,RtcEventRtcpPacketOutgoing)456 TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketOutgoing) {
457 TestRtcEventRtcpPacket(PacketDirection::kOutgoingPacket);
458 }
459
TestRtcEventRtpPacket(PacketDirection direction)460 void RtcEventLogEncoderTest::TestRtcEventRtpPacket(PacketDirection direction) {
461 const int probe_cluster_id = RandomPositiveInt();
462
463 std::unique_ptr<RtpPacketReceived> packet_received;
464 std::unique_ptr<RtpPacketToSend> packet_to_send;
465 RtpPacket* packet;
466 if (direction == PacketDirection::kIncomingPacket) {
467 packet_received = rtc::MakeUnique<RtpPacketReceived>();
468 packet = packet_received.get();
469 } else {
470 packet_to_send = rtc::MakeUnique<RtpPacketToSend>(nullptr);
471 packet = packet_to_send.get();
472 }
473 packet->SetSsrc(RandomSsrc());
474 packet->SetSequenceNumber(static_cast<uint16_t>(RandomInt()));
475 packet->SetPayloadSize(prng_.Rand(0u, 1000u));
476 // TODO(terelius): Add marker bit, capture timestamp, CSRCs, and header
477 // extensions.
478
479 std::unique_ptr<RtcEvent> event;
480 if (direction == PacketDirection::kIncomingPacket) {
481 event = rtc::MakeUnique<RtcEventRtpPacketIncoming>(*packet_received);
482 } else {
483 event = rtc::MakeUnique<RtcEventRtpPacketOutgoing>(*packet_to_send,
484 probe_cluster_id);
485 }
486 const int64_t timestamp_us = event->timestamp_us_;
487
488 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
489 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
490 ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::RTP_EVENT);
491
492 PacketDirection parsed_direction;
493 uint8_t parsed_rtp_header[IP_PACKET_SIZE];
494 size_t parsed_header_length;
495 size_t parsed_total_length;
496 int parsed_probe_cluster_id;
497 parsed_log_.GetRtpHeader(0, &parsed_direction, parsed_rtp_header,
498 &parsed_header_length, &parsed_total_length,
499 &parsed_probe_cluster_id);
500
501 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
502 EXPECT_EQ(parsed_direction, direction);
503 if (parsed_direction == PacketDirection::kOutgoingPacket) {
504 EXPECT_EQ(parsed_probe_cluster_id, probe_cluster_id);
505 }
506 EXPECT_EQ(memcmp(parsed_rtp_header, packet->data(), parsed_header_length), 0);
507 EXPECT_EQ(parsed_header_length, packet->headers_size());
508 EXPECT_EQ(parsed_total_length, packet->size());
509 }
510
TEST_P(RtcEventLogEncoderTest,RtcEventRtpPacketIncoming)511 TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketIncoming) {
512 TestRtcEventRtpPacket(PacketDirection::kIncomingPacket);
513 }
514
TEST_P(RtcEventLogEncoderTest,RtcEventRtpPacketOutgoing)515 TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketOutgoing) {
516 TestRtcEventRtpPacket(PacketDirection::kOutgoingPacket);
517 }
518
TEST_P(RtcEventLogEncoderTest,RtcEventVideoReceiveStreamConfig)519 TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
520 auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
521 stream_config->local_ssrc = RandomSsrc();
522 stream_config->remote_ssrc = RandomSsrc();
523 stream_config->rtcp_mode = RtcpMode::kCompound;
524 stream_config->remb = prng_.Rand<bool>();
525 std::vector<RtpExtension> extensions = RandomRtpExtensions();
526 for (const auto& extension : extensions)
527 stream_config->rtp_extensions.push_back(extension);
528 stream_config->codecs.emplace_back("CODEC", 122, 7);
529
530 auto original_stream_config = *stream_config;
531
532 auto event = rtc::MakeUnique<RtcEventVideoReceiveStreamConfig>(
533 std::move(stream_config));
534 const int64_t timestamp_us = event->timestamp_us_;
535
536 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
537 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
538 ASSERT_EQ(parsed_log_.GetEventType(0),
539 ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT);
540
541 auto parsed_event = parsed_log_.GetVideoReceiveConfig(0);
542 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
543 EXPECT_EQ(parsed_event, original_stream_config);
544 }
545
TEST_P(RtcEventLogEncoderTest,RtcEventVideoSendStreamConfig)546 TEST_P(RtcEventLogEncoderTest, RtcEventVideoSendStreamConfig) {
547 auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
548 stream_config->local_ssrc = RandomSsrc();
549 std::vector<RtpExtension> extensions = RandomRtpExtensions();
550 for (const auto& extension : extensions)
551 stream_config->rtp_extensions.push_back(extension);
552 stream_config->codecs.emplace_back("CODEC", 120, 3);
553
554 auto original_stream_config = *stream_config;
555
556 auto event =
557 rtc::MakeUnique<RtcEventVideoSendStreamConfig>(std::move(stream_config));
558 const int64_t timestamp_us = event->timestamp_us_;
559
560 ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
561 ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
562 ASSERT_EQ(parsed_log_.GetEventType(0),
563 ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT);
564
565 auto parsed_event = parsed_log_.GetVideoSendConfig(0)[0];
566 EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
567 EXPECT_EQ(parsed_event, original_stream_config);
568 }
569
570 INSTANTIATE_TEST_CASE_P(RandomSeeds,
571 RtcEventLogEncoderTest,
572 ::testing::Values(1, 2, 3, 4, 5));
573
574 } // namespace webrtc
575