/* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "logging/rtc_event_log/rtc_event_log_unittest_helper.h" #include // memcmp #include #include #include #include #include #include #include "absl/types/optional.h" #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "modules/rtp_rtcp/include/rtp_cvo.h" #include "modules/rtp_rtcp/source/rtp_header_extensions.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "rtc_base/checks.h" #include "test/gtest.h" namespace webrtc { namespace test { namespace { struct ExtensionPair { RTPExtensionType type; const char* name; }; constexpr int kMaxCsrcs = 3; // Maximum serialized size of a header extension, including 1 byte ID. constexpr int kMaxExtensionSizeBytes = 4; constexpr int kMaxNumExtensions = 5; constexpr ExtensionPair kExtensions[kMaxNumExtensions] = { {RTPExtensionType::kRtpExtensionTransmissionTimeOffset, RtpExtension::kTimestampOffsetUri}, {RTPExtensionType::kRtpExtensionAbsoluteSendTime, RtpExtension::kAbsSendTimeUri}, {RTPExtensionType::kRtpExtensionTransportSequenceNumber, RtpExtension::kTransportSequenceNumberUri}, {RTPExtensionType::kRtpExtensionAudioLevel, RtpExtension::kAudioLevelUri}, {RTPExtensionType::kRtpExtensionVideoRotation, RtpExtension::kVideoRotationUri}}; template void ShuffleInPlace(Random* prng, rtc::ArrayView array) { RTC_DCHECK_LE(array.size(), std::numeric_limits::max()); for (uint32_t i = 0; i + 1 < array.size(); i++) { uint32_t other = prng->Rand(i, static_cast(array.size() - 1)); std::swap(array[i], array[other]); } } absl::optional GetExtensionId(const std::vector& extensions, const std::string& uri) { for (const auto& extension : extensions) { if (extension.uri == uri) return extension.id; } return absl::nullopt; } } // namespace std::unique_ptr EventGenerator::NewAlrState() { return absl::make_unique(prng_.Rand()); } std::unique_ptr EventGenerator::NewAudioPlayout( uint32_t ssrc) { return absl::make_unique(ssrc); } std::unique_ptr EventGenerator::NewAudioNetworkAdaptation() { std::unique_ptr config = absl::make_unique(); config->bitrate_bps = prng_.Rand(0, 3000000); config->enable_fec = prng_.Rand(); config->enable_dtx = prng_.Rand(); config->frame_length_ms = prng_.Rand(10, 120); config->num_channels = prng_.Rand(1, 2); config->uplink_packet_loss_fraction = prng_.Rand(); return absl::make_unique(std::move(config)); } std::unique_ptr EventGenerator::NewBweUpdateDelayBased() { constexpr int32_t kMaxBweBps = 20000000; int32_t bitrate_bps = prng_.Rand(0, kMaxBweBps); BandwidthUsage state = static_cast( prng_.Rand(static_cast(BandwidthUsage::kLast) - 1)); return absl::make_unique(bitrate_bps, state); } std::unique_ptr EventGenerator::NewBweUpdateLossBased() { constexpr int32_t kMaxBweBps = 20000000; constexpr int32_t kMaxPackets = 1000; int32_t bitrate_bps = prng_.Rand(0, kMaxBweBps); uint8_t fraction_lost = prng_.Rand(); int32_t total_packets = prng_.Rand(1, kMaxPackets); return absl::make_unique( bitrate_bps, fraction_lost, total_packets); } std::unique_ptr EventGenerator::NewProbeClusterCreated() { constexpr int kMaxBweBps = 20000000; constexpr int kMaxNumProbes = 10000; int id = prng_.Rand(1, kMaxNumProbes); int bitrate_bps = prng_.Rand(0, kMaxBweBps); int min_probes = prng_.Rand(5, 50); int min_bytes = prng_.Rand(500, 50000); return absl::make_unique(id, bitrate_bps, min_probes, min_bytes); } std::unique_ptr EventGenerator::NewProbeResultFailure() { constexpr int kMaxNumProbes = 10000; int id = prng_.Rand(1, kMaxNumProbes); ProbeFailureReason reason = static_cast( prng_.Rand(static_cast(ProbeFailureReason::kLast) - 1)); return absl::make_unique(id, reason); } std::unique_ptr EventGenerator::NewProbeResultSuccess() { constexpr int kMaxBweBps = 20000000; constexpr int kMaxNumProbes = 10000; int id = prng_.Rand(1, kMaxNumProbes); int bitrate_bps = prng_.Rand(0, kMaxBweBps); return absl::make_unique(id, bitrate_bps); } std::unique_ptr EventGenerator::NewIceCandidatePairConfig() { IceCandidateType local_candidate_type = static_cast( prng_.Rand(static_cast(IceCandidateType::kNumValues) - 1)); IceCandidateNetworkType local_network_type = static_cast(prng_.Rand( static_cast(IceCandidateNetworkType::kNumValues) - 1)); IceCandidatePairAddressFamily local_address_family = static_cast(prng_.Rand( static_cast(IceCandidatePairAddressFamily::kNumValues) - 1)); IceCandidateType remote_candidate_type = static_cast( prng_.Rand(static_cast(IceCandidateType::kNumValues) - 1)); IceCandidatePairAddressFamily remote_address_family = static_cast(prng_.Rand( static_cast(IceCandidatePairAddressFamily::kNumValues) - 1)); IceCandidatePairProtocol protocol_type = static_cast(prng_.Rand( static_cast(IceCandidatePairProtocol::kNumValues) - 1)); IceCandidatePairDescription desc; desc.local_candidate_type = local_candidate_type; desc.local_relay_protocol = protocol_type; desc.local_network_type = local_network_type; desc.local_address_family = local_address_family; desc.remote_candidate_type = remote_candidate_type; desc.remote_address_family = remote_address_family; desc.candidate_pair_protocol = protocol_type; IceCandidatePairConfigType type = static_cast(prng_.Rand( static_cast(IceCandidatePairConfigType::kNumValues) - 1)); uint32_t pair_id = prng_.Rand(); return absl::make_unique(type, pair_id, desc); } std::unique_ptr EventGenerator::NewIceCandidatePair() { IceCandidatePairEventType type = static_cast(prng_.Rand( static_cast(IceCandidatePairEventType::kNumValues) - 1)); uint32_t pair_id = prng_.Rand(); return absl::make_unique(type, pair_id); } rtcp::ReportBlock EventGenerator::NewReportBlock() { rtcp::ReportBlock report_block; report_block.SetMediaSsrc(prng_.Rand()); report_block.SetFractionLost(prng_.Rand()); // cumulative_lost is a 3-byte signed value. RTC_DCHECK(report_block.SetCumulativeLost( prng_.Rand(-(1 << 23) + 1, (1 << 23) - 1))); report_block.SetExtHighestSeqNum(prng_.Rand()); report_block.SetJitter(prng_.Rand()); report_block.SetLastSr(prng_.Rand()); report_block.SetDelayLastSr(prng_.Rand()); return report_block; } rtcp::SenderReport EventGenerator::NewSenderReport() { rtcp::SenderReport sender_report; sender_report.SetSenderSsrc(prng_.Rand()); sender_report.SetNtp(NtpTime(prng_.Rand(), prng_.Rand())); sender_report.SetPacketCount(prng_.Rand()); sender_report.AddReportBlock(NewReportBlock()); return sender_report; } rtcp::ReceiverReport EventGenerator::NewReceiverReport() { rtcp::ReceiverReport receiver_report; receiver_report.SetSenderSsrc(prng_.Rand()); receiver_report.AddReportBlock(NewReportBlock()); return receiver_report; } std::unique_ptr EventGenerator::NewRtcpPacketIncoming() { // TODO(terelius): Test the other RTCP types too. switch (prng_.Rand(0, 1)) { case 0: { rtcp::SenderReport sender_report = NewSenderReport(); rtc::Buffer buffer = sender_report.Build(); return absl::make_unique(buffer); } case 1: { rtcp::ReceiverReport receiver_report = NewReceiverReport(); rtc::Buffer buffer = receiver_report.Build(); return absl::make_unique(buffer); } default: RTC_NOTREACHED(); rtc::Buffer buffer; return absl::make_unique(buffer); } } std::unique_ptr EventGenerator::NewRtcpPacketOutgoing() { // TODO(terelius): Test the other RTCP types too. switch (prng_.Rand(0, 1)) { case 0: { rtcp::SenderReport sender_report = NewSenderReport(); rtc::Buffer buffer = sender_report.Build(); return absl::make_unique(buffer); } case 1: { rtcp::ReceiverReport receiver_report = NewReceiverReport(); rtc::Buffer buffer = receiver_report.Build(); return absl::make_unique(buffer); } default: RTC_NOTREACHED(); rtc::Buffer buffer; return absl::make_unique(buffer); } } void EventGenerator::RandomizeRtpPacket( size_t payload_size, size_t padding_size, uint32_t ssrc, const RtpHeaderExtensionMap& extension_map, RtpPacket* rtp_packet) { constexpr int kMaxPayloadType = 127; rtp_packet->SetPayloadType(prng_.Rand(kMaxPayloadType)); rtp_packet->SetMarker(prng_.Rand()); rtp_packet->SetSequenceNumber(prng_.Rand()); rtp_packet->SetSsrc(ssrc); rtp_packet->SetTimestamp(prng_.Rand()); uint32_t csrcs_count = prng_.Rand(0, kMaxCsrcs); std::vector csrcs; for (size_t i = 0; i < csrcs_count; i++) { csrcs.push_back(prng_.Rand()); } rtp_packet->SetCsrcs(csrcs); if (extension_map.IsRegistered(TransmissionOffset::kId)) rtp_packet->SetExtension(prng_.Rand(0x00ffffff)); if (extension_map.IsRegistered(AudioLevel::kId)) rtp_packet->SetExtension(prng_.Rand(), prng_.Rand(127)); if (extension_map.IsRegistered(AbsoluteSendTime::kId)) rtp_packet->SetExtension(prng_.Rand(0x00ffffff)); if (extension_map.IsRegistered(VideoOrientation::kId)) rtp_packet->SetExtension(prng_.Rand(3)); if (extension_map.IsRegistered(TransportSequenceNumber::kId)) rtp_packet->SetExtension(prng_.Rand()); RTC_CHECK_LE(rtp_packet->headers_size() + payload_size, IP_PACKET_SIZE); uint8_t* payload = rtp_packet->AllocatePayload(payload_size); RTC_DCHECK(payload != nullptr); for (size_t i = 0; i < payload_size; i++) { payload[i] = prng_.Rand(); } RTC_CHECK(rtp_packet->SetPadding(padding_size)); } std::unique_ptr EventGenerator::NewRtpPacketIncoming( uint32_t ssrc, const RtpHeaderExtensionMap& extension_map) { constexpr size_t kMaxPaddingLength = 224; const bool padding = prng_.Rand(0, 9) == 0; // Let padding be 10% probable. const size_t padding_size = !padding ? 0u : prng_.Rand(0u, kMaxPaddingLength); // 12 bytes RTP header, 4 bytes for 0xBEDE + alignment, 4 bytes per CSRC. constexpr size_t kMaxHeaderSize = 16 + 4 * kMaxCsrcs + kMaxExtensionSizeBytes * kMaxNumExtensions; // In principle, a packet can contain both padding and other payload. // Currently, RTC eventlog encoder-parser can only maintain padding length if // packet is full padding. // TODO(webrtc:9730): Remove the deterministic logic for padding_size > 0. size_t payload_size = padding_size > 0 ? 0 : prng_.Rand(0u, static_cast(IP_PACKET_SIZE - 1 - padding_size - kMaxHeaderSize)); RtpPacketReceived rtp_packet(&extension_map); RandomizeRtpPacket(payload_size, padding_size, ssrc, extension_map, &rtp_packet); return absl::make_unique(rtp_packet); } std::unique_ptr EventGenerator::NewRtpPacketOutgoing( uint32_t ssrc, const RtpHeaderExtensionMap& extension_map) { constexpr size_t kMaxPaddingLength = 224; const bool padding = prng_.Rand(0, 9) == 0; // Let padding be 10% probable. const size_t padding_size = !padding ? 0u : prng_.Rand(0u, kMaxPaddingLength); // 12 bytes RTP header, 4 bytes for 0xBEDE + alignment, 4 bytes per CSRC. constexpr size_t kMaxHeaderSize = 16 + 4 * kMaxCsrcs + kMaxExtensionSizeBytes * kMaxNumExtensions; // In principle,a packet can contain both padding and other payload. // Currently, RTC eventlog encoder-parser can only maintain padding length if // packet is full padding. // TODO(webrtc:9730): Remove the deterministic logic for padding_size > 0. size_t payload_size = padding_size > 0 ? 0 : prng_.Rand(0u, static_cast(IP_PACKET_SIZE - 1 - padding_size - kMaxHeaderSize)); RtpPacketToSend rtp_packet(&extension_map, kMaxHeaderSize + payload_size + padding_size); RandomizeRtpPacket(payload_size, padding_size, ssrc, extension_map, &rtp_packet); int probe_cluster_id = prng_.Rand(0, 100000); return absl::make_unique(rtp_packet, probe_cluster_id); } RtpHeaderExtensionMap EventGenerator::NewRtpHeaderExtensionMap() { RtpHeaderExtensionMap extension_map; std::vector id(RtpExtension::kOneByteHeaderExtensionMaxId - RtpExtension::kMinId + 1); std::iota(id.begin(), id.end(), RtpExtension::kMinId); ShuffleInPlace(&prng_, rtc::ArrayView(id)); if (prng_.Rand()) { extension_map.Register(id[0]); } if (prng_.Rand()) { extension_map.Register(id[1]); } if (prng_.Rand()) { extension_map.Register(id[2]); } if (prng_.Rand()) { extension_map.Register(id[3]); } if (prng_.Rand()) { extension_map.Register(id[4]); } return extension_map; } std::unique_ptr EventGenerator::NewAudioReceiveStreamConfig( uint32_t ssrc, const RtpHeaderExtensionMap& extensions) { auto config = absl::make_unique(); // Add SSRCs for the stream. config->remote_ssrc = ssrc; config->local_ssrc = prng_.Rand(); // Add header extensions. for (size_t i = 0; i < kMaxNumExtensions; i++) { uint8_t id = extensions.GetId(kExtensions[i].type); if (id != RtpHeaderExtensionMap::kInvalidId) { config->rtp_extensions.emplace_back(kExtensions[i].name, id); } } return absl::make_unique(std::move(config)); } std::unique_ptr EventGenerator::NewAudioSendStreamConfig( uint32_t ssrc, const RtpHeaderExtensionMap& extensions) { auto config = absl::make_unique(); // Add SSRC to the stream. config->local_ssrc = ssrc; // Add header extensions. for (size_t i = 0; i < kMaxNumExtensions; i++) { uint8_t id = extensions.GetId(kExtensions[i].type); if (id != RtpHeaderExtensionMap::kInvalidId) { config->rtp_extensions.emplace_back(kExtensions[i].name, id); } } return absl::make_unique(std::move(config)); } std::unique_ptr EventGenerator::NewVideoReceiveStreamConfig( uint32_t ssrc, const RtpHeaderExtensionMap& extensions) { auto config = absl::make_unique(); // Add SSRCs for the stream. config->remote_ssrc = ssrc; config->local_ssrc = prng_.Rand(); // Add extensions and settings for RTCP. config->rtcp_mode = prng_.Rand() ? RtcpMode::kCompound : RtcpMode::kReducedSize; config->remb = prng_.Rand(); config->rtx_ssrc = prng_.Rand(); config->codecs.emplace_back(prng_.Rand() ? "VP8" : "H264", prng_.Rand(127), prng_.Rand(127)); // Add header extensions. for (size_t i = 0; i < kMaxNumExtensions; i++) { uint8_t id = extensions.GetId(kExtensions[i].type); if (id != RtpHeaderExtensionMap::kInvalidId) { config->rtp_extensions.emplace_back(kExtensions[i].name, id); } } return absl::make_unique(std::move(config)); } std::unique_ptr EventGenerator::NewVideoSendStreamConfig( uint32_t ssrc, const RtpHeaderExtensionMap& extensions) { auto config = absl::make_unique(); config->codecs.emplace_back(prng_.Rand() ? "VP8" : "H264", prng_.Rand(127), prng_.Rand(127)); config->local_ssrc = ssrc; config->rtx_ssrc = prng_.Rand(); // Add header extensions. for (size_t i = 0; i < kMaxNumExtensions; i++) { uint8_t id = extensions.GetId(kExtensions[i].type); if (id != RtpHeaderExtensionMap::kInvalidId) { config->rtp_extensions.emplace_back(kExtensions[i].name, id); } } return absl::make_unique(std::move(config)); } void VerifyLoggedAlrStateEvent(const RtcEventAlrState& original_event, const LoggedAlrStateEvent& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.in_alr_, logged_event.in_alr); } void VerifyLoggedAudioPlayoutEvent( const RtcEventAudioPlayout& original_event, const LoggedAudioPlayoutEvent& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.ssrc_, logged_event.ssrc); } void VerifyLoggedAudioNetworkAdaptationEvent( const RtcEventAudioNetworkAdaptation& original_event, const LoggedAudioNetworkAdaptationEvent& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.config_->bitrate_bps, logged_event.config.bitrate_bps); EXPECT_EQ(original_event.config_->enable_dtx, logged_event.config.enable_dtx); EXPECT_EQ(original_event.config_->enable_fec, logged_event.config.enable_fec); EXPECT_EQ(original_event.config_->frame_length_ms, logged_event.config.frame_length_ms); EXPECT_EQ(original_event.config_->num_channels, logged_event.config.num_channels); EXPECT_EQ(original_event.config_->uplink_packet_loss_fraction, logged_event.config.uplink_packet_loss_fraction); } void VerifyLoggedBweDelayBasedUpdate( const RtcEventBweUpdateDelayBased& original_event, const LoggedBweDelayBasedUpdate& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.bitrate_bps_, logged_event.bitrate_bps); EXPECT_EQ(original_event.detector_state_, logged_event.detector_state); } void VerifyLoggedBweLossBasedUpdate( const RtcEventBweUpdateLossBased& original_event, const LoggedBweLossBasedUpdate& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.bitrate_bps_, logged_event.bitrate_bps); EXPECT_EQ(original_event.fraction_loss_, logged_event.fraction_lost); EXPECT_EQ(original_event.total_packets_, logged_event.expected_packets); } void VerifyLoggedBweProbeClusterCreatedEvent( const RtcEventProbeClusterCreated& original_event, const LoggedBweProbeClusterCreatedEvent& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.id_, logged_event.id); EXPECT_EQ(original_event.bitrate_bps_, logged_event.bitrate_bps); EXPECT_EQ(original_event.min_probes_, logged_event.min_packets); EXPECT_EQ(original_event.min_bytes_, logged_event.min_bytes); } void VerifyLoggedBweProbeFailureEvent( const RtcEventProbeResultFailure& original_event, const LoggedBweProbeFailureEvent& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.id_, logged_event.id); EXPECT_EQ(original_event.failure_reason_, logged_event.failure_reason); } void VerifyLoggedBweProbeSuccessEvent( const RtcEventProbeResultSuccess& original_event, const LoggedBweProbeSuccessEvent& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.id_, logged_event.id); EXPECT_EQ(original_event.bitrate_bps_, logged_event.bitrate_bps); } void VerifyLoggedIceCandidatePairConfig( const RtcEventIceCandidatePairConfig& original_event, const LoggedIceCandidatePairConfig& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.type_, logged_event.type); EXPECT_EQ(original_event.candidate_pair_id_, logged_event.candidate_pair_id); EXPECT_EQ(original_event.candidate_pair_desc_.local_candidate_type, logged_event.local_candidate_type); EXPECT_EQ(original_event.candidate_pair_desc_.local_relay_protocol, logged_event.local_relay_protocol); EXPECT_EQ(original_event.candidate_pair_desc_.local_network_type, logged_event.local_network_type); EXPECT_EQ(original_event.candidate_pair_desc_.local_address_family, logged_event.local_address_family); EXPECT_EQ(original_event.candidate_pair_desc_.remote_candidate_type, logged_event.remote_candidate_type); EXPECT_EQ(original_event.candidate_pair_desc_.remote_address_family, logged_event.remote_address_family); EXPECT_EQ(original_event.candidate_pair_desc_.candidate_pair_protocol, logged_event.candidate_pair_protocol); } void VerifyLoggedIceCandidatePairEvent( const RtcEventIceCandidatePair& original_event, const LoggedIceCandidatePairEvent& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.type_, logged_event.type); EXPECT_EQ(original_event.candidate_pair_id_, logged_event.candidate_pair_id); } void VerifyLoggedRtpHeader(const RtpPacket& original_header, const RTPHeader& logged_header) { // Standard RTP header. EXPECT_EQ(original_header.Marker(), logged_header.markerBit); EXPECT_EQ(original_header.PayloadType(), logged_header.payloadType); EXPECT_EQ(original_header.SequenceNumber(), logged_header.sequenceNumber); EXPECT_EQ(original_header.Timestamp(), logged_header.timestamp); EXPECT_EQ(original_header.Ssrc(), logged_header.ssrc); EXPECT_EQ(original_header.headers_size(), logged_header.headerLength); // TransmissionOffset header extension. ASSERT_EQ(original_header.HasExtension(), logged_header.extension.hasTransmissionTimeOffset); if (logged_header.extension.hasTransmissionTimeOffset) { int32_t offset; original_header.GetExtension(&offset); EXPECT_EQ(offset, logged_header.extension.transmissionTimeOffset); } // AbsoluteSendTime header extension. ASSERT_EQ(original_header.HasExtension(), logged_header.extension.hasAbsoluteSendTime); if (logged_header.extension.hasAbsoluteSendTime) { uint32_t sendtime; original_header.GetExtension(&sendtime); EXPECT_EQ(sendtime, logged_header.extension.absoluteSendTime); } // TransportSequenceNumber header extension. ASSERT_EQ(original_header.HasExtension(), logged_header.extension.hasTransportSequenceNumber); if (logged_header.extension.hasTransportSequenceNumber) { uint16_t seqnum; original_header.GetExtension(&seqnum); EXPECT_EQ(seqnum, logged_header.extension.transportSequenceNumber); } // AudioLevel header extension. ASSERT_EQ(original_header.HasExtension(), logged_header.extension.hasAudioLevel); if (logged_header.extension.hasAudioLevel) { bool voice_activity; uint8_t audio_level; original_header.GetExtension(&voice_activity, &audio_level); EXPECT_EQ(voice_activity, logged_header.extension.voiceActivity); EXPECT_EQ(audio_level, logged_header.extension.audioLevel); } // VideoOrientation header extension. ASSERT_EQ(original_header.HasExtension(), logged_header.extension.hasVideoRotation); if (logged_header.extension.hasVideoRotation) { uint8_t rotation; original_header.GetExtension(&rotation); EXPECT_EQ(ConvertCVOByteToVideoRotation(rotation), logged_header.extension.videoRotation); } } void VerifyLoggedRtpPacketIncoming( const RtcEventRtpPacketIncoming& original_event, const LoggedRtpPacketIncoming& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.header_.headers_size(), logged_event.rtp.header_length); EXPECT_EQ(original_event.packet_length(), logged_event.rtp.total_length); // Currently, RTC eventlog encoder-parser can only maintain padding length // if packet is full padding. EXPECT_EQ(original_event.padding_length_, logged_event.rtp.header.paddingLength); VerifyLoggedRtpHeader(original_event.header_, logged_event.rtp.header); } void VerifyLoggedRtpPacketOutgoing( const RtcEventRtpPacketOutgoing& original_event, const LoggedRtpPacketOutgoing& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); EXPECT_EQ(original_event.header_.headers_size(), logged_event.rtp.header_length); EXPECT_EQ(original_event.packet_length(), logged_event.rtp.total_length); // Currently, RTC eventlog encoder-parser can only maintain padding length // if packet is full padding. EXPECT_EQ(original_event.padding_length_, logged_event.rtp.header.paddingLength); // TODO(terelius): Probe cluster ID isn't parsed, used or tested. Unless // someone has a strong reason to keep it, it'll be removed. VerifyLoggedRtpHeader(original_event.header_, logged_event.rtp.header); } void VerifyLoggedRtcpPacketIncoming( const RtcEventRtcpPacketIncoming& original_event, const LoggedRtcpPacketIncoming& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); ASSERT_EQ(original_event.packet_.size(), logged_event.rtcp.raw_data.size()); EXPECT_EQ( memcmp(original_event.packet_.data(), logged_event.rtcp.raw_data.data(), original_event.packet_.size()), 0); } void VerifyLoggedRtcpPacketOutgoing( const RtcEventRtcpPacketOutgoing& original_event, const LoggedRtcpPacketOutgoing& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); ASSERT_EQ(original_event.packet_.size(), logged_event.rtcp.raw_data.size()); EXPECT_EQ( memcmp(original_event.packet_.data(), logged_event.rtcp.raw_data.data(), original_event.packet_.size()), 0); } void VerifyLoggedStartEvent(int64_t start_time_us, const LoggedStartEvent& logged_event) { EXPECT_EQ(start_time_us / 1000, logged_event.log_time_ms()); } void VerifyLoggedStopEvent(int64_t stop_time_us, const LoggedStopEvent& logged_event) { EXPECT_EQ(stop_time_us / 1000, logged_event.log_time_ms()); } void VerifyLoggedStreamConfig(const rtclog::StreamConfig& original_config, const rtclog::StreamConfig& logged_config) { EXPECT_EQ(original_config.local_ssrc, logged_config.local_ssrc); EXPECT_EQ(original_config.remote_ssrc, logged_config.remote_ssrc); EXPECT_EQ(original_config.rtx_ssrc, logged_config.rtx_ssrc); EXPECT_EQ(original_config.rsid, logged_config.rsid); EXPECT_EQ(original_config.rtp_extensions.size(), logged_config.rtp_extensions.size()); size_t recognized_extensions = 0; for (size_t i = 0; i < kMaxNumExtensions; i++) { auto original_id = GetExtensionId(original_config.rtp_extensions, kExtensions[i].name); auto logged_id = GetExtensionId(logged_config.rtp_extensions, kExtensions[i].name); EXPECT_EQ(original_id, logged_id) << "IDs for " << kExtensions[i].name << " don't match. Original ID " << original_id.value_or(-1) << ". Parsed ID " << logged_id.value_or(-1) << "."; if (original_id) { recognized_extensions++; } } EXPECT_EQ(recognized_extensions, original_config.rtp_extensions.size()); } void VerifyLoggedAudioRecvConfig( const RtcEventAudioReceiveStreamConfig& original_event, const LoggedAudioRecvConfig& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); VerifyLoggedStreamConfig(*original_event.config_, logged_event.config); } void VerifyLoggedAudioSendConfig( const RtcEventAudioSendStreamConfig& original_event, const LoggedAudioSendConfig& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); VerifyLoggedStreamConfig(*original_event.config_, logged_event.config); } void VerifyLoggedVideoRecvConfig( const RtcEventVideoReceiveStreamConfig& original_event, const LoggedVideoRecvConfig& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); VerifyLoggedStreamConfig(*original_event.config_, logged_event.config); } void VerifyLoggedVideoSendConfig( const RtcEventVideoSendStreamConfig& original_event, const LoggedVideoSendConfig& logged_event) { EXPECT_EQ(original_event.timestamp_us_ / 1000, logged_event.log_time_ms()); // TODO(terelius): In the past, we allowed storing multiple RtcStreamConfigs // in the same RtcEventVideoSendStreamConfig. Look into whether we should drop // backwards compatibility in the parser. ASSERT_EQ(logged_event.configs.size(), 1u); VerifyLoggedStreamConfig(*original_event.config_, logged_event.configs[0]); } } // namespace test } // namespace webrtc