| /* |
| * 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 <cmath> |
| #include <cstdint> |
| #include <limits> |
| #include <memory> |
| #include <numeric> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/strings/string_view.h" |
| #include "absl/types/optional.h" |
| #include "api/array_view.h" |
| #include "api/network_state_predictor.h" |
| #include "api/rtp_headers.h" |
| #include "api/rtp_parameters.h" |
| #include "api/units/time_delta.h" |
| #include "api/units/timestamp.h" |
| #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h" |
| #include "modules/rtp_rtcp/include/rtp_cvo.h" |
| #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| #include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h" |
| #include "modules/rtp_rtcp/source/rtcp_packet/rrtr.h" |
| #include "modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h" |
| #include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.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/buffer.h" |
| #include "rtc_base/checks.h" |
| #include "rtc_base/time_utils.h" |
| #include "system_wrappers/include/ntp_time.h" |
| #include "test/gmock.h" |
| #include "test/gtest.h" |
| |
| namespace webrtc { |
| |
| namespace test { |
| |
| namespace { |
| |
| using ::testing::ElementsAreArray; |
| using ::testing::IsEmpty; |
| |
| 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 = 10; |
| constexpr int kMaxNumExtensions = 6; |
| |
| constexpr ExtensionPair kExtensions[kMaxNumExtensions] = { |
| {RTPExtensionType::kRtpExtensionTransmissionTimeOffset, |
| RtpExtension::kTimestampOffsetUri}, |
| {RTPExtensionType::kRtpExtensionAbsoluteSendTime, |
| RtpExtension::kAbsSendTimeUri}, |
| {RTPExtensionType::kRtpExtensionTransportSequenceNumber, |
| RtpExtension::kTransportSequenceNumberUri}, |
| {RTPExtensionType::kRtpExtensionAudioLevel, RtpExtension::kAudioLevelUri}, |
| {RTPExtensionType::kRtpExtensionVideoRotation, |
| RtpExtension::kVideoRotationUri}, |
| {RTPExtensionType::kRtpExtensionDependencyDescriptor, |
| RtpExtension::kDependencyDescriptorUri}}; |
| |
| 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]); |
| } |
| } |
| |
| absl::optional<int> GetExtensionId(const std::vector<RtpExtension>& extensions, |
| absl::string_view uri) { |
| for (const auto& extension : extensions) { |
| if (extension.uri == uri) |
| return extension.id; |
| } |
| return absl::nullopt; |
| } |
| |
| } // namespace |
| |
| std::unique_ptr<RtcEventAlrState> EventGenerator::NewAlrState() { |
| return std::make_unique<RtcEventAlrState>(prng_.Rand<bool>()); |
| } |
| |
| std::unique_ptr<RtcEventAudioPlayout> EventGenerator::NewAudioPlayout( |
| uint32_t ssrc) { |
| return std::make_unique<RtcEventAudioPlayout>(ssrc); |
| } |
| |
| std::unique_ptr<RtcEventAudioNetworkAdaptation> |
| EventGenerator::NewAudioNetworkAdaptation() { |
| std::unique_ptr<AudioEncoderRuntimeConfig> config = |
| std::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 std::make_unique<RtcEventAudioNetworkAdaptation>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventNetEqSetMinimumDelay> |
| EventGenerator::NewNetEqSetMinimumDelay(uint32_t ssrc) { |
| return std::make_unique<RtcEventNetEqSetMinimumDelay>( |
| ssrc, prng_.Rand(std::numeric_limits<int>::max())); |
| } |
| |
| 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 std::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 std::make_unique<RtcEventBweUpdateLossBased>( |
| bitrate_bps, fraction_lost, total_packets); |
| } |
| |
| std::unique_ptr<RtcEventDtlsTransportState> |
| EventGenerator::NewDtlsTransportState() { |
| DtlsTransportState state = static_cast<DtlsTransportState>( |
| prng_.Rand(static_cast<uint32_t>(DtlsTransportState::kNumValues) - 1)); |
| |
| return std::make_unique<RtcEventDtlsTransportState>(state); |
| } |
| |
| std::unique_ptr<RtcEventDtlsWritableState> |
| EventGenerator::NewDtlsWritableState() { |
| bool writable = prng_.Rand<bool>(); |
| return std::make_unique<RtcEventDtlsWritableState>(writable); |
| } |
| |
| std::unique_ptr<RtcEventFrameDecoded> EventGenerator::NewFrameDecodedEvent( |
| uint32_t ssrc) { |
| constexpr int kMinRenderDelayMs = 1; |
| constexpr int kMaxRenderDelayMs = 2000000; |
| constexpr int kMaxWidth = 15360; |
| constexpr int kMaxHeight = 8640; |
| constexpr int kMinWidth = 16; |
| constexpr int kMinHeight = 16; |
| constexpr int kNumCodecTypes = 6; |
| |
| constexpr VideoCodecType kCodecList[kNumCodecTypes] = { |
| kVideoCodecGeneric, kVideoCodecVP8, kVideoCodecVP9, |
| kVideoCodecAV1, kVideoCodecH264, kVideoCodecH265}; |
| const int64_t render_time_ms = |
| rtc::TimeMillis() + prng_.Rand(kMinRenderDelayMs, kMaxRenderDelayMs); |
| const int width = prng_.Rand(kMinWidth, kMaxWidth); |
| const int height = prng_.Rand(kMinHeight, kMaxHeight); |
| const VideoCodecType codec = kCodecList[prng_.Rand(0, kNumCodecTypes - 1)]; |
| const uint8_t qp = prng_.Rand<uint8_t>(); |
| return std::make_unique<RtcEventFrameDecoded>(render_time_ms, ssrc, width, |
| height, codec, qp); |
| } |
| |
| 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 std::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 std::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 std::make_unique<RtcEventProbeResultSuccess>(id, bitrate_bps); |
| } |
| |
| constexpr uint32_t CandidateTypeCount() { |
| // This switch statement only exists to catch changes to the IceCandidateType |
| // enumeration. If you get an error here, please update the switch statement |
| // and the return value. |
| IceCandidateType type = IceCandidateType::kHost; |
| switch (type) { |
| case IceCandidateType::kHost: |
| case IceCandidateType::kSrflx: |
| case IceCandidateType::kPrflx: |
| case IceCandidateType::kRelay: |
| break; |
| } |
| return 4u; |
| } |
| |
| std::unique_ptr<RtcEventIceCandidatePairConfig> |
| EventGenerator::NewIceCandidatePairConfig() { |
| static_assert(static_cast<int>(IceCandidateType::kHost) == 0, |
| "Expect kLocal to be the first enum value, equal to 0"); |
| IceCandidateType local_candidate_type = |
| static_cast<IceCandidateType>(prng_.Rand(CandidateTypeCount() - 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(CandidateTypeCount() - 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(local_candidate_type, remote_candidate_type); |
| desc.local_relay_protocol = protocol_type; |
| desc.local_network_type = local_network_type; |
| desc.local_address_family = local_address_family; |
| 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 std::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>(); |
| uint32_t transaction_id = prng_.Rand<uint32_t>(); |
| |
| return std::make_unique<RtcEventIceCandidatePair>(type, pair_id, |
| transaction_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.SetRtpTimestamp(prng_.Rand<uint32_t>()); |
| sender_report.SetPacketCount(prng_.Rand<uint32_t>()); |
| sender_report.SetOctetCount(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; |
| } |
| |
| rtcp::ExtendedReports EventGenerator::NewExtendedReports() { |
| rtcp::ExtendedReports extended_report; |
| extended_report.SetSenderSsrc(prng_.Rand<uint32_t>()); |
| |
| rtcp::Rrtr rrtr; |
| rrtr.SetNtp(NtpTime(prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>())); |
| extended_report.SetRrtr(rrtr); |
| |
| rtcp::ReceiveTimeInfo time_info( |
| prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>()); |
| extended_report.AddDlrrItem(time_info); |
| |
| rtcp::TargetBitrate target_bitrate; |
| target_bitrate.AddTargetBitrate(/*spatial layer*/ prng_.Rand(0, 3), |
| /*temporal layer*/ prng_.Rand(0, 3), |
| /*bitrate kbps*/ prng_.Rand(0, 50000)); |
| target_bitrate.AddTargetBitrate(/*spatial layer*/ prng_.Rand(4, 7), |
| /*temporal layer*/ prng_.Rand(4, 7), |
| /*bitrate kbps*/ prng_.Rand(0, 50000)); |
| extended_report.SetTargetBitrate(target_bitrate); |
| return extended_report; |
| } |
| |
| rtcp::Nack EventGenerator::NewNack() { |
| rtcp::Nack nack; |
| uint16_t base_seq_no = prng_.Rand<uint16_t>(); |
| std::vector<uint16_t> nack_list; |
| nack_list.push_back(base_seq_no); |
| for (uint16_t i = 1u; i < 10u; i++) { |
| if (prng_.Rand<bool>()) |
| nack_list.push_back(base_seq_no + i); |
| } |
| nack.SetPacketIds(nack_list); |
| return nack; |
| } |
| |
| rtcp::Fir EventGenerator::NewFir() { |
| rtcp::Fir fir; |
| fir.SetSenderSsrc(prng_.Rand<uint32_t>()); |
| fir.AddRequestTo(/*ssrc*/ prng_.Rand<uint32_t>(), |
| /*seq num*/ prng_.Rand<uint8_t>()); |
| fir.AddRequestTo(/*ssrc*/ prng_.Rand<uint32_t>(), |
| /*seq num*/ prng_.Rand<uint8_t>()); |
| return fir; |
| } |
| |
| rtcp::Pli EventGenerator::NewPli() { |
| rtcp::Pli pli; |
| pli.SetSenderSsrc(prng_.Rand<uint32_t>()); |
| pli.SetMediaSsrc(prng_.Rand<uint32_t>()); |
| return pli; |
| } |
| |
| rtcp::Bye EventGenerator::NewBye() { |
| rtcp::Bye bye; |
| bye.SetSenderSsrc(prng_.Rand<uint32_t>()); |
| std::vector<uint32_t> csrcs{prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>()}; |
| bye.SetCsrcs(csrcs); |
| if (prng_.Rand(0, 2)) { |
| bye.SetReason("foo"); |
| } else { |
| bye.SetReason("bar"); |
| } |
| return bye; |
| } |
| |
| rtcp::TransportFeedback EventGenerator::NewTransportFeedback() { |
| rtcp::TransportFeedback transport_feedback; |
| uint16_t base_seq_no = prng_.Rand<uint16_t>(); |
| Timestamp base_time = Timestamp::Micros(prng_.Rand<uint32_t>()); |
| transport_feedback.SetBase(base_seq_no, base_time); |
| transport_feedback.AddReceivedPacket(base_seq_no, base_time); |
| Timestamp time = base_time; |
| for (uint16_t i = 1u; i < 10u; i++) { |
| time += TimeDelta::Micros(prng_.Rand(0, 100'000)); |
| if (prng_.Rand<bool>()) { |
| transport_feedback.AddReceivedPacket(base_seq_no + i, time); |
| } |
| } |
| return transport_feedback; |
| } |
| |
| rtcp::Remb EventGenerator::NewRemb() { |
| rtcp::Remb remb; |
| // The remb bitrate is transported as a 16-bit mantissa and an 8-bit exponent. |
| uint64_t bitrate_bps = prng_.Rand(0, (1 << 16) - 1) << prng_.Rand(7); |
| std::vector<uint32_t> ssrcs{prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>()}; |
| remb.SetSsrcs(ssrcs); |
| remb.SetBitrateBps(bitrate_bps); |
| return remb; |
| } |
| |
| rtcp::LossNotification EventGenerator::NewLossNotification() { |
| rtcp::LossNotification loss_notification; |
| const uint16_t last_decoded = prng_.Rand<uint16_t>(); |
| const uint16_t last_received = |
| last_decoded + (prng_.Rand<uint16_t>() & 0x7fff); |
| const bool decodability_flag = prng_.Rand<bool>(); |
| EXPECT_TRUE( |
| loss_notification.Set(last_decoded, last_received, decodability_flag)); |
| return loss_notification; |
| } |
| |
| std::unique_ptr<RtcEventRouteChange> EventGenerator::NewRouteChange() { |
| return std::make_unique<RtcEventRouteChange>(prng_.Rand<bool>(), |
| prng_.Rand(0, 128)); |
| } |
| |
| std::unique_ptr<RtcEventRemoteEstimate> EventGenerator::NewRemoteEstimate() { |
| return std::make_unique<RtcEventRemoteEstimate>( |
| DataRate::KilobitsPerSec(prng_.Rand(0, 100000)), |
| DataRate::KilobitsPerSec(prng_.Rand(0, 100000))); |
| } |
| |
| std::unique_ptr<RtcEventRtcpPacketIncoming> |
| EventGenerator::NewRtcpPacketIncoming() { |
| enum class SupportedRtcpTypes { |
| kSenderReport = 0, |
| kReceiverReport, |
| kExtendedReports, |
| kFir, |
| kPli, |
| kNack, |
| kRemb, |
| kBye, |
| kTransportFeedback, |
| kNumValues |
| }; |
| SupportedRtcpTypes type = static_cast<SupportedRtcpTypes>( |
| prng_.Rand(0, static_cast<int>(SupportedRtcpTypes::kNumValues) - 1)); |
| switch (type) { |
| case SupportedRtcpTypes::kSenderReport: { |
| rtcp::SenderReport sender_report = NewSenderReport(); |
| rtc::Buffer buffer = sender_report.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kReceiverReport: { |
| rtcp::ReceiverReport receiver_report = NewReceiverReport(); |
| rtc::Buffer buffer = receiver_report.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kExtendedReports: { |
| rtcp::ExtendedReports extended_report = NewExtendedReports(); |
| rtc::Buffer buffer = extended_report.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kFir: { |
| rtcp::Fir fir = NewFir(); |
| rtc::Buffer buffer = fir.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kPli: { |
| rtcp::Pli pli = NewPli(); |
| rtc::Buffer buffer = pli.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kNack: { |
| rtcp::Nack nack = NewNack(); |
| rtc::Buffer buffer = nack.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kRemb: { |
| rtcp::Remb remb = NewRemb(); |
| rtc::Buffer buffer = remb.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kBye: { |
| rtcp::Bye bye = NewBye(); |
| rtc::Buffer buffer = bye.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| case SupportedRtcpTypes::kTransportFeedback: { |
| rtcp::TransportFeedback transport_feedback = NewTransportFeedback(); |
| rtc::Buffer buffer = transport_feedback.Build(); |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| default: |
| RTC_DCHECK_NOTREACHED(); |
| rtc::Buffer buffer; |
| return std::make_unique<RtcEventRtcpPacketIncoming>(buffer); |
| } |
| } |
| |
| std::unique_ptr<RtcEventRtcpPacketOutgoing> |
| EventGenerator::NewRtcpPacketOutgoing() { |
| enum class SupportedRtcpTypes { |
| kSenderReport = 0, |
| kReceiverReport, |
| kExtendedReports, |
| kFir, |
| kPli, |
| kNack, |
| kRemb, |
| kBye, |
| kTransportFeedback, |
| kNumValues |
| }; |
| SupportedRtcpTypes type = static_cast<SupportedRtcpTypes>( |
| prng_.Rand(0, static_cast<int>(SupportedRtcpTypes::kNumValues) - 1)); |
| switch (type) { |
| case SupportedRtcpTypes::kSenderReport: { |
| rtcp::SenderReport sender_report = NewSenderReport(); |
| rtc::Buffer buffer = sender_report.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kReceiverReport: { |
| rtcp::ReceiverReport receiver_report = NewReceiverReport(); |
| rtc::Buffer buffer = receiver_report.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kExtendedReports: { |
| rtcp::ExtendedReports extended_report = NewExtendedReports(); |
| rtc::Buffer buffer = extended_report.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kFir: { |
| rtcp::Fir fir = NewFir(); |
| rtc::Buffer buffer = fir.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kPli: { |
| rtcp::Pli pli = NewPli(); |
| rtc::Buffer buffer = pli.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kNack: { |
| rtcp::Nack nack = NewNack(); |
| rtc::Buffer buffer = nack.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kRemb: { |
| rtcp::Remb remb = NewRemb(); |
| rtc::Buffer buffer = remb.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kBye: { |
| rtcp::Bye bye = NewBye(); |
| rtc::Buffer buffer = bye.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| case SupportedRtcpTypes::kTransportFeedback: { |
| rtcp::TransportFeedback transport_feedback = NewTransportFeedback(); |
| rtc::Buffer buffer = transport_feedback.Build(); |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| default: |
| RTC_DCHECK_NOTREACHED(); |
| rtc::Buffer buffer; |
| return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer); |
| } |
| } |
| |
| std::unique_ptr<RtcEventGenericPacketSent> |
| EventGenerator::NewGenericPacketSent() { |
| return std::make_unique<RtcEventGenericPacketSent>( |
| sent_packet_number_++, prng_.Rand(40, 50), prng_.Rand(0, 150), |
| prng_.Rand(0, 1000)); |
| } |
| std::unique_ptr<RtcEventGenericPacketReceived> |
| EventGenerator::NewGenericPacketReceived() { |
| return std::make_unique<RtcEventGenericPacketReceived>( |
| received_packet_number_++, prng_.Rand(40, 250)); |
| } |
| std::unique_ptr<RtcEventGenericAckReceived> |
| EventGenerator::NewGenericAckReceived() { |
| absl::optional<int64_t> receive_timestamp = absl::nullopt; |
| if (prng_.Rand(0, 2) > 0) { |
| receive_timestamp = prng_.Rand(0, 100000); |
| } |
| AckedPacket packet = {prng_.Rand(40, 250), receive_timestamp}; |
| return std::move(RtcEventGenericAckReceived::CreateLogs( |
| received_packet_number_++, std::vector<AckedPacket>{packet})[0]); |
| } |
| |
| void EventGenerator::RandomizeRtpPacket( |
| size_t payload_size, |
| size_t padding_size, |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extension_map, |
| RtpPacket* rtp_packet, |
| bool all_configured_exts) { |
| 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) && |
| (all_configured_exts || prng_.Rand<bool>())) { |
| rtp_packet->SetExtension<TransmissionOffset>(prng_.Rand(0x00ffffff)); |
| } |
| |
| if (extension_map.IsRegistered(AudioLevelExtension::kId) && |
| (all_configured_exts || prng_.Rand<bool>())) { |
| rtp_packet->SetExtension<AudioLevelExtension>( |
| AudioLevel(prng_.Rand<bool>(), prng_.Rand(127))); |
| } |
| |
| if (extension_map.IsRegistered(AbsoluteSendTime::kId) && |
| (all_configured_exts || prng_.Rand<bool>())) { |
| rtp_packet->SetExtension<AbsoluteSendTime>(prng_.Rand(0x00ffffff)); |
| } |
| |
| if (extension_map.IsRegistered(VideoOrientation::kId) && |
| (all_configured_exts || prng_.Rand<bool>())) { |
| rtp_packet->SetExtension<VideoOrientation>(prng_.Rand(3)); |
| } |
| |
| if (extension_map.IsRegistered(TransportSequenceNumber::kId) && |
| (all_configured_exts || prng_.Rand<bool>())) { |
| rtp_packet->SetExtension<TransportSequenceNumber>(prng_.Rand<uint16_t>()); |
| } |
| |
| if (extension_map.IsRegistered(RtpDependencyDescriptorExtension::kId) && |
| (all_configured_exts || prng_.Rand<bool>())) { |
| std::vector<uint8_t> raw_data(3 + prng_.Rand(6)); |
| for (uint8_t& d : raw_data) { |
| d = prng_.Rand<uint8_t>(); |
| } |
| rtp_packet->SetRawExtension<RtpDependencyDescriptorExtension>(raw_data); |
| } |
| |
| 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)); |
| } |
| |
| std::unique_ptr<RtcEventRtpPacketIncoming> EventGenerator::NewRtpPacketIncoming( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extension_map, |
| bool all_configured_exts) { |
| 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, all_configured_exts); |
| |
| return std::make_unique<RtcEventRtpPacketIncoming>(rtp_packet); |
| } |
| |
| std::unique_ptr<RtcEventRtpPacketOutgoing> EventGenerator::NewRtpPacketOutgoing( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extension_map, |
| bool all_configured_exts) { |
| 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); |
| RandomizeRtpPacket(payload_size, padding_size, ssrc, extension_map, |
| &rtp_packet, all_configured_exts); |
| |
| int probe_cluster_id = prng_.Rand(0, 100000); |
| return std::make_unique<RtcEventRtpPacketOutgoing>(rtp_packet, |
| probe_cluster_id); |
| } |
| |
| RtpHeaderExtensionMap EventGenerator::NewRtpHeaderExtensionMap( |
| bool configure_all, |
| const std::vector<RTPExtensionType>& excluded_extensions) { |
| 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)); |
| |
| auto not_excluded = [&](RTPExtensionType type) -> bool { |
| return !absl::c_linear_search(excluded_extensions, type); |
| }; |
| |
| if (not_excluded(AudioLevelExtension::kId) && |
| (configure_all || prng_.Rand<bool>())) { |
| extension_map.Register<AudioLevelExtension>(id[0]); |
| } |
| if (not_excluded(TransmissionOffset::kId) && |
| (configure_all || prng_.Rand<bool>())) { |
| extension_map.Register<TransmissionOffset>(id[1]); |
| } |
| if (not_excluded(AbsoluteSendTime::kId) && |
| (configure_all || prng_.Rand<bool>())) { |
| extension_map.Register<AbsoluteSendTime>(id[2]); |
| } |
| if (not_excluded(VideoOrientation::kId) && |
| (configure_all || prng_.Rand<bool>())) { |
| extension_map.Register<VideoOrientation>(id[3]); |
| } |
| if (not_excluded(TransportSequenceNumber::kId) && |
| (configure_all || prng_.Rand<bool>())) { |
| extension_map.Register<TransportSequenceNumber>(id[4]); |
| } |
| if (not_excluded(RtpDependencyDescriptorExtension::kId) && |
| (configure_all || prng_.Rand<bool>())) { |
| extension_map.Register<RtpDependencyDescriptorExtension>(id[5]); |
| } |
| |
| return extension_map; |
| } |
| |
| std::unique_ptr<RtcEventAudioReceiveStreamConfig> |
| EventGenerator::NewAudioReceiveStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = std::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 std::make_unique<RtcEventAudioReceiveStreamConfig>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventAudioSendStreamConfig> |
| EventGenerator::NewAudioSendStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = std::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 std::make_unique<RtcEventAudioSendStreamConfig>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventVideoReceiveStreamConfig> |
| EventGenerator::NewVideoReceiveStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = std::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 std::make_unique<RtcEventVideoReceiveStreamConfig>(std::move(config)); |
| } |
| |
| std::unique_ptr<RtcEventVideoSendStreamConfig> |
| EventGenerator::NewVideoSendStreamConfig( |
| uint32_t ssrc, |
| const RtpHeaderExtensionMap& extensions) { |
| auto config = std::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 std::make_unique<RtcEventVideoSendStreamConfig>(std::move(config)); |
| } |
| |
| void EventVerifier::VerifyLoggedAlrStateEvent( |
| const RtcEventAlrState& original_event, |
| const LoggedAlrStateEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.in_alr(), logged_event.in_alr); |
| } |
| |
| void EventVerifier::VerifyLoggedAudioPlayoutEvent( |
| const RtcEventAudioPlayout& original_event, |
| const LoggedAudioPlayoutEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.ssrc(), logged_event.ssrc); |
| } |
| |
| void EventVerifier::VerifyLoggedAudioNetworkAdaptationEvent( |
| const RtcEventAudioNetworkAdaptation& original_event, |
| const LoggedAudioNetworkAdaptationEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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); |
| |
| // uplink_packet_loss_fraction |
| ASSERT_EQ(original_event.config().uplink_packet_loss_fraction.has_value(), |
| logged_event.config.uplink_packet_loss_fraction.has_value()); |
| if (original_event.config().uplink_packet_loss_fraction.has_value()) { |
| const float original = |
| original_event.config().uplink_packet_loss_fraction.value(); |
| const float logged = |
| logged_event.config.uplink_packet_loss_fraction.value(); |
| const float uplink_packet_loss_fraction_delta = std::abs(original - logged); |
| EXPECT_LE(uplink_packet_loss_fraction_delta, 0.0001f); |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedBweDelayBasedUpdate( |
| const RtcEventBweUpdateDelayBased& original_event, |
| const LoggedBweDelayBasedUpdate& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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 EventVerifier::VerifyLoggedBweLossBasedUpdate( |
| const RtcEventBweUpdateLossBased& original_event, |
| const LoggedBweLossBasedUpdate& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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 EventVerifier::VerifyLoggedBweProbeClusterCreatedEvent( |
| const RtcEventProbeClusterCreated& original_event, |
| const LoggedBweProbeClusterCreatedEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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 EventVerifier::VerifyLoggedBweProbeFailureEvent( |
| const RtcEventProbeResultFailure& original_event, |
| const LoggedBweProbeFailureEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.id(), logged_event.id); |
| EXPECT_EQ(original_event.failure_reason(), logged_event.failure_reason); |
| } |
| |
| void EventVerifier::VerifyLoggedBweProbeSuccessEvent( |
| const RtcEventProbeResultSuccess& original_event, |
| const LoggedBweProbeSuccessEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.id(), logged_event.id); |
| EXPECT_EQ(original_event.bitrate_bps(), logged_event.bitrate_bps); |
| } |
| |
| void EventVerifier::VerifyLoggedDtlsTransportState( |
| const RtcEventDtlsTransportState& original_event, |
| const LoggedDtlsTransportState& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.dtls_transport_state(), |
| logged_event.dtls_transport_state); |
| } |
| |
| void EventVerifier::VerifyLoggedDtlsWritableState( |
| const RtcEventDtlsWritableState& original_event, |
| const LoggedDtlsWritableState& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.writable(), logged_event.writable); |
| } |
| |
| void EventVerifier::VerifyLoggedFrameDecoded( |
| const RtcEventFrameDecoded& original_event, |
| const LoggedFrameDecoded& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.ssrc(), logged_event.ssrc); |
| EXPECT_EQ(original_event.render_time_ms(), logged_event.render_time_ms); |
| EXPECT_EQ(original_event.width(), logged_event.width); |
| EXPECT_EQ(original_event.height(), logged_event.height); |
| EXPECT_EQ(original_event.codec(), logged_event.codec); |
| EXPECT_EQ(original_event.qp(), logged_event.qp); |
| } |
| |
| void EventVerifier::VerifyLoggedIceCandidatePairConfig( |
| const RtcEventIceCandidatePairConfig& original_event, |
| const LoggedIceCandidatePairConfig& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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 EventVerifier::VerifyLoggedIceCandidatePairEvent( |
| const RtcEventIceCandidatePair& original_event, |
| const LoggedIceCandidatePairEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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); |
| if (encoding_type_ == RtcEventLog::EncodingType::NewFormat) { |
| EXPECT_EQ(original_event.transaction_id(), logged_event.transaction_id); |
| } |
| } |
| |
| template <typename Event> |
| void VerifyLoggedRtpHeader(const Event& 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.header_length(), logged_header.headerLength); |
| |
| // TransmissionOffset header extension. |
| ASSERT_EQ(original_header.template HasExtension<TransmissionOffset>(), |
| logged_header.extension.hasTransmissionTimeOffset); |
| if (logged_header.extension.hasTransmissionTimeOffset) { |
| int32_t offset; |
| ASSERT_TRUE( |
| original_header.template GetExtension<TransmissionOffset>(&offset)); |
| EXPECT_EQ(offset, logged_header.extension.transmissionTimeOffset); |
| } |
| |
| // AbsoluteSendTime header extension. |
| ASSERT_EQ(original_header.template HasExtension<AbsoluteSendTime>(), |
| logged_header.extension.hasAbsoluteSendTime); |
| if (logged_header.extension.hasAbsoluteSendTime) { |
| uint32_t sendtime; |
| ASSERT_TRUE( |
| original_header.template GetExtension<AbsoluteSendTime>(&sendtime)); |
| EXPECT_EQ(sendtime, logged_header.extension.absoluteSendTime); |
| } |
| |
| // TransportSequenceNumber header extension. |
| ASSERT_EQ(original_header.template HasExtension<TransportSequenceNumber>(), |
| logged_header.extension.hasTransportSequenceNumber); |
| if (logged_header.extension.hasTransportSequenceNumber) { |
| uint16_t seqnum; |
| ASSERT_TRUE(original_header.template GetExtension<TransportSequenceNumber>( |
| &seqnum)); |
| EXPECT_EQ(seqnum, logged_header.extension.transportSequenceNumber); |
| } |
| |
| // AudioLevel header extension. |
| ASSERT_EQ(original_header.template HasExtension<AudioLevelExtension>(), |
| logged_header.extension.audio_level().has_value()); |
| if (logged_header.extension.audio_level()) { |
| AudioLevel audio_level; |
| ASSERT_TRUE(original_header.template GetExtension<AudioLevelExtension>( |
| &audio_level)); |
| EXPECT_EQ(audio_level.voice_activity(), |
| logged_header.extension.audio_level()->voice_activity()); |
| EXPECT_EQ(audio_level.level(), |
| logged_header.extension.audio_level()->level()); |
| } |
| |
| // VideoOrientation header extension. |
| ASSERT_EQ(original_header.template HasExtension<VideoOrientation>(), |
| logged_header.extension.hasVideoRotation); |
| if (logged_header.extension.hasVideoRotation) { |
| uint8_t rotation; |
| ASSERT_TRUE( |
| original_header.template GetExtension<VideoOrientation>(&rotation)); |
| EXPECT_EQ(ConvertCVOByteToVideoRotation(rotation), |
| logged_header.extension.videoRotation); |
| } |
| } |
| |
| template <typename Event> |
| void EventVerifier::VerifyLoggedDependencyDescriptor( |
| const Event& packet, |
| const std::vector<uint8_t>& logged_dd) const { |
| if (expect_dependency_descriptor_rtp_header_extension_is_set_) { |
| rtc::ArrayView<const uint8_t> original = |
| packet.template GetRawExtension<RtpDependencyDescriptorExtension>(); |
| EXPECT_THAT(logged_dd, ElementsAreArray(original)); |
| } else { |
| EXPECT_THAT(logged_dd, IsEmpty()); |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedRouteChangeEvent( |
| const RtcEventRouteChange& original_event, |
| const LoggedRouteChangeEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.connected(), logged_event.connected); |
| EXPECT_EQ(original_event.overhead(), logged_event.overhead); |
| } |
| |
| void EventVerifier::VerifyLoggedRemoteEstimateEvent( |
| const RtcEventRemoteEstimate& original_event, |
| const LoggedRemoteEstimateEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.link_capacity_lower_, |
| logged_event.link_capacity_lower); |
| EXPECT_EQ(original_event.link_capacity_upper_, |
| logged_event.link_capacity_upper); |
| } |
| |
| void EventVerifier::VerifyLoggedRtpPacketIncoming( |
| const RtcEventRtpPacketIncoming& original_event, |
| const LoggedRtpPacketIncoming& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| |
| EXPECT_EQ(original_event.header_length(), 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, logged_event.rtp.header); |
| VerifyLoggedDependencyDescriptor( |
| original_event, logged_event.rtp.dependency_descriptor_wire_format); |
| } |
| |
| void EventVerifier::VerifyLoggedRtpPacketOutgoing( |
| const RtcEventRtpPacketOutgoing& original_event, |
| const LoggedRtpPacketOutgoing& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| |
| EXPECT_EQ(original_event.header_length(), 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, logged_event.rtp.header); |
| VerifyLoggedDependencyDescriptor( |
| original_event, logged_event.rtp.dependency_descriptor_wire_format); |
| } |
| |
| void EventVerifier::VerifyLoggedGenericPacketSent( |
| const RtcEventGenericPacketSent& original_event, |
| const LoggedGenericPacketSent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.packet_number(), logged_event.packet_number); |
| EXPECT_EQ(original_event.overhead_length(), logged_event.overhead_length); |
| EXPECT_EQ(original_event.payload_length(), logged_event.payload_length); |
| EXPECT_EQ(original_event.padding_length(), logged_event.padding_length); |
| } |
| |
| void EventVerifier::VerifyLoggedGenericPacketReceived( |
| const RtcEventGenericPacketReceived& original_event, |
| const LoggedGenericPacketReceived& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.packet_number(), logged_event.packet_number); |
| EXPECT_EQ(static_cast<int>(original_event.packet_length()), |
| logged_event.packet_length); |
| } |
| |
| void EventVerifier::VerifyLoggedGenericAckReceived( |
| const RtcEventGenericAckReceived& original_event, |
| const LoggedGenericAckReceived& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| EXPECT_EQ(original_event.packet_number(), logged_event.packet_number); |
| EXPECT_EQ(original_event.acked_packet_number(), |
| logged_event.acked_packet_number); |
| EXPECT_EQ(original_event.receive_acked_packet_time_ms(), |
| logged_event.receive_acked_packet_time_ms); |
| } |
| |
| void EventVerifier::VerifyLoggedRtcpPacketIncoming( |
| const RtcEventRtcpPacketIncoming& original_event, |
| const LoggedRtcpPacketIncoming& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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 EventVerifier::VerifyLoggedRtcpPacketOutgoing( |
| const RtcEventRtcpPacketOutgoing& original_event, |
| const LoggedRtcpPacketOutgoing& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), 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 EventVerifier::VerifyReportBlock( |
| const rtcp::ReportBlock& original_report_block, |
| const rtcp::ReportBlock& logged_report_block) { |
| EXPECT_EQ(original_report_block.source_ssrc(), |
| logged_report_block.source_ssrc()); |
| EXPECT_EQ(original_report_block.fraction_lost(), |
| logged_report_block.fraction_lost()); |
| EXPECT_EQ(original_report_block.cumulative_lost(), |
| logged_report_block.cumulative_lost()); |
| EXPECT_EQ(original_report_block.extended_high_seq_num(), |
| logged_report_block.extended_high_seq_num()); |
| EXPECT_EQ(original_report_block.jitter(), logged_report_block.jitter()); |
| EXPECT_EQ(original_report_block.last_sr(), logged_report_block.last_sr()); |
| EXPECT_EQ(original_report_block.delay_since_last_sr(), |
| logged_report_block.delay_since_last_sr()); |
| } |
| |
| void EventVerifier::VerifyLoggedSenderReport( |
| int64_t log_time_ms, |
| const rtcp::SenderReport& original_sr, |
| const LoggedRtcpPacketSenderReport& logged_sr) { |
| EXPECT_EQ(log_time_ms, logged_sr.log_time_ms()); |
| EXPECT_EQ(original_sr.sender_ssrc(), logged_sr.sr.sender_ssrc()); |
| EXPECT_EQ(original_sr.ntp(), logged_sr.sr.ntp()); |
| EXPECT_EQ(original_sr.rtp_timestamp(), logged_sr.sr.rtp_timestamp()); |
| EXPECT_EQ(original_sr.sender_packet_count(), |
| logged_sr.sr.sender_packet_count()); |
| EXPECT_EQ(original_sr.sender_octet_count(), |
| logged_sr.sr.sender_octet_count()); |
| ASSERT_EQ(original_sr.report_blocks().size(), |
| logged_sr.sr.report_blocks().size()); |
| for (size_t i = 0; i < original_sr.report_blocks().size(); i++) { |
| VerifyReportBlock(original_sr.report_blocks()[i], |
| logged_sr.sr.report_blocks()[i]); |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedReceiverReport( |
| int64_t log_time_ms, |
| const rtcp::ReceiverReport& original_rr, |
| const LoggedRtcpPacketReceiverReport& logged_rr) { |
| EXPECT_EQ(log_time_ms, logged_rr.log_time_ms()); |
| EXPECT_EQ(original_rr.sender_ssrc(), logged_rr.rr.sender_ssrc()); |
| ASSERT_EQ(original_rr.report_blocks().size(), |
| logged_rr.rr.report_blocks().size()); |
| for (size_t i = 0; i < original_rr.report_blocks().size(); i++) { |
| VerifyReportBlock(original_rr.report_blocks()[i], |
| logged_rr.rr.report_blocks()[i]); |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedExtendedReports( |
| int64_t log_time_ms, |
| const rtcp::ExtendedReports& original_xr, |
| const LoggedRtcpPacketExtendedReports& logged_xr) { |
| EXPECT_EQ(log_time_ms, logged_xr.log_time_ms()); |
| EXPECT_EQ(original_xr.sender_ssrc(), logged_xr.xr.sender_ssrc()); |
| |
| EXPECT_EQ(original_xr.rrtr().has_value(), logged_xr.xr.rrtr().has_value()); |
| if (original_xr.rrtr().has_value() && logged_xr.xr.rrtr().has_value()) { |
| EXPECT_EQ(original_xr.rrtr()->ntp(), logged_xr.xr.rrtr()->ntp()); |
| } |
| |
| const auto& original_subblocks = original_xr.dlrr().sub_blocks(); |
| const auto& logged_subblocks = logged_xr.xr.dlrr().sub_blocks(); |
| ASSERT_EQ(original_subblocks.size(), logged_subblocks.size()); |
| for (size_t i = 0; i < original_subblocks.size(); i++) { |
| EXPECT_EQ(original_subblocks[i].ssrc, logged_subblocks[i].ssrc); |
| EXPECT_EQ(original_subblocks[i].last_rr, logged_subblocks[i].last_rr); |
| EXPECT_EQ(original_subblocks[i].delay_since_last_rr, |
| logged_subblocks[i].delay_since_last_rr); |
| } |
| |
| EXPECT_EQ(original_xr.target_bitrate().has_value(), |
| logged_xr.xr.target_bitrate().has_value()); |
| if (original_xr.target_bitrate().has_value() && |
| logged_xr.xr.target_bitrate().has_value()) { |
| const auto& original_bitrates = |
| original_xr.target_bitrate()->GetTargetBitrates(); |
| const auto& logged_bitrates = |
| logged_xr.xr.target_bitrate()->GetTargetBitrates(); |
| ASSERT_EQ(original_bitrates.size(), logged_bitrates.size()); |
| for (size_t i = 0; i < original_bitrates.size(); i++) { |
| EXPECT_EQ(original_bitrates[i].spatial_layer, |
| logged_bitrates[i].spatial_layer); |
| EXPECT_EQ(original_bitrates[i].temporal_layer, |
| logged_bitrates[i].temporal_layer); |
| EXPECT_EQ(original_bitrates[i].target_bitrate_kbps, |
| logged_bitrates[i].target_bitrate_kbps); |
| } |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedFir(int64_t log_time_ms, |
| const rtcp::Fir& original_fir, |
| const LoggedRtcpPacketFir& logged_fir) { |
| EXPECT_EQ(log_time_ms, logged_fir.log_time_ms()); |
| EXPECT_EQ(original_fir.sender_ssrc(), logged_fir.fir.sender_ssrc()); |
| const auto& original_requests = original_fir.requests(); |
| const auto& logged_requests = logged_fir.fir.requests(); |
| ASSERT_EQ(original_requests.size(), logged_requests.size()); |
| for (size_t i = 0; i < original_requests.size(); i++) { |
| EXPECT_EQ(original_requests[i].ssrc, logged_requests[i].ssrc); |
| EXPECT_EQ(original_requests[i].seq_nr, logged_requests[i].seq_nr); |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedPli(int64_t log_time_ms, |
| const rtcp::Pli& original_pli, |
| const LoggedRtcpPacketPli& logged_pli) { |
| EXPECT_EQ(log_time_ms, logged_pli.log_time_ms()); |
| EXPECT_EQ(original_pli.sender_ssrc(), logged_pli.pli.sender_ssrc()); |
| EXPECT_EQ(original_pli.media_ssrc(), logged_pli.pli.media_ssrc()); |
| } |
| |
| void EventVerifier::VerifyLoggedBye(int64_t log_time_ms, |
| const rtcp::Bye& original_bye, |
| const LoggedRtcpPacketBye& logged_bye) { |
| EXPECT_EQ(log_time_ms, logged_bye.log_time_ms()); |
| EXPECT_EQ(original_bye.sender_ssrc(), logged_bye.bye.sender_ssrc()); |
| EXPECT_EQ(original_bye.csrcs(), logged_bye.bye.csrcs()); |
| EXPECT_EQ(original_bye.reason(), logged_bye.bye.reason()); |
| } |
| |
| void EventVerifier::VerifyLoggedNack(int64_t log_time_ms, |
| const rtcp::Nack& original_nack, |
| const LoggedRtcpPacketNack& logged_nack) { |
| EXPECT_EQ(log_time_ms, logged_nack.log_time_ms()); |
| EXPECT_EQ(original_nack.packet_ids(), logged_nack.nack.packet_ids()); |
| } |
| |
| void EventVerifier::VerifyLoggedTransportFeedback( |
| int64_t log_time_ms, |
| const rtcp::TransportFeedback& original_transport_feedback, |
| const LoggedRtcpPacketTransportFeedback& logged_transport_feedback) { |
| EXPECT_EQ(log_time_ms, logged_transport_feedback.log_time_ms()); |
| ASSERT_EQ( |
| original_transport_feedback.GetReceivedPackets().size(), |
| logged_transport_feedback.transport_feedback.GetReceivedPackets().size()); |
| for (size_t i = 0; |
| i < original_transport_feedback.GetReceivedPackets().size(); i++) { |
| EXPECT_EQ( |
| original_transport_feedback.GetReceivedPackets()[i].sequence_number(), |
| logged_transport_feedback.transport_feedback.GetReceivedPackets()[i] |
| .sequence_number()); |
| EXPECT_EQ( |
| original_transport_feedback.GetReceivedPackets()[i].delta(), |
| logged_transport_feedback.transport_feedback.GetReceivedPackets()[i] |
| .delta()); |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedRemb(int64_t log_time_ms, |
| const rtcp::Remb& original_remb, |
| const LoggedRtcpPacketRemb& logged_remb) { |
| EXPECT_EQ(log_time_ms, logged_remb.log_time_ms()); |
| EXPECT_EQ(original_remb.ssrcs(), logged_remb.remb.ssrcs()); |
| EXPECT_EQ(original_remb.bitrate_bps(), logged_remb.remb.bitrate_bps()); |
| } |
| |
| void EventVerifier::VerifyLoggedLossNotification( |
| int64_t log_time_ms, |
| const rtcp::LossNotification& original_loss_notification, |
| const LoggedRtcpPacketLossNotification& logged_loss_notification) { |
| EXPECT_EQ(log_time_ms, logged_loss_notification.log_time_ms()); |
| EXPECT_EQ(original_loss_notification.last_decoded(), |
| logged_loss_notification.loss_notification.last_decoded()); |
| EXPECT_EQ(original_loss_notification.last_received(), |
| logged_loss_notification.loss_notification.last_received()); |
| EXPECT_EQ(original_loss_notification.decodability_flag(), |
| logged_loss_notification.loss_notification.decodability_flag()); |
| } |
| |
| void EventVerifier::VerifyLoggedStartEvent( |
| int64_t start_time_us, |
| int64_t utc_start_time_us, |
| const LoggedStartEvent& logged_event) const { |
| EXPECT_EQ(start_time_us / 1000, logged_event.log_time_ms()); |
| if (encoding_type_ == RtcEventLog::EncodingType::NewFormat) { |
| EXPECT_EQ(utc_start_time_us / 1000, logged_event.utc_start_time.ms()); |
| } |
| } |
| |
| void EventVerifier::VerifyLoggedStopEvent( |
| int64_t stop_time_us, |
| const LoggedStopEvent& logged_event) const { |
| 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.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 EventVerifier::VerifyLoggedAudioRecvConfig( |
| const RtcEventAudioReceiveStreamConfig& original_event, |
| const LoggedAudioRecvConfig& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| VerifyLoggedStreamConfig(original_event.config(), logged_event.config); |
| } |
| |
| void EventVerifier::VerifyLoggedAudioSendConfig( |
| const RtcEventAudioSendStreamConfig& original_event, |
| const LoggedAudioSendConfig& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| VerifyLoggedStreamConfig(original_event.config(), logged_event.config); |
| } |
| |
| void EventVerifier::VerifyLoggedVideoRecvConfig( |
| const RtcEventVideoReceiveStreamConfig& original_event, |
| const LoggedVideoRecvConfig& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| VerifyLoggedStreamConfig(original_event.config(), logged_event.config); |
| } |
| |
| void EventVerifier::VerifyLoggedVideoSendConfig( |
| const RtcEventVideoSendStreamConfig& original_event, |
| const LoggedVideoSendConfig& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms()); |
| VerifyLoggedStreamConfig(original_event.config(), logged_event.config); |
| } |
| |
| void EventVerifier::VerifyLoggedNetEqSetMinimumDelay( |
| const RtcEventNetEqSetMinimumDelay& original_event, |
| const LoggedNetEqSetMinimumDelayEvent& logged_event) const { |
| EXPECT_EQ(original_event.timestamp_ms(), logged_event.timestamp.ms()); |
| EXPECT_EQ(original_event.remote_ssrc(), logged_event.remote_ssrc); |
| EXPECT_EQ(original_event.minimum_delay_ms(), logged_event.minimum_delay_ms); |
| } |
| |
| } // namespace test |
| } // namespace webrtc |