diff --git a/call/call.cc b/call/call.cc index 1bfde2e692..8bfab8a493 100644 --- a/call/call.cc +++ b/call/call.cc @@ -1303,7 +1303,7 @@ PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type, } if (rtcp_delivered) - event_log_->LogRtcpPacket(kIncomingPacket, packet, length); + event_log_->LogIncomingRtcpPacket(rtc::MakeArrayView(packet, length)); return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR; } @@ -1352,7 +1352,7 @@ PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type, if (audio_receiver_controller_.OnRtpPacket(*parsed_packet)) { received_bytes_per_second_counter_.Add(static_cast(length)); received_audio_bytes_per_second_counter_.Add(static_cast(length)); - event_log_->LogRtpHeader(kIncomingPacket, packet, length); + event_log_->LogIncomingRtpHeader(*parsed_packet); const int64_t arrival_time_ms = parsed_packet->arrival_time_ms(); if (!first_received_rtp_audio_ms_) { first_received_rtp_audio_ms_.emplace(arrival_time_ms); @@ -1364,7 +1364,7 @@ PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type, if (video_receiver_controller_.OnRtpPacket(*parsed_packet)) { received_bytes_per_second_counter_.Add(static_cast(length)); received_video_bytes_per_second_counter_.Add(static_cast(length)); - event_log_->LogRtpHeader(kIncomingPacket, packet, length); + event_log_->LogIncomingRtpHeader(*parsed_packet); const int64_t arrival_time_ms = parsed_packet->arrival_time_ms(); if (!first_received_rtp_video_ms_) { first_received_rtp_video_ms_.emplace(arrival_time_ms); diff --git a/logging/BUILD.gn b/logging/BUILD.gn index dc5f8adee4..eb4cec277c 100644 --- a/logging/BUILD.gn +++ b/logging/BUILD.gn @@ -31,6 +31,7 @@ rtc_source_set("rtc_event_log_api") { ] deps = [ "..:webrtc_common", + "../api:array_view", "../api:libjingle_peerconnection_api", "../call:video_stream_api", "../rtc_base:rtc_base_approved", diff --git a/logging/rtc_event_log/mock/mock_rtc_event_log.h b/logging/rtc_event_log/mock/mock_rtc_event_log.h index eb0d9b9596..d84a39e5be 100644 --- a/logging/rtc_event_log/mock/mock_rtc_event_log.h +++ b/logging/rtc_event_log/mock/mock_rtc_event_log.h @@ -16,6 +16,8 @@ #include "logging/rtc_event_log/rtc_event_log.h" #include "logging/rtc_event_log/rtc_stream_config.h" #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "test/gmock.h" namespace webrtc { @@ -42,21 +44,16 @@ class MockRtcEventLog : public RtcEventLog { MOCK_METHOD1(LogAudioSendStreamConfig, void(const rtclog::StreamConfig& config)); - MOCK_METHOD3(LogRtpHeader, - void(PacketDirection direction, - const uint8_t* header, - size_t packet_length)); + MOCK_METHOD1(LogIncomingRtpHeader, void(const RtpPacketReceived& packet)); - MOCK_METHOD4(LogRtpHeader, - void(PacketDirection direction, - const uint8_t* header, - size_t packet_length, - int probe_cluster_id)); + MOCK_METHOD2(LogOutgoingRtpHeader, + void(const RtpPacketToSend& packet, int probe_cluster_id)); - MOCK_METHOD3(LogRtcpPacket, - void(PacketDirection direction, - const uint8_t* packet, - size_t length)); + MOCK_METHOD1(LogIncomingRtcpPacket, + void(rtc::ArrayView packet)); + + MOCK_METHOD1(LogOutgoingRtcpPacket, + void(rtc::ArrayView packet)); MOCK_METHOD1(LogAudioPlayout, void(uint32_t ssrc)); diff --git a/logging/rtc_event_log/rtc_event_log.cc b/logging/rtc_event_log/rtc_event_log.cc index c6d67f21e1..5cb398da9f 100644 --- a/logging/rtc_event_log/rtc_event_log.cc +++ b/logging/rtc_event_log/rtc_event_log.cc @@ -33,6 +33,8 @@ #include "modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" #include "modules/rtp_rtcp/source/rtcp_packet/sdes.h" #include "modules/rtp_rtcp/source/rtcp_packet/sender_report.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 "rtc_base/constructormagic.h" #include "rtc_base/event.h" @@ -112,16 +114,27 @@ class RtcEventLogImpl final : public RtcEventLog { void LogVideoSendStreamConfig(const rtclog::StreamConfig& config) override; void LogAudioReceiveStreamConfig(const rtclog::StreamConfig& config) override; void LogAudioSendStreamConfig(const rtclog::StreamConfig& config) override; + // TODO(terelius): This can be removed as soon as the interface has been + // updated. void LogRtpHeader(PacketDirection direction, const uint8_t* header, size_t packet_length) override; + // TODO(terelius): This can be made private, non-virtual as soon as the + // interface has been updated. void LogRtpHeader(PacketDirection direction, const uint8_t* header, size_t packet_length, int probe_cluster_id) override; + void LogIncomingRtpHeader(const RtpPacketReceived& packet) override; + void LogOutgoingRtpHeader(const RtpPacketToSend& packet, + int probe_cluster_id) override; + // TODO(terelius): This can be made private, non-virtual as soon as the + // interface has been updated. void LogRtcpPacket(PacketDirection direction, const uint8_t* packet, size_t length) override; + void LogIncomingRtcpPacket(rtc::ArrayView packet) override; + void LogOutgoingRtcpPacket(rtc::ArrayView packet) override; void LogAudioPlayout(uint32_t ssrc) override; void LogLossBasedBweUpdate(int32_t bitrate_bps, uint8_t fraction_loss, @@ -418,6 +431,16 @@ void RtcEventLogImpl::LogAudioSendStreamConfig( StoreEvent(std::move(event)); } +void RtcEventLogImpl::LogIncomingRtpHeader(const RtpPacketReceived& packet) { + LogRtpHeader(kIncomingPacket, packet.data(), packet.size(), + PacedPacketInfo::kNotAProbe); +} + +void RtcEventLogImpl::LogOutgoingRtpHeader(const RtpPacketToSend& packet, + int probe_cluster_id) { + LogRtpHeader(kOutgoingPacket, packet.data(), packet.size(), probe_cluster_id); +} + void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, const uint8_t* header, size_t packet_length) { @@ -455,6 +478,16 @@ void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, StoreEvent(std::move(rtp_event)); } +void RtcEventLogImpl::LogIncomingRtcpPacket( + rtc::ArrayView packet) { + LogRtcpPacket(kIncomingPacket, packet.data(), packet.size()); +} + +void RtcEventLogImpl::LogOutgoingRtcpPacket( + rtc::ArrayView packet) { + LogRtcpPacket(kOutgoingPacket, packet.data(), packet.size()); +} + void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction, const uint8_t* packet, size_t length) { diff --git a/logging/rtc_event_log/rtc_event_log.h b/logging/rtc_event_log/rtc_event_log.h index b5336007d2..31caa447cd 100644 --- a/logging/rtc_event_log/rtc_event_log.h +++ b/logging/rtc_event_log/rtc_event_log.h @@ -15,6 +15,7 @@ #include #include +#include "api/array_view.h" // TODO(eladalon): Get rid of this later in the CL-stack. #include "api/rtpparameters.h" #include "common_types.h" // NOLINT(build/include) @@ -30,6 +31,8 @@ struct StreamConfig; class Clock; struct AudioEncoderRuntimeConfig; +class RtpPacketReceived; +class RtpPacketToSend; enum class MediaType; enum class BandwidthUsage; @@ -49,7 +52,7 @@ class RtcEventLog { static std::unique_ptr Create(); // TODO(nisse): webrtc::Clock is deprecated. Delete this method and // above forward declaration of Clock when - // webrtc/system_wrappers/include/clock.h is deleted. + // system_wrappers/include/clock.h is deleted. static std::unique_ptr Create(const Clock* clock) { return Create(); } @@ -98,23 +101,33 @@ class RtcEventLog { // Logs configuration information for an audio send stream. virtual void LogAudioSendStreamConfig(const rtclog::StreamConfig& config) = 0; - // Logs the header of an incoming or outgoing RTP packet. packet_length + RTC_DEPRECATED virtual void LogRtpHeader(PacketDirection direction, + const uint8_t* header, + size_t packet_length) {} + + RTC_DEPRECATED virtual void LogRtpHeader(PacketDirection direction, + const uint8_t* header, + size_t packet_length, + int probe_cluster_id) {} + + // Logs the header of an incoming RTP packet. |packet_length| // is the total length of the packet, including both header and payload. - virtual void LogRtpHeader(PacketDirection direction, - const uint8_t* header, - size_t packet_length) = 0; + virtual void LogIncomingRtpHeader(const RtpPacketReceived& packet) = 0; - // Same as above but used on the sender side to log packets that are part of - // a probe cluster. - virtual void LogRtpHeader(PacketDirection direction, - const uint8_t* header, - size_t packet_length, - int probe_cluster_id) = 0; + // Logs the header of an incoming RTP packet. |packet_length| + // is the total length of the packet, including both header and payload. + virtual void LogOutgoingRtpHeader(const RtpPacketToSend& packet, + int probe_cluster_id) = 0; - // Logs an incoming or outgoing RTCP packet. - virtual void LogRtcpPacket(PacketDirection direction, - const uint8_t* packet, - size_t length) = 0; + RTC_DEPRECATED virtual void LogRtcpPacket(PacketDirection direction, + const uint8_t* header, + size_t packet_length) {} + + // Logs an incoming RTCP packet. + virtual void LogIncomingRtcpPacket(rtc::ArrayView packet) = 0; + + // Logs an outgoing RTCP packet. + virtual void LogOutgoingRtcpPacket(rtc::ArrayView packet) = 0; // Logs an audio playout event. virtual void LogAudioPlayout(uint32_t ssrc) = 0; @@ -164,16 +177,11 @@ class RtcEventLogNullImpl : public RtcEventLog { void LogAudioReceiveStreamConfig( const rtclog::StreamConfig& config) override {} void LogAudioSendStreamConfig(const rtclog::StreamConfig& config) override {} - void LogRtpHeader(PacketDirection direction, - const uint8_t* header, - size_t packet_length) override {} - void LogRtpHeader(PacketDirection direction, - const uint8_t* header, - size_t packet_length, - int probe_cluster_id) override {} - void LogRtcpPacket(PacketDirection direction, - const uint8_t* packet, - size_t length) override {} + void LogIncomingRtpHeader(const RtpPacketReceived& packet) override {} + void LogOutgoingRtpHeader(const RtpPacketToSend& packet, + int probe_cluster_id) override {} + void LogIncomingRtcpPacket(rtc::ArrayView packet) override {} + void LogOutgoingRtcpPacket(rtc::ArrayView packet) override {} void LogAudioPlayout(uint32_t ssrc) override {} void LogLossBasedBweUpdate(int32_t bitrate_bps, uint8_t fraction_loss, diff --git a/logging/rtc_event_log/rtc_event_log_unittest.cc b/logging/rtc_event_log/rtc_event_log_unittest.cc index 7624420ede..99e3e7eeab 100644 --- a/logging/rtc_event_log/rtc_event_log_unittest.cc +++ b/logging/rtc_event_log/rtc_event_log_unittest.cc @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -25,10 +26,12 @@ #include "modules/rtp_rtcp/source/rtcp_packet.h" #include "modules/rtp_rtcp/source/rtcp_packet/sender_report.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/fakeclock.h" +#include "rtc_base/ptr_util.h" #include "rtc_base/random.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" @@ -44,72 +47,105 @@ namespace webrtc { namespace { +const uint8_t kTransmissionTimeOffsetExtensionId = 1; +const uint8_t kAbsoluteSendTimeExtensionId = 14; +const uint8_t kTransportSequenceNumberExtensionId = 13; +const uint8_t kAudioLevelExtensionId = 9; +const uint8_t kVideoRotationExtensionId = 5; + +const uint8_t kExtensionIds[] = { + kTransmissionTimeOffsetExtensionId, kAbsoluteSendTimeExtensionId, + kTransportSequenceNumberExtensionId, kAudioLevelExtensionId, + kVideoRotationExtensionId}; const RTPExtensionType kExtensionTypes[] = { RTPExtensionType::kRtpExtensionTransmissionTimeOffset, - RTPExtensionType::kRtpExtensionAudioLevel, RTPExtensionType::kRtpExtensionAbsoluteSendTime, - RTPExtensionType::kRtpExtensionVideoRotation, - RTPExtensionType::kRtpExtensionTransportSequenceNumber}; + RTPExtensionType::kRtpExtensionTransportSequenceNumber, + RTPExtensionType::kRtpExtensionAudioLevel, + RTPExtensionType::kRtpExtensionVideoRotation}; const char* kExtensionNames[] = { - RtpExtension::kTimestampOffsetUri, RtpExtension::kAudioLevelUri, - RtpExtension::kAbsSendTimeUri, RtpExtension::kVideoRotationUri, - RtpExtension::kTransportSequenceNumberUri}; + RtpExtension::kTimestampOffsetUri, RtpExtension::kAbsSendTimeUri, + RtpExtension::kTransportSequenceNumberUri, RtpExtension::kAudioLevelUri, + RtpExtension::kVideoRotationUri}; + const size_t kNumExtensions = 5; -void PrintActualEvents(const ParsedRtcEventLog& parsed_log) { - std::map actual_event_counts; - for (size_t i = 0; i < parsed_log.GetNumberOfEvents(); i++) { - actual_event_counts[parsed_log.GetEventType(i)]++; - } - printf("Actual events: "); - for (auto kv : actual_event_counts) { - printf("%d_count = %zu, ", kv.first, kv.second); - } - printf("\n"); - for (size_t i = 0; i < parsed_log.GetNumberOfEvents(); i++) { - printf("%4d ", parsed_log.GetEventType(i)); - } - printf("\n"); -} +struct BweLossEvent { + int32_t bitrate_bps; + uint8_t fraction_loss; + int32_t total_packets; +}; -void PrintExpectedEvents(size_t rtp_count, - size_t rtcp_count, - size_t playout_count, - size_t bwe_loss_count) { - printf( - "Expected events: rtp_count = %zu, rtcp_count = %zu," - "playout_count = %zu, bwe_loss_count = %zu\n", - rtp_count, rtcp_count, playout_count, bwe_loss_count); - size_t rtcp_index = 1, playout_index = 1, bwe_loss_index = 1; - printf("strt cfg cfg "); - for (size_t i = 1; i <= rtp_count; i++) { - printf(" rtp "); - if (i * rtcp_count >= rtcp_index * rtp_count) { - printf("rtcp "); - rtcp_index++; - } - if (i * playout_count >= playout_index * rtp_count) { - printf("play "); - playout_index++; - } - if (i * bwe_loss_count >= bwe_loss_index * rtp_count) { - printf("loss "); - bwe_loss_index++; - } - } - printf("end \n"); -} +// TODO(terelius): Merge with event type in parser once updated? +enum class EventType { + kIncomingRtp, + kOutgoingRtp, + kIncomingRtcp, + kOutgoingRtcp, + kAudioPlayout, + kBweLossUpdate, + kBweDelayUpdate, + kVideoRecvConfig, + kVideoSendConfig, + kAudioRecvConfig, + kAudioSendConfig, + kAudioNetworkAdaptation, + kBweProbeClusterCreated, + kBweProbeResult, +}; + +const std::map event_type_to_string( + {{EventType::kIncomingRtp, "RTP(in)"}, + {EventType::kOutgoingRtp, "RTP(out)"}, + {EventType::kIncomingRtcp, "RTCP(in)"}, + {EventType::kOutgoingRtcp, "RTCP(out)"}, + {EventType::kAudioPlayout, "PLAYOUT"}, + {EventType::kBweLossUpdate, "BWE_LOSS"}, + {EventType::kBweDelayUpdate, "BWE_DELAY"}, + {EventType::kVideoRecvConfig, "VIDEO_RECV_CONFIG"}, + {EventType::kVideoSendConfig, "VIDEO_SEND_CONFIG"}, + {EventType::kAudioRecvConfig, "AUDIO_RECV_CONFIG"}, + {EventType::kAudioSendConfig, "AUDIO_SEND_CONFIG"}, + {EventType::kAudioNetworkAdaptation, "AUDIO_NETWORK_ADAPTATION"}, + {EventType::kBweProbeClusterCreated, "BWE_PROBE_CREATED"}, + {EventType::kBweProbeResult, "BWE_PROBE_RESULT"}}); + +const std::map + parsed_event_type_to_string( + {{ParsedRtcEventLog::EventType::UNKNOWN_EVENT, "UNKNOWN_EVENT"}, + {ParsedRtcEventLog::EventType::LOG_START, "LOG_START"}, + {ParsedRtcEventLog::EventType::LOG_END, "LOG_END"}, + {ParsedRtcEventLog::EventType::RTP_EVENT, "RTP"}, + {ParsedRtcEventLog::EventType::RTCP_EVENT, "RTCP"}, + {ParsedRtcEventLog::EventType::AUDIO_PLAYOUT_EVENT, "AUDIO_PLAYOUT"}, + {ParsedRtcEventLog::EventType::LOSS_BASED_BWE_UPDATE, + "LOSS_BASED_BWE_UPDATE"}, + {ParsedRtcEventLog::EventType::DELAY_BASED_BWE_UPDATE, + "DELAY_BASED_BWE_UPDATE"}, + {ParsedRtcEventLog::EventType::VIDEO_RECEIVER_CONFIG_EVENT, + "VIDEO_RECV_CONFIG"}, + {ParsedRtcEventLog::EventType::VIDEO_SENDER_CONFIG_EVENT, + "VIDEO_SEND_CONFIG"}, + {ParsedRtcEventLog::EventType::AUDIO_RECEIVER_CONFIG_EVENT, + "AUDIO_RECV_CONFIG"}, + {ParsedRtcEventLog::EventType::AUDIO_SENDER_CONFIG_EVENT, + "AUDIO_SEND_CONFIG"}, + {ParsedRtcEventLog::EventType::AUDIO_NETWORK_ADAPTATION_EVENT, + "AUDIO_NETWORK_ADAPTATION"}, + {ParsedRtcEventLog::EventType::BWE_PROBE_CLUSTER_CREATED_EVENT, + "BWE_PROBE_CREATED"}, + {ParsedRtcEventLog::EventType::BWE_PROBE_RESULT_EVENT, + "BWE_PROBE_RESULT"}}); } // namespace -/* - * Bit number i of extension_bitvector is set to indicate the - * presence of extension number i from kExtensionTypes / kExtensionNames. - * The least significant bit extension_bitvector has number 0. - */ -RtpPacketToSend GenerateRtpPacket(const RtpHeaderExtensionMap* extensions, - uint32_t csrcs_count, - size_t packet_size, - Random* prng) { +void PrintActualEvents(const ParsedRtcEventLog& parsed_log, + std::ostream& stream); + +RtpPacketToSend GenerateOutgoingRtpPacket( + const RtpHeaderExtensionMap* extensions, + uint32_t csrcs_count, + size_t packet_size, + Random* prng) { RTC_CHECK_GE(packet_size, 16 + 4 * csrcs_count + 4 * kNumExtensions); std::vector csrcs; @@ -139,6 +175,18 @@ RtpPacketToSend GenerateRtpPacket(const RtpHeaderExtensionMap* extensions, return rtp_packet; } +RtpPacketReceived GenerateIncomingRtpPacket( + const RtpHeaderExtensionMap* extensions, + uint32_t csrcs_count, + size_t packet_size, + Random* prng) { + RtpPacketToSend packet_out = + GenerateOutgoingRtpPacket(extensions, csrcs_count, packet_size, prng); + RtpPacketReceived packet_in(extensions); + packet_in.Parse(packet_out.data(), packet_out.size()); + return packet_in; +} + rtc::Buffer GenerateRtcpPacket(Random* prng) { rtcp::ReportBlock report_block; report_block.SetMediaSsrc(prng->Rand()); // Remote SSRC. @@ -153,7 +201,7 @@ rtc::Buffer GenerateRtcpPacket(Random* prng) { return sender_report.Build(); } -void GenerateVideoReceiveConfig(uint32_t extensions_bitvector, +void GenerateVideoReceiveConfig(const RtpHeaderExtensionMap& extensions, rtclog::StreamConfig* config, Random* prng) { // Add SSRCs for the stream. @@ -168,14 +216,14 @@ void GenerateVideoReceiveConfig(uint32_t extensions_bitvector, prng->Rand(1, 127), prng->Rand(1, 127)); // Add header extensions. for (unsigned i = 0; i < kNumExtensions; i++) { - if (extensions_bitvector & (1u << i)) { - config->rtp_extensions.emplace_back(kExtensionNames[i], - prng->Rand()); + uint8_t id = extensions.GetId(kExtensionTypes[i]); + if (id != RtpHeaderExtensionMap::kInvalidId) { + config->rtp_extensions.emplace_back(kExtensionNames[i], id); } } } -void GenerateVideoSendConfig(uint32_t extensions_bitvector, +void GenerateVideoSendConfig(const RtpHeaderExtensionMap& extensions, rtclog::StreamConfig* config, Random* prng) { config->codecs.emplace_back(prng->Rand() ? "VP8" : "H264", @@ -184,14 +232,14 @@ void GenerateVideoSendConfig(uint32_t extensions_bitvector, config->rtx_ssrc = prng->Rand(); // Add header extensions. for (unsigned i = 0; i < kNumExtensions; i++) { - if (extensions_bitvector & (1u << i)) { - config->rtp_extensions.push_back( - RtpExtension(kExtensionNames[i], prng->Rand())); + uint8_t id = extensions.GetId(kExtensionTypes[i]); + if (id != RtpHeaderExtensionMap::kInvalidId) { + config->rtp_extensions.emplace_back(kExtensionNames[i], id); } } } -void GenerateAudioReceiveConfig(uint32_t extensions_bitvector, +void GenerateAudioReceiveConfig(const RtpHeaderExtensionMap& extensions, rtclog::StreamConfig* config, Random* prng) { // Add SSRCs for the stream. @@ -199,28 +247,36 @@ void GenerateAudioReceiveConfig(uint32_t extensions_bitvector, config->local_ssrc = prng->Rand(); // Add header extensions. for (unsigned i = 0; i < kNumExtensions; i++) { - if (extensions_bitvector & (1u << i)) { - config->rtp_extensions.push_back( - RtpExtension(kExtensionNames[i], prng->Rand())); + uint8_t id = extensions.GetId(kExtensionTypes[i]); + if (id != RtpHeaderExtensionMap::kInvalidId) { + config->rtp_extensions.emplace_back(kExtensionNames[i], id); } } } -void GenerateAudioSendConfig(uint32_t extensions_bitvector, +void GenerateAudioSendConfig(const RtpHeaderExtensionMap& extensions, rtclog::StreamConfig* config, Random* prng) { // Add SSRC to the stream. config->local_ssrc = prng->Rand(); // Add header extensions. for (unsigned i = 0; i < kNumExtensions; i++) { - if (extensions_bitvector & (1u << i)) { - config->rtp_extensions.push_back( - RtpExtension(kExtensionNames[i], prng->Rand())); + uint8_t id = extensions.GetId(kExtensionTypes[i]); + if (id != RtpHeaderExtensionMap::kInvalidId) { + config->rtp_extensions.emplace_back(kExtensionNames[i], id); } } } -void GenerateAudioNetworkAdaptation(uint32_t extensions_bitvector, +BweLossEvent GenerateBweLossEvent(Random* prng) { + BweLossEvent loss_event; + loss_event.bitrate_bps = prng->Rand(6000, 10000000); + loss_event.fraction_loss = prng->Rand(); + loss_event.total_packets = prng->Rand(1, 1000); + return loss_event; +} + +void GenerateAudioNetworkAdaptation(const RtpHeaderExtensionMap& extensions, AudioEncoderRuntimeConfig* config, Random* prng) { config->bitrate_bps = rtc::Optional(prng->Rand(0, 3000000)); @@ -232,201 +288,414 @@ void GenerateAudioNetworkAdaptation(uint32_t extensions_bitvector, rtc::Optional(prng->Rand()); } -// Test for the RtcEventLog class. Dumps some RTP packets and other events -// to disk, then reads them back to see if they match. -void LogSessionAndReadBack(size_t rtp_count, - size_t rtcp_count, - size_t playout_count, - size_t bwe_loss_count, - uint32_t extensions_bitvector, - uint32_t csrcs_count, - unsigned int random_seed) { - ASSERT_LE(rtcp_count, rtp_count); - ASSERT_LE(playout_count, rtp_count); - ASSERT_LE(bwe_loss_count, rtp_count); - std::vector rtp_packets; - std::vector rtcp_packets; +class RtcEventLogSessionDescription { + public: + explicit RtcEventLogSessionDescription(unsigned int random_seed) + : prng(random_seed) {} + void GenerateSessionDescription(size_t incoming_rtp_count, + size_t outgoing_rtp_count, + size_t incoming_rtcp_count, + size_t outgoing_rtcp_count, + size_t playout_count, + size_t bwe_loss_count, + size_t bwe_delay_count, + const RtpHeaderExtensionMap& extensions, + uint32_t csrcs_count); + void WriteSession(); + void ReadAndVerifySession(); + void PrintExpectedEvents(std::ostream& stream); + + private: + std::vector incoming_rtp_packets; + std::vector outgoing_rtp_packets; + std::vector incoming_rtcp_packets; + std::vector outgoing_rtcp_packets; std::vector playout_ssrcs; - std::vector > bwe_loss_updates; + std::vector bwe_loss_updates; + std::vector > bwe_delay_updates; + std::vector receiver_configs; + std::vector sender_configs; + std::vector event_types; + Random prng; +}; - rtclog::StreamConfig receiver_config; - rtclog::StreamConfig sender_config; +void RtcEventLogSessionDescription::GenerateSessionDescription( + size_t incoming_rtp_count, + size_t outgoing_rtp_count, + size_t incoming_rtcp_count, + size_t outgoing_rtcp_count, + size_t playout_count, + size_t bwe_loss_count, + size_t bwe_delay_count, + const RtpHeaderExtensionMap& extensions, + uint32_t csrcs_count) { + // Create configuration for the video receive stream. + receiver_configs.push_back(rtclog::StreamConfig()); + GenerateVideoReceiveConfig(extensions, &receiver_configs.back(), &prng); + event_types.push_back(EventType::kVideoRecvConfig); - Random prng(random_seed); + // Create configuration for the video send stream. + sender_configs.push_back(rtclog::StreamConfig()); + GenerateVideoSendConfig(extensions, &sender_configs.back(), &prng); + event_types.push_back(EventType::kVideoSendConfig); + const size_t config_count = 2; - // Initialize rtp header extensions to be used in generated rtp packets. - RtpHeaderExtensionMap extensions; - for (unsigned i = 0; i < kNumExtensions; i++) { - if (extensions_bitvector & (1u << i)) { - extensions.Register(kExtensionTypes[i], i + 1); - } - } - // Create rtp_count RTP packets containing random data. - for (size_t i = 0; i < rtp_count; i++) { + // Create incoming and outgoing RTP packets containing random data. + for (size_t i = 0; i < incoming_rtp_count; i++) { size_t packet_size = prng.Rand(1000, 1100); - rtp_packets.push_back( - GenerateRtpPacket(&extensions, csrcs_count, packet_size, &prng)); + incoming_rtp_packets.push_back(GenerateIncomingRtpPacket( + &extensions, csrcs_count, packet_size, &prng)); + event_types.push_back(EventType::kIncomingRtp); } - // Create rtcp_count RTCP packets containing random data. - for (size_t i = 0; i < rtcp_count; i++) { - rtcp_packets.push_back(GenerateRtcpPacket(&prng)); + for (size_t i = 0; i < outgoing_rtp_count; i++) { + size_t packet_size = prng.Rand(1000, 1100); + outgoing_rtp_packets.push_back(GenerateOutgoingRtpPacket( + &extensions, csrcs_count, packet_size, &prng)); + event_types.push_back(EventType::kOutgoingRtp); } - // Create playout_count random SSRCs to use when logging AudioPlayout events. + // Create incoming and outgoing RTCP packets containing random data. + for (size_t i = 0; i < incoming_rtcp_count; i++) { + incoming_rtcp_packets.push_back(GenerateRtcpPacket(&prng)); + event_types.push_back(EventType::kIncomingRtcp); + } + for (size_t i = 0; i < outgoing_rtcp_count; i++) { + outgoing_rtcp_packets.push_back(GenerateRtcpPacket(&prng)); + event_types.push_back(EventType::kOutgoingRtcp); + } + // Create random SSRCs to use when logging AudioPlayout events. for (size_t i = 0; i < playout_count; i++) { playout_ssrcs.push_back(prng.Rand()); + event_types.push_back(EventType::kAudioPlayout); } - // Create bwe_loss_count random bitrate updates for LossBasedBwe. + // Create random bitrate updates for LossBasedBwe. for (size_t i = 0; i < bwe_loss_count; i++) { - bwe_loss_updates.push_back( - std::make_pair(prng.Rand(), prng.Rand())); + bwe_loss_updates.push_back(GenerateBweLossEvent(&prng)); + event_types.push_back(EventType::kBweLossUpdate); + } + // Create random bitrate updates for DelayBasedBwe. + for (size_t i = 0; i < bwe_delay_count; i++) { + bwe_delay_updates.push_back(std::make_pair( + prng.Rand(6000, 10000000), prng.Rand() + ? BandwidthUsage::kBwOverusing + : BandwidthUsage::kBwUnderusing)); + event_types.push_back(EventType::kBweDelayUpdate); } - // Create configurations for the video streams. - GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config, &prng); - GenerateVideoSendConfig(extensions_bitvector, &sender_config, &prng); - const int config_count = 2; + // Order the events randomly. The configurations are stored in a separate + // buffer, so they might be written before any othe events. Hence, we can't + // mix the config events with other events. + for (size_t i = config_count; i < event_types.size(); i++) { + size_t other = prng.Rand(static_cast(i), + static_cast(event_types.size() - 1)); + RTC_CHECK(i <= other && other < event_types.size()); + std::swap(event_types[i], event_types[other]); + } +} + +void RtcEventLogSessionDescription::WriteSession() { // Find the name of the current test, in order to use it as a temporary // filename. auto test_info = ::testing::UnitTest::GetInstance()->current_test_info(); const std::string temp_filename = test::OutputPath() + test_info->test_case_name() + test_info->name(); + rtc::ScopedFakeClock fake_clock; + fake_clock.SetTimeMicros(prng.Rand()); + // When log_dumper goes out of scope, it causes the log file to be flushed // to disk. - { - rtc::ScopedFakeClock fake_clock; - fake_clock.SetTimeMicros(prng.Rand()); - std::unique_ptr log_dumper(RtcEventLog::Create()); - log_dumper->LogVideoReceiveStreamConfig(receiver_config); + std::unique_ptr log_dumper(RtcEventLog::Create()); + + size_t incoming_rtp_written = 0; + size_t outgoing_rtp_written = 0; + size_t incoming_rtcp_written = 0; + size_t outgoing_rtcp_written = 0; + size_t playouts_written = 0; + size_t bwe_loss_written = 0; + size_t bwe_delay_written = 0; + size_t recv_configs_written = 0; + size_t send_configs_written = 0; + + for (size_t i = 0; i < event_types.size(); i++) { fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - log_dumper->LogVideoSendStreamConfig(sender_config); - fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - size_t rtcp_index = 1; - size_t playout_index = 1; - size_t bwe_loss_index = 1; - for (size_t i = 1; i <= rtp_count; i++) { - log_dumper->LogRtpHeader( - (i % 2 == 0) ? kIncomingPacket : kOutgoingPacket, - rtp_packets[i - 1].data(), rtp_packets[i - 1].size()); - fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - if (i * rtcp_count >= rtcp_index * rtp_count) { - log_dumper->LogRtcpPacket( - (rtcp_index % 2 == 0) ? kIncomingPacket : kOutgoingPacket, - rtcp_packets[rtcp_index - 1].data(), - rtcp_packets[rtcp_index - 1].size()); - rtcp_index++; - fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - } - if (i * playout_count >= playout_index * rtp_count) { - log_dumper->LogAudioPlayout(playout_ssrcs[playout_index - 1]); - playout_index++; - fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - } - if (i * bwe_loss_count >= bwe_loss_index * rtp_count) { + if (i == event_types.size() / 2) + log_dumper->StartLogging(temp_filename, 10000000); + switch (event_types[i]) { + case EventType::kIncomingRtp: + RTC_CHECK(incoming_rtp_written < incoming_rtp_packets.size()); + log_dumper->LogIncomingRtpHeader( + incoming_rtp_packets[incoming_rtp_written++]); + break; + case EventType::kOutgoingRtp: + RTC_CHECK(outgoing_rtp_written < outgoing_rtp_packets.size()); + log_dumper->LogOutgoingRtpHeader( + outgoing_rtp_packets[outgoing_rtp_written++], + PacedPacketInfo::kNotAProbe); + break; + case EventType::kIncomingRtcp: + RTC_CHECK(incoming_rtcp_written < incoming_rtcp_packets.size()); + log_dumper->LogIncomingRtcpPacket( + incoming_rtcp_packets[incoming_rtcp_written++]); + break; + case EventType::kOutgoingRtcp: + RTC_CHECK(outgoing_rtcp_written < outgoing_rtcp_packets.size()); + log_dumper->LogOutgoingRtcpPacket( + outgoing_rtcp_packets[outgoing_rtcp_written++]); + break; + case EventType::kAudioPlayout: + RTC_CHECK(playouts_written < playout_ssrcs.size()); + log_dumper->LogAudioPlayout(playout_ssrcs[playouts_written++]); + break; + case EventType::kBweLossUpdate: + RTC_CHECK(bwe_loss_written < bwe_loss_updates.size()); log_dumper->LogLossBasedBweUpdate( - bwe_loss_updates[bwe_loss_index - 1].first, - bwe_loss_updates[bwe_loss_index - 1].second, i); - bwe_loss_index++; - fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - } - if (i == rtp_count / 2) { - log_dumper->StartLogging(temp_filename, 10000000); - fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - } + bwe_loss_updates[bwe_loss_written].bitrate_bps, + bwe_loss_updates[bwe_loss_written].fraction_loss, + bwe_loss_updates[bwe_loss_written].total_packets); + bwe_loss_written++; + break; + case EventType::kBweDelayUpdate: + RTC_CHECK(bwe_delay_written < bwe_delay_updates.size()); + log_dumper->LogDelayBasedBweUpdate( + bwe_delay_updates[bwe_delay_written].first, + bwe_delay_updates[bwe_delay_written].second); + bwe_delay_written++; + break; + case EventType::kVideoRecvConfig: + RTC_CHECK(recv_configs_written < receiver_configs.size()); + log_dumper->LogVideoReceiveStreamConfig( + receiver_configs[recv_configs_written++]); + break; + case EventType::kVideoSendConfig: + RTC_CHECK(send_configs_written < sender_configs.size()); + log_dumper->LogVideoSendStreamConfig( + sender_configs[send_configs_written++]); + break; + case EventType::kAudioRecvConfig: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kAudioSendConfig: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kAudioNetworkAdaptation: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kBweProbeClusterCreated: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kBweProbeResult: + // Not implemented + RTC_NOTREACHED(); + break; } - log_dumper->StopLogging(); } + log_dumper->StopLogging(); +} + +// Read the file and verify that what we read back from the event log is the +// same as what we wrote down. +void RtcEventLogSessionDescription::ReadAndVerifySession() { + // Find the name of the current test, in order to use it as a temporary + // filename. + auto test_info = ::testing::UnitTest::GetInstance()->current_test_info(); + const std::string temp_filename = + test::OutputPath() + test_info->test_case_name() + test_info->name(); + // Read the generated file from disk. ParsedRtcEventLog parsed_log; - ASSERT_TRUE(parsed_log.ParseFile(temp_filename)); + EXPECT_GE(1000u, event_types.size() + + 2); // The events must fit in the message queue. + EXPECT_EQ(event_types.size() + 2, parsed_log.GetNumberOfEvents()); + + size_t incoming_rtp_read = 0; + size_t outgoing_rtp_read = 0; + size_t incoming_rtcp_read = 0; + size_t outgoing_rtcp_read = 0; + size_t playouts_read = 0; + size_t bwe_loss_read = 0; + size_t bwe_delay_read = 0; + size_t recv_configs_read = 0; + size_t send_configs_read = 0; - // Verify that what we read back from the event log is the same as - // what we wrote down. For RTCP we log the full packets, but for - // RTP we should only log the header. - const size_t event_count = config_count + playout_count + bwe_loss_count + - rtcp_count + rtp_count + 2; - EXPECT_GE(1000u, event_count); // The events must fit in the message queue. - EXPECT_EQ(event_count, parsed_log.GetNumberOfEvents()); - if (event_count != parsed_log.GetNumberOfEvents()) { - // Print the expected and actual event types for easier debugging. - PrintActualEvents(parsed_log); - PrintExpectedEvents(rtp_count, rtcp_count, playout_count, bwe_loss_count); - } RtcEventLogTestHelper::VerifyLogStartEvent(parsed_log, 0); - RtcEventLogTestHelper::VerifyVideoReceiveStreamConfig(parsed_log, 1, - receiver_config); - RtcEventLogTestHelper::VerifyVideoSendStreamConfig(parsed_log, 2, - sender_config); - size_t event_index = config_count + 1; - size_t rtcp_index = 1; - size_t playout_index = 1; - size_t bwe_loss_index = 1; - for (size_t i = 1; i <= rtp_count; i++) { - RtcEventLogTestHelper::VerifyRtpEvent( - parsed_log, event_index, - (i % 2 == 0) ? kIncomingPacket : kOutgoingPacket, - rtp_packets[i - 1].data(), rtp_packets[i - 1].headers_size(), - rtp_packets[i - 1].size()); - event_index++; - if (i * rtcp_count >= rtcp_index * rtp_count) { - RtcEventLogTestHelper::VerifyRtcpEvent( - parsed_log, event_index, - rtcp_index % 2 == 0 ? kIncomingPacket : kOutgoingPacket, - rtcp_packets[rtcp_index - 1].data(), - rtcp_packets[rtcp_index - 1].size()); - event_index++; - rtcp_index++; - } - if (i * playout_count >= playout_index * rtp_count) { - RtcEventLogTestHelper::VerifyPlayoutEvent( - parsed_log, event_index, playout_ssrcs[playout_index - 1]); - event_index++; - playout_index++; - } - if (i * bwe_loss_count >= bwe_loss_index * rtp_count) { - RtcEventLogTestHelper::VerifyBweLossEvent( - parsed_log, event_index, bwe_loss_updates[bwe_loss_index - 1].first, - bwe_loss_updates[bwe_loss_index - 1].second, i); - event_index++; - bwe_loss_index++; + + for (size_t i = 0; i < event_types.size(); i++) { + switch (event_types[i]) { + case EventType::kIncomingRtp: + RTC_CHECK(incoming_rtp_read < incoming_rtp_packets.size()); + RtcEventLogTestHelper::VerifyIncomingRtpEvent( + parsed_log, i + 1, incoming_rtp_packets[incoming_rtp_read++]); + break; + case EventType::kOutgoingRtp: + RTC_CHECK(outgoing_rtp_read < outgoing_rtp_packets.size()); + RtcEventLogTestHelper::VerifyOutgoingRtpEvent( + parsed_log, i + 1, outgoing_rtp_packets[outgoing_rtp_read++]); + break; + case EventType::kIncomingRtcp: + RTC_CHECK(incoming_rtcp_read < incoming_rtcp_packets.size()); + RtcEventLogTestHelper::VerifyRtcpEvent( + parsed_log, i + 1, kIncomingPacket, + incoming_rtcp_packets[incoming_rtcp_read].data(), + incoming_rtcp_packets[incoming_rtcp_read].size()); + incoming_rtcp_read++; + break; + case EventType::kOutgoingRtcp: + RTC_CHECK(outgoing_rtcp_read < outgoing_rtcp_packets.size()); + RtcEventLogTestHelper::VerifyRtcpEvent( + parsed_log, i + 1, kOutgoingPacket, + outgoing_rtcp_packets[outgoing_rtcp_read].data(), + outgoing_rtcp_packets[outgoing_rtcp_read].size()); + outgoing_rtcp_read++; + break; + case EventType::kAudioPlayout: + RTC_CHECK(playouts_read < playout_ssrcs.size()); + RtcEventLogTestHelper::VerifyPlayoutEvent( + parsed_log, i + 1, playout_ssrcs[playouts_read++]); + break; + case EventType::kBweLossUpdate: + RTC_CHECK(bwe_loss_read < bwe_loss_updates.size()); + RtcEventLogTestHelper::VerifyBweLossEvent( + parsed_log, i + 1, bwe_loss_updates[bwe_loss_read].bitrate_bps, + bwe_loss_updates[bwe_loss_read].fraction_loss, + bwe_loss_updates[bwe_loss_read].total_packets); + bwe_loss_read++; + break; + case EventType::kBweDelayUpdate: + RTC_CHECK(bwe_delay_read < bwe_delay_updates.size()); + RtcEventLogTestHelper::VerifyBweDelayEvent( + parsed_log, i + 1, bwe_delay_updates[bwe_delay_read].first, + bwe_delay_updates[bwe_delay_read].second); + bwe_delay_read++; + break; + case EventType::kVideoRecvConfig: + RTC_CHECK(recv_configs_read < receiver_configs.size()); + RtcEventLogTestHelper::VerifyVideoReceiveStreamConfig( + parsed_log, i + 1, receiver_configs[recv_configs_read++]); + break; + case EventType::kVideoSendConfig: + RTC_CHECK(send_configs_read < sender_configs.size()); + RtcEventLogTestHelper::VerifyVideoSendStreamConfig( + parsed_log, i + 1, sender_configs[send_configs_read++]); + break; + case EventType::kAudioRecvConfig: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kAudioSendConfig: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kAudioNetworkAdaptation: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kBweProbeClusterCreated: + // Not implemented + RTC_NOTREACHED(); + break; + case EventType::kBweProbeResult: + // Not implemented + RTC_NOTREACHED(); + break; } } + RtcEventLogTestHelper::VerifyLogEndEvent(parsed_log, + parsed_log.GetNumberOfEvents() - 1); + // Clean up temporary file - can be pretty slow. remove(temp_filename.c_str()); } -TEST(RtcEventLogTest, LogSessionAndReadBack) { - // Log 5 RTP, 2 RTCP, 0 playout events and 0 BWE events - // with no header extensions or CSRCS. - LogSessionAndReadBack(5, 2, 0, 0, 0, 0, 321); - - // Enable AbsSendTime and TransportSequenceNumbers. - uint32_t extensions = 0; - for (uint32_t i = 0; i < kNumExtensions; i++) { - if (kExtensionTypes[i] == RTPExtensionType::kRtpExtensionAbsoluteSendTime || - kExtensionTypes[i] == - RTPExtensionType::kRtpExtensionTransportSequenceNumber) { - extensions |= 1u << i; - } +void RtcEventLogSessionDescription::PrintExpectedEvents(std::ostream& stream) { + for (size_t i = 0; i < event_types.size(); i++) { + auto it = event_type_to_string.find(event_types[i]); + RTC_CHECK(it != event_type_to_string.end()); + stream << it->second << " "; } - LogSessionAndReadBack(8, 2, 0, 0, extensions, 0, 3141592653u); + stream << std::endl; +} - extensions = (1u << kNumExtensions) - 1; // Enable all header extensions. - LogSessionAndReadBack(9, 2, 3, 2, extensions, 2, 2718281828u); +void PrintActualEvents(const ParsedRtcEventLog& parsed_log, + std::ostream& stream) { + for (size_t i = 0; i < parsed_log.GetNumberOfEvents(); i++) { + auto it = parsed_event_type_to_string.find(parsed_log.GetEventType(i)); + RTC_CHECK(it != parsed_event_type_to_string.end()); + stream << it->second << " "; + } + stream << std::endl; +} +TEST(RtcEventLogTest, LogSessionAndReadBack) { + RtpHeaderExtensionMap extensions; + RtcEventLogSessionDescription session(321 /*Random seed*/); + session.GenerateSessionDescription(3, // Number of incoming RTP packets. + 2, // Number of outgoing RTP packets. + 1, // Number of incoming RTCP packets. + 1, // Number of outgoing RTCP packets. + 0, // Number of playout events. + 0, // Number of BWE loss events. + 0, // Number of BWE delay events. + extensions, // No extensions. + 0); // Number of contributing sources. + session.WriteSession(); + session.ReadAndVerifySession(); +} + +TEST(RtcEventLogTest, LogSessionAndReadBackWith2Extensions) { + RtpHeaderExtensionMap extensions; + extensions.Register(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId); + extensions.Register(kRtpExtensionTransportSequenceNumber, + kTransportSequenceNumberExtensionId); + RtcEventLogSessionDescription session(3141592653u /*Random seed*/); + session.GenerateSessionDescription(4, 4, 1, 1, 0, 0, 0, extensions, 0); + session.WriteSession(); + session.ReadAndVerifySession(); +} + +TEST(RtcEventLogTest, LogSessionAndReadBackWithAllExtensions) { + RtpHeaderExtensionMap extensions; + for (uint32_t i = 0; i < kNumExtensions; i++) { + extensions.Register(kExtensionTypes[i], kExtensionIds[i]); + } + RtcEventLogSessionDescription session(2718281828u /*Random seed*/); + session.GenerateSessionDescription(5, 4, 1, 1, 3, 2, 2, extensions, 2); + session.WriteSession(); + session.ReadAndVerifySession(); +} + +TEST(RtcEventLogTest, LogSessionAndReadBackAllCombinations) { // Try all combinations of header extensions and up to 2 CSRCS. - for (extensions = 0; extensions < (1u << kNumExtensions); extensions++) { + for (uint32_t extension_selection = 0; + extension_selection < (1u << kNumExtensions); extension_selection++) { + RtpHeaderExtensionMap extensions; + for (uint32_t i = 0; i < kNumExtensions; i++) { + if (extension_selection & (1u << i)) { + extensions.Register(kExtensionTypes[i], kExtensionIds[i]); + } + } for (uint32_t csrcs_count = 0; csrcs_count < 3; csrcs_count++) { - LogSessionAndReadBack(5 + extensions, // Number of RTP packets. - 2 + csrcs_count, // Number of RTCP packets. - 3 + csrcs_count, // Number of playout events. - 1 + csrcs_count, // Number of BWE loss events. - extensions, // Bit vector choosing extensions. - csrcs_count, // Number of contributing sources. - extensions * 3 + csrcs_count + 1); // Random seed. + RtcEventLogSessionDescription session(extension_selection * 3 + + csrcs_count + 1 /*Random seed*/); + session.GenerateSessionDescription( + 2 + extension_selection, // Number of incoming RTP packets. + 2 + extension_selection, // Number of outgoing RTP packets. + 1 + csrcs_count, // Number of incoming RTCP packets. + 1 + csrcs_count, // Number of outgoing RTCP packets. + 3 + csrcs_count, // Number of playout events. + 1 + csrcs_count, // Number of BWE loss events. + 2 + csrcs_count, // Number of BWE delay events. + extensions, // Bit vector choosing extensions. + csrcs_count); // Number of contributing sources. + session.WriteSession(); + session.ReadAndVerifySession(); } } } @@ -436,8 +705,8 @@ TEST(RtcEventLogTest, LogEventAndReadBack) { // Create one RTP and one RTCP packet containing random data. size_t packet_size = prng.Rand(1000, 1100); - RtpPacketToSend rtp_packet = - GenerateRtpPacket(nullptr, 0, packet_size, &prng); + RtpPacketReceived rtp_packet = + GenerateIncomingRtpPacket(nullptr, 0, packet_size, &prng); rtc::Buffer rtcp_packet = GenerateRtcpPacket(&prng); // Find the name of the current test, in order to use it as a temporary @@ -451,15 +720,13 @@ TEST(RtcEventLogTest, LogEventAndReadBack) { fake_clock.SetTimeMicros(prng.Rand()); std::unique_ptr log_dumper(RtcEventLog::Create()); - log_dumper->LogRtpHeader(kIncomingPacket, rtp_packet.data(), - rtp_packet.size()); + log_dumper->LogIncomingRtpHeader(rtp_packet); fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); log_dumper->StartLogging(temp_filename, 10000000); fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); - log_dumper->LogRtcpPacket(kOutgoingPacket, rtcp_packet.data(), - rtcp_packet.size()); + log_dumper->LogOutgoingRtcpPacket(rtcp_packet); fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000)); log_dumper->StopLogging(); @@ -474,9 +741,7 @@ TEST(RtcEventLogTest, LogEventAndReadBack) { RtcEventLogTestHelper::VerifyLogStartEvent(parsed_log, 0); - RtcEventLogTestHelper::VerifyRtpEvent( - parsed_log, 1, kIncomingPacket, rtp_packet.data(), - rtp_packet.headers_size(), rtp_packet.size()); + RtcEventLogTestHelper::VerifyIncomingRtpEvent(parsed_log, 1, rtp_packet); RtcEventLogTestHelper::VerifyRtcpEvent( parsed_log, 2, kOutgoingPacket, rtcp_packet.data(), rtcp_packet.size()); @@ -721,7 +986,7 @@ class ConfigReadWriteTest { public: ConfigReadWriteTest() : prng(987654321) {} virtual ~ConfigReadWriteTest() {} - virtual void GenerateConfig(uint32_t extensions_bitvector) = 0; + virtual void GenerateConfig(const RtpHeaderExtensionMap& extensions) = 0; virtual void VerifyConfig(const ParsedRtcEventLog& parsed_log, size_t index) = 0; virtual void LogConfig(RtcEventLog* event_log) = 0; @@ -734,8 +999,11 @@ class ConfigReadWriteTest { test::OutputPath() + test_info->test_case_name() + test_info->name(); // Use all extensions. - uint32_t extensions_bitvector = (1u << kNumExtensions) - 1; - GenerateConfig(extensions_bitvector); + RtpHeaderExtensionMap extensions; + for (uint32_t i = 0; i < kNumExtensions; i++) { + extensions.Register(kExtensionTypes[i], kExtensionIds[i]); + } + GenerateConfig(extensions); // Log a single config event and stop logging. rtc::ScopedFakeClock fake_clock; @@ -768,8 +1036,8 @@ class ConfigReadWriteTest { class AudioReceiveConfigReadWriteTest : public ConfigReadWriteTest { public: - void GenerateConfig(uint32_t extensions_bitvector) override { - GenerateAudioReceiveConfig(extensions_bitvector, &config, &prng); + void GenerateConfig(const RtpHeaderExtensionMap& extensions) override { + GenerateAudioReceiveConfig(extensions, &config, &prng); } void LogConfig(RtcEventLog* event_log) override { event_log->LogAudioReceiveStreamConfig(config); @@ -785,8 +1053,8 @@ class AudioReceiveConfigReadWriteTest : public ConfigReadWriteTest { class AudioSendConfigReadWriteTest : public ConfigReadWriteTest { public: AudioSendConfigReadWriteTest() {} - void GenerateConfig(uint32_t extensions_bitvector) override { - GenerateAudioSendConfig(extensions_bitvector, &config, &prng); + void GenerateConfig(const RtpHeaderExtensionMap& extensions) override { + GenerateAudioSendConfig(extensions, &config, &prng); } void LogConfig(RtcEventLog* event_log) override { event_log->LogAudioSendStreamConfig(config); @@ -802,8 +1070,8 @@ class AudioSendConfigReadWriteTest : public ConfigReadWriteTest { class VideoReceiveConfigReadWriteTest : public ConfigReadWriteTest { public: VideoReceiveConfigReadWriteTest() {} - void GenerateConfig(uint32_t extensions_bitvector) override { - GenerateVideoReceiveConfig(extensions_bitvector, &config, &prng); + void GenerateConfig(const RtpHeaderExtensionMap& extensions) override { + GenerateVideoReceiveConfig(extensions, &config, &prng); } void LogConfig(RtcEventLog* event_log) override { event_log->LogVideoReceiveStreamConfig(config); @@ -819,8 +1087,8 @@ class VideoReceiveConfigReadWriteTest : public ConfigReadWriteTest { class VideoSendConfigReadWriteTest : public ConfigReadWriteTest { public: VideoSendConfigReadWriteTest() {} - void GenerateConfig(uint32_t extensions_bitvector) override { - GenerateVideoSendConfig(extensions_bitvector, &config, &prng); + void GenerateConfig(const RtpHeaderExtensionMap& extensions) override { + GenerateVideoSendConfig(extensions, &config, &prng); } void LogConfig(RtcEventLog* event_log) override { event_log->LogVideoSendStreamConfig(config); @@ -835,8 +1103,8 @@ class VideoSendConfigReadWriteTest : public ConfigReadWriteTest { class AudioNetworkAdaptationReadWriteTest : public ConfigReadWriteTest { public: - void GenerateConfig(uint32_t extensions_bitvector) override { - GenerateAudioNetworkAdaptation(extensions_bitvector, &config, &prng); + void GenerateConfig(const RtpHeaderExtensionMap& extensions) override { + GenerateAudioNetworkAdaptation(extensions, &config, &prng); } void LogConfig(RtcEventLog* event_log) override { event_log->LogAudioNetworkAdaptation(config); diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc index 972411a836..ed9cab1590 100644 --- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc +++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc @@ -18,6 +18,7 @@ #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/checks.h" +#include "test/gmock.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" @@ -349,25 +350,23 @@ void RtcEventLogTestHelper::VerifyAudioSendStreamConfig( VerifyStreamConfigsAreEqual(config, parsed_config); } -void RtcEventLogTestHelper::VerifyRtpEvent(const ParsedRtcEventLog& parsed_log, - size_t index, - PacketDirection direction, - const uint8_t* header, - size_t header_size, - size_t total_size) { +void RtcEventLogTestHelper::VerifyIncomingRtpEvent( + const ParsedRtcEventLog& parsed_log, + size_t index, + const RtpPacketReceived& expected_packet) { const rtclog::Event& event = parsed_log.events_[index]; ASSERT_TRUE(IsValidBasicEvent(event)); ASSERT_EQ(rtclog::Event::RTP_EVENT, event.type()); const rtclog::RtpPacket& rtp_packet = event.rtp_packet(); ASSERT_TRUE(rtp_packet.has_incoming()); - EXPECT_EQ(direction == kIncomingPacket, rtp_packet.incoming()); + EXPECT_TRUE(rtp_packet.incoming()); ASSERT_TRUE(rtp_packet.has_packet_length()); - EXPECT_EQ(total_size, rtp_packet.packet_length()); + EXPECT_EQ(expected_packet.size(), rtp_packet.packet_length()); + size_t header_size = expected_packet.headers_size(); ASSERT_TRUE(rtp_packet.has_header()); - ASSERT_EQ(header_size, rtp_packet.header().size()); - for (size_t i = 0; i < header_size; i++) { - EXPECT_EQ(header[i], static_cast(rtp_packet.header()[i])); - } + EXPECT_THAT(testing::make_tuple(expected_packet.data(), header_size), + testing::ElementsAreArray(rtp_packet.header().data(), + rtp_packet.header().size())); // Check consistency of the parser. PacketDirection parsed_direction; @@ -375,10 +374,40 @@ void RtcEventLogTestHelper::VerifyRtpEvent(const ParsedRtcEventLog& parsed_log, size_t parsed_header_size, parsed_total_size; parsed_log.GetRtpHeader(index, &parsed_direction, parsed_header, &parsed_header_size, &parsed_total_size); - EXPECT_EQ(direction, parsed_direction); - ASSERT_EQ(header_size, parsed_header_size); - EXPECT_EQ(0, std::memcmp(header, parsed_header, header_size)); - EXPECT_EQ(total_size, parsed_total_size); + EXPECT_EQ(kIncomingPacket, parsed_direction); + EXPECT_THAT(testing::make_tuple(expected_packet.data(), header_size), + testing::ElementsAreArray(parsed_header, parsed_header_size)); + EXPECT_EQ(expected_packet.size(), parsed_total_size); +} + +void RtcEventLogTestHelper::VerifyOutgoingRtpEvent( + const ParsedRtcEventLog& parsed_log, + size_t index, + const RtpPacketToSend& expected_packet) { + const rtclog::Event& event = parsed_log.events_[index]; + ASSERT_TRUE(IsValidBasicEvent(event)); + ASSERT_EQ(rtclog::Event::RTP_EVENT, event.type()); + const rtclog::RtpPacket& rtp_packet = event.rtp_packet(); + ASSERT_TRUE(rtp_packet.has_incoming()); + EXPECT_FALSE(rtp_packet.incoming()); + ASSERT_TRUE(rtp_packet.has_packet_length()); + EXPECT_EQ(expected_packet.size(), rtp_packet.packet_length()); + size_t header_size = expected_packet.headers_size(); + ASSERT_TRUE(rtp_packet.has_header()); + EXPECT_THAT(testing::make_tuple(expected_packet.data(), header_size), + testing::ElementsAreArray(rtp_packet.header().data(), + rtp_packet.header().size())); + + // Check consistency of the parser. + PacketDirection parsed_direction; + uint8_t parsed_header[1500]; + size_t parsed_header_size, parsed_total_size; + parsed_log.GetRtpHeader(index, &parsed_direction, parsed_header, + &parsed_header_size, &parsed_total_size); + EXPECT_EQ(kOutgoingPacket, parsed_direction); + EXPECT_THAT(testing::make_tuple(expected_packet.data(), header_size), + testing::ElementsAreArray(parsed_header, parsed_header_size)); + EXPECT_EQ(expected_packet.size(), parsed_total_size); } void RtcEventLogTestHelper::VerifyRtcpEvent(const ParsedRtcEventLog& parsed_log, diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/logging/rtc_event_log/rtc_event_log_unittest_helper.h index 29031ed5f9..630f160a18 100644 --- a/logging/rtc_event_log/rtc_event_log_unittest_helper.h +++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.h @@ -13,6 +13,8 @@ #include "call/call.h" #include "logging/rtc_event_log/rtc_event_log_parser.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" namespace webrtc { @@ -32,12 +34,12 @@ class RtcEventLogTestHelper { static void VerifyAudioSendStreamConfig(const ParsedRtcEventLog& parsed_log, size_t index, const rtclog::StreamConfig& config); - static void VerifyRtpEvent(const ParsedRtcEventLog& parsed_log, - size_t index, - PacketDirection direction, - const uint8_t* header, - size_t header_size, - size_t total_size); + static void VerifyIncomingRtpEvent(const ParsedRtcEventLog& parsed_log, + size_t index, + const RtpPacketReceived& expected_packet); + static void VerifyOutgoingRtpEvent(const ParsedRtcEventLog& parsed_log, + size_t index, + const RtpPacketToSend& expected_packet); static void VerifyRtcpEvent(const ParsedRtcEventLog& parsed_log, size_t index, PacketDirection direction, diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc index 9145bbce16..c7e75b67e7 100644 --- a/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/modules/rtp_rtcp/source/rtcp_sender.cc @@ -99,7 +99,8 @@ class PacketContainer : public rtcp::CompoundPacket, if (transport_->SendRtcp(data, length)) { bytes_sent_ += length; if (event_log_) { - event_log_->LogRtcpPacket(kOutgoingPacket, data, length); + event_log_->LogOutgoingRtcpPacket( + rtc::ArrayView(data, length)); } } } @@ -962,7 +963,8 @@ bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) { void OnPacketReady(uint8_t* data, size_t length) override { if (transport_->SendRtcp(data, length)) { if (event_log_) { - event_log_->LogRtcpPacket(kOutgoingPacket, data, length); + event_log_->LogOutgoingRtcpPacket( + rtc::ArrayView(data, length)); } } else { send_failure_ = true; diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index 1a47d97ece..34af1cbcb0 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -644,8 +644,7 @@ bool RTPSender::SendPacketToNetwork(const RtpPacketToSend& packet, ? static_cast(packet.size()) : -1; if (event_log_ && bytes_sent > 0) { - event_log_->LogRtpHeader(kOutgoingPacket, packet.data(), packet.size(), - pacing_info.probe_cluster_id); + event_log_->LogOutgoingRtpHeader(packet, pacing_info.probe_cluster_id); } } TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc index 858c308346..e40406cb3b 100644 --- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -530,8 +530,7 @@ TEST_P(RtpSenderTestWithoutPacer, WritesTimestampToTimingExtension) { TEST_P(RtpSenderTest, TrafficSmoothingWithExtensions) { EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority, kSsrc, kSeqNum, _, _, _)); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)); + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)); rtp_sender_->SetStorePacketsStatus(true, 10); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( @@ -575,8 +574,7 @@ TEST_P(RtpSenderTest, TrafficSmoothingWithExtensions) { TEST_P(RtpSenderTest, TrafficSmoothingRetransmits) { EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority, kSsrc, kSeqNum, _, _, _)); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)); + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)); rtp_sender_->SetStorePacketsStatus(true, 10); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( @@ -629,9 +627,7 @@ TEST_P(RtpSenderTest, SendPadding) { // Make all (non-padding) packets go to send queue. EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority, kSsrc, kSeqNum, _, _, _)); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) - .Times(1 + 4 + 1); + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)).Times(1 + 4 + 1); uint16_t seq_num = kSeqNum; uint32_t timestamp = kTimestamp; @@ -830,8 +826,7 @@ TEST_P(RtpSenderTest, SendRedundantPayloads) { EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority, kSsrc, _, _, _, _)) .Times(kNumPayloadSizes); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)) .Times(kNumPayloadSizes); // Send 10 packets of increasing size. @@ -844,8 +839,7 @@ TEST_P(RtpSenderTest, SendRedundantPayloads) { fake_clock_.AdvanceTimeMilliseconds(33); } - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)) .Times(::testing::AtLeast(4)); // The amount of padding to send it too small to send a payload packet. @@ -941,9 +935,7 @@ TEST_P(RtpSenderTest, SendFlexfecPackets) { kFlexfecSsrc, _, _, _, false)) .WillOnce(testing::SaveArg<2>(&flexfec_seq_num)); SendGenericPayload(); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) - .Times(2); + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)).Times(2); EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum, fake_clock_.TimeInMilliseconds(), false, PacedPacketInfo())); @@ -1018,9 +1010,7 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) { sizeof(kPayloadData), nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs)); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) - .Times(1); + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)).Times(1); EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum, fake_clock_.TimeInMilliseconds(), false, PacedPacketInfo())); @@ -1044,9 +1034,7 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) { kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs)); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) - .Times(2); + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)).Times(2); EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum + 1, fake_clock_.TimeInMilliseconds(), false, PacedPacketInfo())); @@ -1092,9 +1080,7 @@ TEST_P(RtpSenderTestWithoutPacer, SendFlexfecPackets) { params.fec_mask_type = kFecMaskRandom; rtp_sender_->SetFecParameters(params, params); - EXPECT_CALL(mock_rtc_event_log_, - LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) - .Times(2); + EXPECT_CALL(mock_rtc_event_log_, LogOutgoingRtpHeader(_, _)).Times(2); SendGenericPayload(); ASSERT_EQ(2, transport_.packets_sent()); const RtpPacketReceived& media_packet = transport_.sent_packets_[0]; diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc index 5fa7973b49..aab292b9e0 100644 --- a/voice_engine/channel.cc +++ b/voice_engine/channel.cc @@ -11,7 +11,10 @@ #include "voice_engine/channel.h" #include +#include +#include #include +#include #include "api/array_view.h" #include "audio/utility/audio_frame_operations.h" @@ -98,29 +101,32 @@ class RtcEventLogProxy final : public webrtc::RtcEventLog { } } - void LogRtpHeader(webrtc::PacketDirection direction, - const uint8_t* header, - size_t packet_length) override { - LogRtpHeader(direction, header, packet_length, PacedPacketInfo::kNotAProbe); - } - - void LogRtpHeader(webrtc::PacketDirection direction, - const uint8_t* header, - size_t packet_length, - int probe_cluster_id) override { + void LogIncomingRtpHeader(const RtpPacketReceived& packet) override { rtc::CritScope lock(&crit_); if (event_log_) { - event_log_->LogRtpHeader(direction, header, packet_length, - probe_cluster_id); + event_log_->LogIncomingRtpHeader(packet); } } - void LogRtcpPacket(webrtc::PacketDirection direction, - const uint8_t* packet, - size_t length) override { + void LogOutgoingRtpHeader(const RtpPacketToSend& packet, + int probe_cluster_id) override { rtc::CritScope lock(&crit_); if (event_log_) { - event_log_->LogRtcpPacket(direction, packet, length); + event_log_->LogOutgoingRtpHeader(packet, probe_cluster_id); + } + } + + void LogIncomingRtcpPacket(rtc::ArrayView packet) override { + rtc::CritScope lock(&crit_); + if (event_log_) { + event_log_->LogIncomingRtcpPacket(packet); + } + } + + void LogOutgoingRtcpPacket(rtc::ArrayView packet) override { + rtc::CritScope lock(&crit_); + if (event_log_) { + event_log_->LogOutgoingRtcpPacket(packet); } }