| /* |
| * 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 <string.h> // memcmp |
| |
| #include <limits> |
| #include <memory> |
| #include <numeric> |
| #include <utility> |
| #include <vector> |
| |
| #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" |
| |
| 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 <typename T> |
| void ShuffleInPlace(Random* prng, rtc::ArrayView<T> array) { |
| RTC_DCHECK_LE(array.size(), std::numeric_limits<uint32_t>::max()); |
| for (uint32_t i = 0; i + 1 < array.size(); i++) { |
| uint32_t other = prng->Rand(i, static_cast<uint32_t>(array.size() - 1)); |
| std::swap(array[i], array[other]); |
| } |
| } |
| } // namespace |
| |
| std::unique_ptr<RtcEventAlrState> EventGenerator::NewAlrState() { |
| return absl::make_unique<RtcEventAlrState>(prng_.Rand<bool>()); |
| } |
| |
| std::unique_ptr<RtcEventAudioPlayout> EventGenerator::NewAudioPlayout( |
| uint32_t ssrc) { |
| return absl::make_unique<RtcEventAudioPlayout>(ssrc); |
| } |
| |
| std::unique_ptr<RtcEventAudioNetworkAdaptation> |
| EventGenerator::NewAudioNetworkAdaptation() { |
| std::unique_ptr<AudioEncoderRuntimeConfig> config = |
| absl::make_unique<AudioEncoderRuntimeConfig>(); |
| |
| config->bitrate_bps = prng_.Rand(0, 3000000); |
| config->enable_fec = prng_.Rand<bool>(); |
| config->enable_dtx = prng_.Rand<bool>(); |
| config->frame_length_ms = prng_.Rand(10, 120); |
| config->num_channels = prng_.Rand(1, 2); |
| config->uplink_packet_loss_fraction = prng_.Rand<float>(); |
| |
| return absl::make_unique<RtcEventAudioNetworkAdaptation>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventBweUpdateDelayBased> |
| EventGenerator::NewBweUpdateDelayBased() { |
| constexpr int32_t kMaxBweBps = 20000000; |
| int32_t bitrate_bps = prng_.Rand(0, kMaxBweBps); |
| BandwidthUsage state = static_cast<BandwidthUsage>( |
| prng_.Rand(static_cast<uint32_t>(BandwidthUsage::kLast) - 1)); |
| return absl::make_unique<RtcEventBweUpdateDelayBased>(bitrate_bps, state); |
| } |
| |
| std::unique_ptr<RtcEventBweUpdateLossBased> |
| 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<uint8_t>(); |
| int32_t total_packets = prng_.Rand(1, kMaxPackets); |
| |
| return absl::make_unique<RtcEventBweUpdateLossBased>( |
| bitrate_bps, fraction_lost, total_packets); |
| } |
| |
| std::unique_ptr<RtcEventProbeClusterCreated> |
| 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<RtcEventProbeClusterCreated>(id, bitrate_bps, |
| min_probes, min_bytes); |
| } |
| |
| std::unique_ptr<RtcEventProbeResultFailure> |
| EventGenerator::NewProbeResultFailure() { |
| constexpr int kMaxNumProbes = 10000; |
| int id = prng_.Rand(1, kMaxNumProbes); |
| ProbeFailureReason reason = static_cast<ProbeFailureReason>( |
| prng_.Rand(static_cast<uint32_t>(ProbeFailureReason::kLast) - 1)); |
| |
| return absl::make_unique<RtcEventProbeResultFailure>(id, reason); |
| } |
| |
| std::unique_ptr<RtcEventProbeResultSuccess> |
| 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<RtcEventProbeResultSuccess>(id, bitrate_bps); |
| } |
| |
| std::unique_ptr<RtcEventIceCandidatePairConfig> |
| EventGenerator::NewIceCandidatePairConfig() { |
| IceCandidateType local_candidate_type = static_cast<IceCandidateType>( |
| prng_.Rand(static_cast<uint32_t>(IceCandidateType::kNumValues) - 1)); |
| IceCandidateNetworkType local_network_type = |
| static_cast<IceCandidateNetworkType>(prng_.Rand( |
| static_cast<uint32_t>(IceCandidateNetworkType::kNumValues) - 1)); |
| IceCandidatePairAddressFamily local_address_family = |
| static_cast<IceCandidatePairAddressFamily>(prng_.Rand( |
| static_cast<uint32_t>(IceCandidatePairAddressFamily::kNumValues) - |
| 1)); |
| IceCandidateType remote_candidate_type = static_cast<IceCandidateType>( |
| prng_.Rand(static_cast<uint32_t>(IceCandidateType::kNumValues) - 1)); |
| IceCandidatePairAddressFamily remote_address_family = |
| static_cast<IceCandidatePairAddressFamily>(prng_.Rand( |
| static_cast<uint32_t>(IceCandidatePairAddressFamily::kNumValues) - |
| 1)); |
| IceCandidatePairProtocol protocol_type = |
| static_cast<IceCandidatePairProtocol>(prng_.Rand( |
| static_cast<uint32_t>(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<IceCandidatePairConfigType>(prng_.Rand( |
| static_cast<uint32_t>(IceCandidatePairConfigType::kNumValues) - 1)); |
| uint32_t pair_id = prng_.Rand<uint32_t>(); |
| return absl::make_unique<RtcEventIceCandidatePairConfig>(type, pair_id, desc); |
| } |
| |
| std::unique_ptr<RtcEventIceCandidatePair> |
| EventGenerator::NewIceCandidatePair() { |
| IceCandidatePairEventType type = |
| static_cast<IceCandidatePairEventType>(prng_.Rand( |
| static_cast<uint32_t>(IceCandidatePairEventType::kNumValues) - 1)); |
| uint32_t pair_id = prng_.Rand<uint32_t>(); |
| |
| return absl::make_unique<RtcEventIceCandidatePair>(type, pair_id); |
| } |
| |
| rtcp::ReportBlock EventGenerator::NewReportBlock() { |
| rtcp::ReportBlock report_block; |
| report_block.SetMediaSsrc(prng_.Rand<uint32_t>()); |
| report_block.SetFractionLost(prng_.Rand<uint8_t>()); |
| // 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<uint32_t>()); |
| report_block.SetJitter(prng_.Rand<uint32_t>()); |
| report_block.SetLastSr(prng_.Rand<uint32_t>()); |
| report_block.SetDelayLastSr(prng_.Rand<uint32_t>()); |
| return report_block; |
| } |
| |
| rtcp::SenderReport EventGenerator::NewSenderReport() { |
| rtcp::SenderReport sender_report; |
| sender_report.SetSenderSsrc(prng_.Rand<uint32_t>()); |
| sender_report.SetNtp(NtpTime(prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>())); |
| sender_report.SetPacketCount(prng_.Rand<uint32_t>()); |
| sender_report.AddReportBlock(NewReportBlock()); |
| return sender_report; |
| } |
| |
| rtcp::ReceiverReport EventGenerator::NewReceiverReport() { |
| rtcp::ReceiverReport receiver_report; |
| receiver_report.SetSenderSsrc(prng_.Rand<uint32_t>()); |
| receiver_report.AddReportBlock(NewReportBlock()); |
| return receiver_report; |
| } |
| |
| std::unique_ptr<RtcEventRtcpPacketIncoming> |
| 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<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case 1: { |
| rtcp::ReceiverReport receiver_report = NewReceiverReport(); |
| rtc::Buffer buffer = receiver_report.Build(); |
| return absl::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| default: |
| RTC_NOTREACHED(); |
| rtc::Buffer buffer; |
| return absl::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| } |
| |
| std::unique_ptr<RtcEventRtcpPacketOutgoing> |
| 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<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case 1: { |
| rtcp::ReceiverReport receiver_report = NewReceiverReport(); |
| rtc::Buffer buffer = receiver_report.Build(); |
| return absl::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| default: |
| RTC_NOTREACHED(); |
| rtc::Buffer buffer; |
| return absl::make_unique<RtcEventRtcpPacketOutgoing>(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<bool>()); |
| rtp_packet->SetSequenceNumber(prng_.Rand<uint16_t>()); |
| rtp_packet->SetSsrc(ssrc); |
| rtp_packet->SetTimestamp(prng_.Rand<uint32_t>()); |
| |
| uint32_t csrcs_count = prng_.Rand(0, kMaxCsrcs); |
| std::vector<uint32_t> csrcs; |
| for (size_t i = 0; i < csrcs_count; i++) { |
| csrcs.push_back(prng_.Rand<uint32_t>()); |
| } |
| rtp_packet->SetCsrcs(csrcs); |
| |
| if (extension_map.IsRegistered(TransmissionOffset::kId)) |
| rtp_packet->SetExtension<TransmissionOffset>(prng_.Rand(0x00ffffff)); |
| if (extension_map.IsRegistered(AudioLevel::kId)) |
| rtp_packet->SetExtension<AudioLevel>(prng_.Rand<bool>(), prng_.Rand(127)); |
| if (extension_map.IsRegistered(AbsoluteSendTime::kId)) |
| rtp_packet->SetExtension<AbsoluteSendTime>(prng_.Rand(0x00ffffff)); |
| if (extension_map.IsRegistered(VideoOrientation::kId)) |
| rtp_packet->SetExtension<VideoOrientation>(prng_.Rand(3)); |
| if (extension_map.IsRegistered(TransportSequenceNumber::kId)) |
| rtp_packet->SetExtension<TransportSequenceNumber>(prng_.Rand<uint16_t>()); |
| |
| 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<uint8_t>(); |
| } |
| RTC_CHECK(rtp_packet->SetPadding(padding_size, &prng_)); |
| } |
| |
| std::unique_ptr<RtcEventRtpPacketIncoming> 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<uint32_t>(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<RtcEventRtpPacketIncoming>(rtp_packet); |
| } |
| |
| std::unique_ptr<RtcEventRtpPacketOutgoing> 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<uint32_t>(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<RtcEventRtpPacketOutgoing>(rtp_packet, |
| probe_cluster_id); |
| } |
| |
| RtpHeaderExtensionMap EventGenerator::NewRtpHeaderExtensionMap() { |
| RtpHeaderExtensionMap extension_map; |
| std::vector<int> id(RtpExtension::kOneByteHeaderExtensionMaxId - |
| RtpExtension::kMinId + 1); |
| std::iota(id.begin(), id.end(), RtpExtension::kMinId); |
| ShuffleInPlace(&prng_, rtc::ArrayView<int>(id)); |
| |
| if (prng_.Rand<bool>()) { |
| extension_map.Register<AudioLevel>(id[0]); |
| } |
| if (prng_.Rand<bool>()) { |
| extension_map.Register<TransmissionOffset>(id[1]); |
| } |
| if (prng_.Rand<bool>()) { |
| extension_map.Register<AbsoluteSendTime>(id[2]); |
| } |
| if (prng_.Rand<bool>()) { |
| extension_map.Register<VideoOrientation>(id[3]); |
| } |
| if (prng_.Rand<bool>()) { |
| extension_map.Register<TransportSequenceNumber>(id[4]); |
| } |
| |
| return extension_map; |
| } |
| |
| std::unique_ptr<RtcEventAudioReceiveStreamConfig> |
| EventGenerator::NewAudioReceiveStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = absl::make_unique<rtclog::StreamConfig>(); |
| // Add SSRCs for the stream. |
| config->remote_ssrc = ssrc; |
| config->local_ssrc = prng_.Rand<uint32_t>(); |
| // 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<RtcEventAudioReceiveStreamConfig>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventAudioSendStreamConfig> |
| EventGenerator::NewAudioSendStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = absl::make_unique<rtclog::StreamConfig>(); |
| // 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<RtcEventAudioSendStreamConfig>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventVideoReceiveStreamConfig> |
| EventGenerator::NewVideoReceiveStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = absl::make_unique<rtclog::StreamConfig>(); |
| |
| // Add SSRCs for the stream. |
| config->remote_ssrc = ssrc; |
| config->local_ssrc = prng_.Rand<uint32_t>(); |
| // Add extensions and settings for RTCP. |
| config->rtcp_mode = |
| prng_.Rand<bool>() ? RtcpMode::kCompound : RtcpMode::kReducedSize; |
| config->remb = prng_.Rand<bool>(); |
| config->rtx_ssrc = prng_.Rand<uint32_t>(); |
| config->codecs.emplace_back(prng_.Rand<bool>() ? "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<RtcEventVideoReceiveStreamConfig>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventVideoSendStreamConfig> |
| EventGenerator::NewVideoSendStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = absl::make_unique<rtclog::StreamConfig>(); |
| |
| config->codecs.emplace_back(prng_.Rand<bool>() ? "VP8" : "H264", |
| prng_.Rand(127), prng_.Rand(127)); |
| config->local_ssrc = ssrc; |
| config->rtx_ssrc = prng_.Rand<uint32_t>(); |
| // 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<RtcEventVideoSendStreamConfig>(std::move(config)); |
| } |
| |
| bool VerifyLoggedAlrStateEvent(const RtcEventAlrState& original_event, |
| const LoggedAlrStateEvent& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (original_event.in_alr_ != logged_event.in_alr) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedAudioPlayoutEvent( |
| const RtcEventAudioPlayout& original_event, |
| const LoggedAudioPlayoutEvent& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (original_event.ssrc_ != logged_event.ssrc) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedAudioNetworkAdaptationEvent( |
| const RtcEventAudioNetworkAdaptation& original_event, |
| const LoggedAudioNetworkAdaptationEvent& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| |
| if (original_event.config_->bitrate_bps != logged_event.config.bitrate_bps) |
| return false; |
| if (original_event.config_->enable_dtx != logged_event.config.enable_dtx) |
| return false; |
| if (original_event.config_->enable_fec != logged_event.config.enable_fec) |
| return false; |
| if (original_event.config_->frame_length_ms != |
| logged_event.config.frame_length_ms) |
| return false; |
| if (original_event.config_->num_channels != logged_event.config.num_channels) |
| return false; |
| if (original_event.config_->uplink_packet_loss_fraction != |
| logged_event.config.uplink_packet_loss_fraction) |
| return false; |
| |
| return true; |
| } |
| |
| bool VerifyLoggedBweDelayBasedUpdate( |
| const RtcEventBweUpdateDelayBased& original_event, |
| const LoggedBweDelayBasedUpdate& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (original_event.bitrate_bps_ != logged_event.bitrate_bps) |
| return false; |
| if (original_event.detector_state_ != logged_event.detector_state) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedBweLossBasedUpdate( |
| const RtcEventBweUpdateLossBased& original_event, |
| const LoggedBweLossBasedUpdate& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (original_event.bitrate_bps_ != logged_event.bitrate_bps) |
| return false; |
| if (original_event.fraction_loss_ != logged_event.fraction_lost) |
| return false; |
| if (original_event.total_packets_ != logged_event.expected_packets) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedBweProbeClusterCreatedEvent( |
| const RtcEventProbeClusterCreated& original_event, |
| const LoggedBweProbeClusterCreatedEvent& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (original_event.id_ != logged_event.id) |
| return false; |
| if (original_event.bitrate_bps_ != logged_event.bitrate_bps) |
| return false; |
| if (original_event.min_probes_ != logged_event.min_packets) |
| return false; |
| if (original_event.min_bytes_ != logged_event.min_bytes) |
| return false; |
| |
| return true; |
| } |
| |
| bool VerifyLoggedBweProbeFailureEvent( |
| const RtcEventProbeResultFailure& original_event, |
| const LoggedBweProbeFailureEvent& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (original_event.id_ != logged_event.id) |
| return false; |
| if (original_event.failure_reason_ != logged_event.failure_reason) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedBweProbeSuccessEvent( |
| const RtcEventProbeResultSuccess& original_event, |
| const LoggedBweProbeSuccessEvent& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (original_event.id_ != logged_event.id) |
| return false; |
| if (original_event.bitrate_bps_ != logged_event.bitrate_bps) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedIceCandidatePairConfig( |
| const RtcEventIceCandidatePairConfig& original_event, |
| const LoggedIceCandidatePairConfig& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| |
| if (original_event.type_ != logged_event.type) |
| return false; |
| if (original_event.candidate_pair_id_ != logged_event.candidate_pair_id) |
| return false; |
| if (original_event.candidate_pair_desc_.local_candidate_type != |
| logged_event.local_candidate_type) |
| return false; |
| if (original_event.candidate_pair_desc_.local_relay_protocol != |
| logged_event.local_relay_protocol) |
| return false; |
| if (original_event.candidate_pair_desc_.local_network_type != |
| logged_event.local_network_type) |
| return false; |
| if (original_event.candidate_pair_desc_.local_address_family != |
| logged_event.local_address_family) |
| return false; |
| if (original_event.candidate_pair_desc_.remote_candidate_type != |
| logged_event.remote_candidate_type) |
| return false; |
| if (original_event.candidate_pair_desc_.remote_address_family != |
| logged_event.remote_address_family) |
| return false; |
| if (original_event.candidate_pair_desc_.candidate_pair_protocol != |
| logged_event.candidate_pair_protocol) |
| return false; |
| |
| return true; |
| } |
| |
| bool VerifyLoggedIceCandidatePairEvent( |
| const RtcEventIceCandidatePair& original_event, |
| const LoggedIceCandidatePairEvent& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| |
| if (original_event.type_ != logged_event.type) |
| return false; |
| if (original_event.candidate_pair_id_ != logged_event.candidate_pair_id) |
| return false; |
| |
| return true; |
| } |
| |
| bool VerifyLoggedRtpHeader(const RtpPacket& original_header, |
| const RTPHeader& logged_header) { |
| // Standard RTP header. |
| if (original_header.Marker() != logged_header.markerBit) |
| return false; |
| if (original_header.PayloadType() != logged_header.payloadType) |
| return false; |
| if (original_header.SequenceNumber() != logged_header.sequenceNumber) |
| return false; |
| if (original_header.Timestamp() != logged_header.timestamp) |
| return false; |
| if (original_header.Ssrc() != logged_header.ssrc) |
| return false; |
| if (original_header.Csrcs().size() != logged_header.numCSRCs) |
| return false; |
| for (size_t i = 0; i < logged_header.numCSRCs; i++) { |
| if (original_header.Csrcs()[i] != logged_header.arrOfCSRCs[i]) |
| return false; |
| } |
| |
| if (original_header.headers_size() != logged_header.headerLength) |
| return false; |
| |
| // TransmissionOffset header extension. |
| if (original_header.HasExtension<TransmissionOffset>() != |
| logged_header.extension.hasTransmissionTimeOffset) |
| return false; |
| if (logged_header.extension.hasTransmissionTimeOffset) { |
| int32_t offset; |
| original_header.GetExtension<TransmissionOffset>(&offset); |
| if (offset != logged_header.extension.transmissionTimeOffset) |
| return false; |
| } |
| |
| // AbsoluteSendTime header extension. |
| if (original_header.HasExtension<AbsoluteSendTime>() != |
| logged_header.extension.hasAbsoluteSendTime) |
| return false; |
| if (logged_header.extension.hasAbsoluteSendTime) { |
| uint32_t sendtime; |
| original_header.GetExtension<AbsoluteSendTime>(&sendtime); |
| if (sendtime != logged_header.extension.absoluteSendTime) |
| return false; |
| } |
| |
| // TransportSequenceNumber header extension. |
| if (original_header.HasExtension<TransportSequenceNumber>() != |
| logged_header.extension.hasTransportSequenceNumber) |
| return false; |
| if (logged_header.extension.hasTransportSequenceNumber) { |
| uint16_t seqnum; |
| original_header.GetExtension<TransportSequenceNumber>(&seqnum); |
| if (seqnum != logged_header.extension.transportSequenceNumber) |
| return false; |
| } |
| |
| // AudioLevel header extension. |
| if (original_header.HasExtension<AudioLevel>() != |
| logged_header.extension.hasAudioLevel) |
| return false; |
| if (logged_header.extension.hasAudioLevel) { |
| bool voice_activity; |
| uint8_t audio_level; |
| original_header.GetExtension<AudioLevel>(&voice_activity, &audio_level); |
| if (voice_activity != logged_header.extension.voiceActivity) |
| return false; |
| if (audio_level != logged_header.extension.audioLevel) |
| return false; |
| } |
| |
| // VideoOrientation header extension. |
| if (original_header.HasExtension<VideoOrientation>() != |
| logged_header.extension.hasVideoRotation) |
| return false; |
| if (logged_header.extension.hasVideoRotation) { |
| uint8_t rotation; |
| original_header.GetExtension<VideoOrientation>(&rotation); |
| if (ConvertCVOByteToVideoRotation(rotation) != |
| logged_header.extension.videoRotation) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool VerifyLoggedRtpPacketIncoming( |
| const RtcEventRtpPacketIncoming& original_event, |
| const LoggedRtpPacketIncoming& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| |
| if (original_event.header_.headers_size() != logged_event.rtp.header_length) |
| return false; |
| |
| if (original_event.packet_length_ != logged_event.rtp.total_length) |
| return false; |
| |
| if ((original_event.header_.data()[0] & 0x20) != 0 && // has padding |
| original_event.packet_length_ - original_event.header_.headers_size() != |
| logged_event.rtp.header.paddingLength) { |
| // Currently, RTC eventlog encoder-parser can only maintain padding length |
| // if packet is full padding. |
| // TODO(webrtc:9730): Change the condition to something like |
| // original_event.padding_length_ != logged_event.rtp.header.paddingLength. |
| return false; |
| } |
| |
| if (!VerifyLoggedRtpHeader(original_event.header_, logged_event.rtp.header)) |
| return false; |
| |
| return true; |
| } |
| |
| bool VerifyLoggedRtpPacketOutgoing( |
| const RtcEventRtpPacketOutgoing& original_event, |
| const LoggedRtpPacketOutgoing& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| |
| if (original_event.header_.headers_size() != logged_event.rtp.header_length) |
| return false; |
| |
| if (original_event.packet_length_ != logged_event.rtp.total_length) |
| return false; |
| |
| if ((original_event.header_.data()[0] & 0x20) != 0 && // has padding |
| original_event.packet_length_ - original_event.header_.headers_size() != |
| logged_event.rtp.header.paddingLength) { |
| // Currently, RTC eventlog encoder-parser can only maintain padding length |
| // if packet is full padding. |
| // TODO(webrtc:9730): Change the condition to something like |
| // original_event.padding_length_ != logged_event.rtp.header.paddingLength. |
| return false; |
| } |
| |
| // TODO(terelius): Probe cluster ID isn't parsed, used or tested. Unless |
| // someone has a strong reason to keep it, it'll be removed. |
| |
| if (!VerifyLoggedRtpHeader(original_event.header_, logged_event.rtp.header)) |
| return false; |
| |
| return true; |
| } |
| |
| bool VerifyLoggedRtcpPacketIncoming( |
| const RtcEventRtcpPacketIncoming& original_event, |
| const LoggedRtcpPacketIncoming& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| |
| if (original_event.packet_.size() != logged_event.rtcp.raw_data.size()) |
| return false; |
| if (memcmp(original_event.packet_.data(), logged_event.rtcp.raw_data.data(), |
| original_event.packet_.size()) != 0) { |
| return false; |
| } |
| return true; |
| } |
| |
| bool VerifyLoggedRtcpPacketOutgoing( |
| const RtcEventRtcpPacketOutgoing& original_event, |
| const LoggedRtcpPacketOutgoing& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| |
| if (original_event.packet_.size() != logged_event.rtcp.raw_data.size()) |
| return false; |
| if (memcmp(original_event.packet_.data(), logged_event.rtcp.raw_data.data(), |
| original_event.packet_.size()) != 0) { |
| return false; |
| } |
| return true; |
| } |
| |
| bool VerifyLoggedStartEvent(int64_t start_time_us, |
| const LoggedStartEvent& logged_event) { |
| if (start_time_us != logged_event.log_time_us()) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedStopEvent(int64_t stop_time_us, |
| const LoggedStopEvent& logged_event) { |
| if (stop_time_us != logged_event.log_time_us()) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedAudioRecvConfig( |
| const RtcEventAudioReceiveStreamConfig& original_event, |
| const LoggedAudioRecvConfig& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (*original_event.config_ != logged_event.config) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedAudioSendConfig( |
| const RtcEventAudioSendStreamConfig& original_event, |
| const LoggedAudioSendConfig& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (*original_event.config_ != logged_event.config) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedVideoRecvConfig( |
| const RtcEventVideoReceiveStreamConfig& original_event, |
| const LoggedVideoRecvConfig& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| if (*original_event.config_ != logged_event.config) |
| return false; |
| return true; |
| } |
| |
| bool VerifyLoggedVideoSendConfig( |
| const RtcEventVideoSendStreamConfig& original_event, |
| const LoggedVideoSendConfig& logged_event) { |
| if (original_event.timestamp_us_ != logged_event.log_time_us()) |
| return false; |
| // 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. |
| if (logged_event.configs.size() != 1) |
| return false; |
| if (*original_event.config_ != logged_event.configs[0]) |
| return false; |
| return true; |
| } |
| |
| } // namespace test |
| } // namespace webrtc |